allegro-4.4.3.1/0000775000175000017500000000000013437077703012275 5ustar siegesiegeallegro-4.4.3.1/modules.lst0000664000175000017500000000034713437077643014500 0ustar siegesiege# List of modules to be loaded by the Unix version of Allegro. alleg-vga.so alleg-fbcon.so alleg-svgalib.so alleg-dga2.so alleg-esddigi.so alleg-artsdigi.so alleg-sgialdigi.so alleg-alsadigi.so alleg-alsamidi.so alleg-jackdigi.so allegro-4.4.3.1/indent.pro0000664000175000017500000000004113437077643014276 0ustar siegesiege-kr -nce -ss -ncs -i3 -cli3 -nut allegro-4.4.3.1/todo.txt0000664000175000017500000001626013437077643014013 0ustar siegesiege--------------------------------------------------------------------------- This is the public TODO list for the Allegro Game/Multimedia Library. --------------------------------------------------------------------------- Updates or comments can be sent to the Allegro developer's mailing list , preferrably with the text [TODO] in the subject. 4.2.1 todos: --------------------------------------------------------------------------- - Investigate video bitmap problems reported in http://www.allegro.cc/forums/view_thread.php?_id=453220 - Investigate mouse problem reported in http://www.allegro.cc/forums/view_thread.php?_id=459972 - Mouse problems in Windows reported in http://www.allegro.cc/forums/view_thread.php?_id=497651 - Make the grabber (try to) use system cursors - Purge main docs of DOSisms if that hasn't been done already - some gcc 4.0 fixes for DJGPP and MinGW need to be applied - some remaining problem with keyboards in Windows http://www.allegro.cc/forums/view_thread.php?_id=484193 http://www.allegro.cc/forums/view_thread.php?_id=493712 - configure/OSS detection problems on Solaris - guilt's patches - settings CFLAGS from configure, http://bugs.gentoo.org/show_bug.cgi?id=90049 - grabber.txt was moved, so the grabber can't find it anymore - improved demo - if we keep the old demo, make it show correct characters with accents or upgrade font (reported by Marcio Fialho) - MacOS X problems with 8-bit mode, http://www.allegro.cc/forums/view_thread.php?_id=517057 - 64-bit portability warnings with MSVC7.1, http://www.allegro.cc/forums/view_thread.php?_id=523945 - DirectInput joystick bug, http://www.allegro.cc/forums/view_thread.php?_id=507375 - Allegro loses keyboard focus on opening, http://www.allegro.cc/forums/view_thread.php?_id=551330 - fbcon driver doesn't restore original resolution - fbcon driver requires 2 video mode sets to change the resolution, [AD] 2005-11-08 "fbcon directcolor modes patch" - disable or embed .manifest files when using MSVC 8, http://www.allegro.cc/forums/view_thread.php?_id=543226&page=2 - make the evdev driver the default linux mouse driver - fix mouse coordinates in GFX_DIRECTX_WIN, [AD] 2005-12-09 "Inconsistent behaviour with mouse coordinates in different windowed modes in Windows." - add is_mouse_inside_window() function General (Platform independent) todos: --------------------------------------------------------------------------- - make the library internally thread-safe - The dependency generation seems to be quite broken, and far more complicated than necessary. Remove all the misc/dep*scripts, and simply call "gcc -M" on every source file. - Investigate making the mixer mutex globally accessible, and add locking e.g. to set_volume DOS todos: --------------------------------------------------------------------------- - Write a unified Sidewinder driver - Fix buggy dos/wss.c - grabber compiled with bcc32 5.5.1 crashes on exit in release mode, but not debug mode Win32 todos: --------------------------------------------------------------------------- - Add a configuration option to specify the monitor on multi-monitor systems - Re-enable docs build with a MinGW cross-compiler - Investigate Alt+Tab pop-up window being overdrawn in windowed mode - Investigate problem with keyboard in the dxwindow test - Modify convert_hbitmap_to_bitmap() behaviour with 8-bit DDBs Linux todos: --------------------------------------------------------------------------- - fix fb 24-bit scrolling (allegro presuming padding?) - awaiting svgalib folks to provide an atexit-free vga_init [forget it, svgalib is dead] - make at least one sound driver take advantage of multiple hardware voices X11 todos: --------------------------------------------------------------------------- - Investigate problems with the SIGALRM version - Investigate fullscreen without XVidMode if the desktop already has the right mode: http://www.allegro.cc/forums/thread/561876 - Investigate quadruple color lookup in X11 color converter: http://www.allegro.cc/forums/thread/561876 Unix todos: --------------------------------------------------------------------------- - tidy up the configure machinery - implement load-on-demand for modules - fix modules support on IRIX (export-dynamic is ignored) - fix problem with alunixac.h #defines leaking into user programs MacOS X todos --------------------------------------------------------------------------- - asm routines (altivec?) to speed things up - Mac default installation path? BeOS todos: --------------------------------------------------------------------------- - Launching programs from the Be menu still doesn't work (Tracker works though) QNX todos: --------------------------------------------------------------------------- - Display switching in fullscreen mode - Overlay gfx driver Wishlist: --------------------------------------------------------------------------- - polygon() should draw bottom pixels. I.e. polygon() with 4 points should produce the same shape as rectfill() (http://www.allegro.cc/forums/view_thread.php?_id=480867) - ellipse/circle should use a better algorithm to give a uniform outline, not the current "crispy" look (in fact, it's just very inaccurate). And there should be a way to have even width ellipses. (http://www.allegro.cc/forums/view_thread.php?_id=483211) - Variable line thickness on graphics primitives - OSS MIDI pitch bend is wrong - size_t where appropriate (get more opinions first) - keyboard set_rate - More hardware accelerated functions? Trans/lit sprites come to mind. - framebuffer hardware accel via XFB or DirectFB (?) library/driver - implementation of request_refresh_rate for fbdev, since apparently you can set video modes with a great detail (scanlines, memory, etc). - Better get_config_text support, with multiple fallback configuration files (you can have lot's of them under linux), which is not supported at the moment (IIRC two at most). - Split setup in two: user program and configuration library. This would allow easier merge process of configuration program into real user programs, as well as modifying the interface and "look'n'feel". The lib should be written in such a way to support future additions without the need of rewritting the user setup ui. - hook function to handle window resizing - DirectMusic 6 MIDI driver - more modularity under Linux - Threaded Alsa driver, since the current one doesn't work properly for at least one person. - Speed up the X11 driver, so it is comparable to SDL in performance. - Add an option to the X11 driver to use the current palette in 8-bit mode. - Disable screensaver in X11, as the Windows port does currently. - Make (at least truecolor) mask color modifyable. Makedoc wishlist: --------------------------------------------------------------------------- - Add shortdesc support for makeinfo. - Make makeinfo spit out a "detailed node listing" after the short one, like many other info manuals (like GNU make). - Generate plain LaTeX output for proper pdf/postscript output. This would potentially allow more flexibility with the final look. - Lout output? - makexml as template for next generation makedoc? --------------------------------------------------------------------------- allegro-4.4.3.1/cmake/0000775000175000017500000000000013437077643013360 5ustar siegesiegeallegro-4.4.3.1/cmake/Common.cmake0000664000175000017500000000654513437077643015624 0ustar siegesiege# For OS X frameworks to work you must add headers to the target's sources. function(add_our_library target) add_library(${target} ${ARGN}) set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -debug PROFILE_POSTFIX -profile ) endfunction(add_our_library) function(set_our_framework_properties target nm) if(WANT_FRAMEWORKS) if(WANT_EMBED) set(install_name_dir "@executable_path/../Frameworks") else() set(install_name_dir "${FRAMEWORK_INSTALL_PREFIX}") endif(WANT_EMBED) set_target_properties(${target} PROPERTIES FRAMEWORK on OUTPUT_NAME ${nm} INSTALL_NAME_DIR "${install_name_dir}" ) endif(WANT_FRAMEWORKS) endfunction(set_our_framework_properties) function(install_our_library target) install(TARGETS ${target} LIBRARY DESTINATION "lib${LIB_SUFFIX}" ARCHIVE DESTINATION "lib${LIB_SUFFIX}" FRAMEWORK DESTINATION "${FRAMEWORK_INSTALL_PREFIX}" RUNTIME DESTINATION "bin" # Doesn't work, see below. # PUBLIC_HEADER DESTINATION "include" ) endfunction(install_our_library) # Unfortunately, CMake's PUBLIC_HEADER support doesn't install into nested # directories well, otherwise we could rely on install(TARGETS) to install # header files associated with the target. Instead we use the install(FILES) # to install headers. We reuse the MACOSX_PACKAGE_LOCATION property, # substituting the "Headers" prefix with "include". function(install_our_headers) foreach(hdr ${ARGN}) get_source_file_property(LOC ${hdr} MACOSX_PACKAGE_LOCATION) string(REGEX REPLACE "^Headers" "include" LOC ${LOC}) install(FILES ${hdr} DESTINATION ${LOC}) endforeach() endfunction(install_our_headers) function(add_our_executable nm) add_executable(${nm} ${ARGN}) target_link_libraries(${nm} allegro) if(PSP) add_psp_executable(${nm}) endif(PSP) endfunction() # Oh my. CMake really is bad for this - but I couldn't find a better # way. function(sanitize_cmake_link_flags return) SET(acc_libs) foreach(lib ${ARGN}) # Watch out for -framework options (OS X) IF (NOT lib MATCHES "-framework.*|.*framework") # Remove absolute path. string(REGEX REPLACE "/.*/(.*)" "\\1" lib ${lib}) # Remove .a/.so/.dylib. string(REGEX REPLACE "lib(.*)\\.(a|so|dylib)" "\\1" lib ${lib}) # Remove -l prefix if it's there already. string(REGEX REPLACE "-l(.*)" "\\1" lib ${lib}) set(acc_libs "${acc_libs} -l${lib}") ENDIF() endforeach(lib) set(${return} ${acc_libs} PARENT_SCOPE) endfunction(sanitize_cmake_link_flags) function(copy_files target) if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") return() endif() foreach(file ${ARGN}) # The "./" is NOT redundant as CMAKE_CFG_INTDIR may be "/". add_custom_command( OUTPUT "./${CMAKE_CFG_INTDIR}/${file}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${file}" COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/${file}" "./${CMAKE_CFG_INTDIR}/${file}" ) endforeach() add_custom_target(${target} ALL DEPENDS ${ARGN}) endfunction() # vim: set sts=4 sw=4 et: allegro-4.4.3.1/cmake/FindSvgalib.cmake0000664000175000017500000000127013437077643016552 0ustar siegesiege# - Find svgalib # # SVGALIB_INCLUDE_DIR - where to find vga.h, etc. # SVGALIB_LIBRARIES - List of libraries when using svgalib. # SVGALIB_FOUND - True if vorbis found. if(SVGALIB_INCLUDE_DIR) # Already in cache, be silent set(SVGALIB_FIND_QUIETLY TRUE) endif(SVGALIB_INCLUDE_DIR) find_path(SVGALIB_INCLUDE_DIR vga.h) find_library(SVGALIB_LIBRARY NAMES vga) # Handle the QUIETLY and REQUIRED arguments and set SVGALIB_FOUND # to TRUE if all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SVGALIB DEFAULT_MSG SVGALIB_INCLUDE_DIR SVGALIB_LIBRARY) mark_as_advanced(SVGALIB_INCLUDE_DIR) mark_as_advanced(SVGALIB_LIBRARY) allegro-4.4.3.1/cmake/FindVorbis.cmake0000664000175000017500000000304313437077643016427 0ustar siegesiege# - Find vorbis # Find the native vorbis includes and libraries # # VORBIS_INCLUDE_DIR - where to find vorbis.h, etc. # VORBIS_LIBRARIES - List of libraries when using vorbis(file). # VORBIS_FOUND - True if vorbis found. if(NOT GP2XWIZ) if(VORBIS_INCLUDE_DIR) # Already in cache, be silent set(VORBIS_FIND_QUIETLY TRUE) endif(VORBIS_INCLUDE_DIR) find_path(OGG_INCLUDE_DIR ogg/ogg.h) find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h) find_library(OGG_LIBRARY NAMES ogg) find_library(VORBIS_LIBRARY NAMES vorbis) find_library(VORBISFILE_LIBRARY NAMES vorbisfile) # Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND # to TRUE if all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(VORBIS DEFAULT_MSG OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY) else(NOT GP2XWIZ) find_path(VORBIS_INCLUDE_DIR tremor/ivorbisfile.h) find_library(VORBIS_LIBRARY NAMES vorbis_dec) find_package_handle_standard_args(VORBIS DEFAULT_MSG VORBIS_INCLUDE_DIR VORBIS_LIBRARY) endif(NOT GP2XWIZ) if(VORBIS_FOUND) if(NOT GP2XWIZ) set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY}) else(NOT GP2XWIZ) set(VORBIS_LIBRARIES ${VORBIS_LIBRARY}) endif(NOT GP2XWIZ) else(VORBIS_FOUND) set(VORBIS_LIBRARIES) endif(VORBIS_FOUND) mark_as_advanced(OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR) mark_as_advanced(OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY) allegro-4.4.3.1/cmake/FileList.cmake0000664000175000017500000002653713437077643016112 0ustar siegesiegeset(ALLEGRO_SRC_FILES src/allegro.c src/blit.c src/bmp.c src/clip3d.c src/clip3df.c src/colblend.c src/color.c src/config.c src/datafile.c src/dataregi.c src/digmid.c src/dither.c src/dispsw.c src/drvlist.c src/file.c src/fli.c src/flood.c src/font.c src/fontbios.c src/fontbmp.c src/fontdat.c src/fontgrx.c src/fonttxt.c src/fsel.c src/gfx.c src/glyph.c src/graphics.c src/gsprite.c src/gui.c src/guiproc.c src/inline.c src/joystick.c src/keyboard.c src/lbm.c src/libc.c src/lzss.c src/math.c src/math3d.c src/midi.c src/mixer.c src/modesel.c src/mouse.c src/pcx.c src/poly3d.c src/polygon.c src/quantize.c src/quat.c src/readbmp.c src/readfont.c src/readsmp.c src/rle.c src/rotate.c src/rsfb.c src/scene3d.c src/sound.c src/spline.c src/stream.c src/text.c src/tga.c src/timer.c src/unicode.c src/vtable.c src/vtable15.c src/vtable16.c src/vtable24.c src/vtable32.c src/vtable8.c ) set(ALLEGRO_SRC_C_FILES src/c/cblit16.c src/c/cblit24.c src/c/cblit32.c src/c/cblit8.c src/c/ccpu.c src/c/ccsprite.c src/c/cgfx15.c src/c/cgfx16.c src/c/cgfx24.c src/c/cgfx32.c src/c/cgfx8.c src/c/cmisc.c src/c/cscan15.c src/c/cscan16.c src/c/cscan24.c src/c/cscan32.c src/c/cscan8.c src/c/cspr15.c src/c/cspr16.c src/c/cspr24.c src/c/cspr32.c src/c/cspr8.c src/c/cstretch.c src/c/czscan15.c src/c/czscan16.c src/c/czscan24.c src/c/czscan32.c src/c/czscan8.c src/misc/ccolconv.c src/misc/colconv.c ) set(ALLEGRO_SRC_DOS_FILES src/dos/adlib.c src/dos/awedata.c src/dos/dfile.c src/dos/dgfxdrv.c src/dos/djoydrv.c src/dos/dkeybd.c src/dos/dma.c src/dos/dmouse.c src/dos/dpmi.c src/dos/dsnddrv.c src/dos/dsystem.c src/dos/dtimer.c src/dos/emu8k.c src/dos/emu8kmid.c src/dos/essaudio.c src/dos/gpro.c src/dos/grip.c src/dos/gripjoy.c src/dos/gripfnc.s src/dos/ifsega.c src/dos/ifsega2f.c src/dos/ifsega2p.c src/dos/joystd.c src/dos/mpu.c src/dos/multijoy.c src/dos/n64pad.c src/dos/pic.c src/dos/psxpad.c src/dos/sb.c src/dos/sndscape.c src/dos/snespad.c src/dos/sw.c src/dos/swpp.c src/dos/swpps.s src/dos/vesa.c src/dos/vesas.s src/dos/wss.c src/dos/ww.c src/misc/modex.c src/misc/modexgfx.s src/misc/modexsms.c src/misc/pckeys.c src/misc/vbeaf.c src/misc/vbeafs.s src/misc/vbeafex.c src/misc/vga.c src/misc/vgaregs.c ) set(ALLEGRO_SRC_WIN_FILES src/win/asmlock.s src/win/dllver.rc src/win/gdi.c src/win/wddaccel.c src/win/wddbmp.c src/win/wddbmpl.c src/win/wddraw.c src/win/wddfull.c src/win/wddlock.c src/win/wddmode.c src/win/wddovl.c src/win/wddwin.c src/win/wdsinput.c src/win/wdsndmix.c src/win/wdsound.c src/win/wsndwo.c src/win/wdxver.c src/win/wdispsw.c src/win/wfile.c src/win/wgdi.c src/win/wgfxdrv.c src/win/winput.c src/win/wjoydrv.c src/win/wjoydx.c src/win/wjoyhelp.c src/win/wjoyw32.c src/win/wkeybd.c src/win/wmidi.c src/win/wmouse.c src/win/wsnddrv.c src/win/wsystem.c src/win/wthread.c src/win/wtimer.c src/win/wwnd.c ) set(ALLEGRO_SRC_BEOS_FILES src/beos/baccel.cpp src/beos/bdispsw.cpp src/beos/bdwindow.cpp src/beos/bgfx.c src/beos/bgfxapi.cpp src/beos/bgfxdrv.c src/beos/bjoy.c src/beos/bjoydrv.c src/beos/bjoyapi.cpp src/beos/bkey.c src/beos/bkeyapi.cpp src/beos/bkeydrv.c src/beos/bmidi.c src/beos/bmidiapi.cpp src/beos/bmididrv.c src/beos/bmousapi.cpp src/beos/bmousdrv.c src/beos/bmouse.c src/beos/boverlay.cpp src/beos/bsnd.c src/beos/bsndapi.cpp src/beos/bsnddrv.c src/beos/bswitch.s src/beos/bsysapi.cpp src/beos/bsysdrv.c src/beos/bsystem.c src/beos/btimeapi.cpp src/beos/btimedrv.c src/beos/btimer.c src/beos/bwindow.cpp src/beos/bwscreen.cpp src/unix/ufile.c src/misc/pckeys.c ) set(ALLEGRO_SRC_LINUX_FILES src/linux/fbcon.c src/linux/lconsole.c src/linux/lgfxdrv.c # Listed with UNIX files. # src/linux/ljoy.c src/linux/lkeybd.c src/linux/lmemory.c src/linux/lmouse.c src/linux/lmsedrv.c src/linux/lmsegpmd.c src/linux/lmsems.c src/linux/lmseps2.c src/linux/lmseev.c src/linux/lstddrv.c src/linux/lsystem.c src/linux/ltimer.c src/linux/lvga.c src/linux/lvgahelp.c src/linux/svgalib.c src/linux/svgalibs.s src/linux/tslib.c src/linux/vtswitch.c src/misc/vbeaf.c src/misc/vbeafs.s src/misc/vgaregs.c src/misc/vga.c # src/misc/modex.c # src/misc/modexgfx.s ) set(ALLEGRO_SRC_UNIX_FILES src/unix/alsa9.c src/unix/alsamidi.c src/unix/arts.c src/unix/sgial.c src/unix/jack.c src/unix/udjgpp.c src/unix/udrvlist.c src/unix/udummy.c src/unix/uesd.c src/unix/ufile.c src/unix/ugfxdrv.c src/unix/ujoydrv.c src/unix/ukeybd.c src/unix/umain.c src/unix/umodules.c src/unix/umouse.c src/unix/uoss.c src/unix/uossmidi.c src/unix/uptimer.c src/unix/usigalrm.c src/unix/usnddrv.c src/unix/ustimer.c src/unix/usystem.c src/unix/uthreads.c src/unix/utimer.c # src/misc/modexsms.c # May be used without enabling the entire Linux console port. src/linux/ljoy.c ) set(ALLEGRO_SRC_X_FILES src/x/xgfxdrv.c src/x/xkeyboard.c src/x/xmouse.c src/x/xsystem.c src/x/xtimer.c src/x/xvtable.c src/x/xwin.c src/x/xdga2.c src/x/xdga2s.s src/x/xwins.s ) set(ALLEGRO_SRC_MACOSX_FILES src/macosx/cadigi.m src/macosx/camidi.m src/macosx/drivers.m src/macosx/hidjoy.m src/macosx/hidman.m src/macosx/keybd.m src/macosx/pcpu.m src/macosx/qtmidi.m src/macosx/quartz.m src/macosx/qzfull.m src/macosx/qzmouse.m src/macosx/qzwindow.m src/macosx/soundman.m src/macosx/system.m src/unix/ufile.c src/unix/utimer.c src/unix/uptimer.c src/unix/usystem.c src/unix/uthreads.c ) set(ALLEGRO_SRC_PSP_FILES src/psp/pdrivers.c src/psp/pfile.c src/psp/pgfx.c src/psp/pjoy.c src/psp/pkey.c src/psp/pmouse.c src/psp/psound.c src/psp/psystem.c src/psp/ptimer.c src/psp/pvram.c src/psp/pvtable8.c ) set(ALLEGRO_INCLUDE_ALLEGRO_FILES include/allegro/3d.h include/allegro/3dmaths.h include/allegro/alcompat.h include/allegro/alinline.h include/allegro/base.h include/allegro/color.h include/allegro/compiled.h include/allegro/config.h include/allegro/datafile.h include/allegro/debug.h include/allegro/digi.h include/allegro/draw.h include/allegro/file.h include/allegro/fix.h include/allegro/fixed.h include/allegro/fli.h include/allegro/fmaths.h include/allegro/font.h include/allegro/gfx.h include/allegro/graphics.h include/allegro/gui.h include/allegro/joystick.h include/allegro/keyboard.h include/allegro/lzss.h include/allegro/matrix.h include/allegro/midi.h include/allegro/mouse.h include/allegro/palette.h include/allegro/quat.h include/allegro/rle.h include/allegro/sound.h include/allegro/stream.h include/allegro/system.h include/allegro/text.h include/allegro/timer.h include/allegro/unicode.h ) set(ALLEGRO_INCLUDE_ALLEGRO_INLINE_FILES include/allegro/inline/3dmaths.inl include/allegro/inline/asm.inl include/allegro/inline/color.inl include/allegro/inline/draw.inl include/allegro/inline/fix.inl include/allegro/inline/fmaths.inl include/allegro/inline/gfx.inl include/allegro/inline/matrix.inl include/allegro/inline/rle.inl include/allegro/inline/system.inl ) set(ALLEGRO_INCLUDE_ALLEGRO_INTERNAL_FILES include/allegro/internal/aintern.h include/allegro/internal/aintvga.h include/allegro/internal/alconfig.h ) set(ALLEGRO_INCLUDE_ALLEGRO_PLATFORM_FILES include/allegro/platform/aintbeos.h include/allegro/platform/aintdos.h include/allegro/platform/aintlnx.h include/allegro/platform/aintmac.h include/allegro/platform/aintosx.h include/allegro/platform/aintpsp.h include/allegro/platform/aintqnx.h include/allegro/platform/aintunix.h include/allegro/platform/aintwin.h include/allegro/platform/al386gcc.h include/allegro/platform/al386vc.h include/allegro/platform/al386wat.h include/allegro/platform/albcc32.h include/allegro/platform/albecfg.h include/allegro/platform/albeos.h include/allegro/platform/aldjgpp.h include/allegro/platform/aldmc.h include/allegro/platform/aldos.h include/allegro/platform/almac.h include/allegro/platform/almaccfg.h include/allegro/platform/almngw32.h include/allegro/platform/almsvc.h include/allegro/platform/alosx.h include/allegro/platform/alosxcfg.h # include/allegro/platform/alplatf.h.cmake include/allegro/platform/alpsp.h include/allegro/platform/alpspcfg.h include/allegro/platform/alqnx.h include/allegro/platform/alqnxcfg.h include/allegro/platform/alucfg.h include/allegro/platform/alunix.h # include/allegro/platform/alunixac.h.cmake # include/allegro/platform/alunixac.hin include/allegro/platform/alwatcom.h include/allegro/platform/alwin.h include/allegro/platform/astdint.h include/allegro/platform/macdef.h ) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro-4.4.3.1/cmake/Toolchain-psp-gcc.cmake0000664000175000017500000002067513437077643017646 0ustar siegesiege# Use this command to build the PSP port of Allegro: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-psp-gcc.cmake . # # or for out of source: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-psp-gcc.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # The name of the target operating system. set(CMAKE_SYSTEM_NAME Generic) # Location of target environment. find_program(psp-config_SCRIPT psp-config) if (psp-config_SCRIPT) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --psp-prefix OUTPUT_VARIABLE PSP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --pspsdk-path OUTPUT_VARIABLE PSPSDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) else (psp-config_SCRIPT) message(FATAL_ERROR "psp-config was not found.\nInstall the PSPDEV toolchain or update the $PATH environment variable.") endif (psp-config_SCRIPT) set(CMAKE_SYSTEM_INCLUDE_PATH "${PSP_PREFIX}/include") set(CMAKE_SYSTEM_LIBRARY_PATH "${PSP_PREFIX}/lib") set(CMAKE_SYSTEM_PROGRAM_PATH "${PSP_PREFIX}/bin") # Which compilers to use for C and C++. set(CMAKE_C_COMPILER psp-gcc) set(CMAKE_CXX_COMPILER psp-g++) # Needed to pass the compiler tests. set(LINK_DIRECTORIES ${PSPSDK_PATH}/lib) set(LINK_LIBRARIES -lc -lpspuser -lpspkernel -lc) # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH ${PSP_PREFIX}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # After building the ELF binary build the PSP executable. function(add_psp_executable nm) get_target_property(PSP_EXECUTABLE_OUTPUT_NAME ${nm} OUTPUT_NAME) if (NOT PSP_EXECUTABLE_OUTPUT_NAME) set(PSP_EXECUTABLE_OUTPUT_NAME ${nm}) endif(NOT PSP_EXECUTABLE_OUTPUT_NAME) set_target_properties( ${nm} PROPERTIES LINK_FLAGS "-specs=${PSPSDK_PATH}/lib/prxspecs -Wl,-q,-T${PSPSDK_PATH}/lib/linkfile.prx ${PSPSDK_PATH}/lib/prxexports.o" ) add_custom_command( TARGET ${nm} POST_BUILD COMMAND psp-fixup-imports ${PSP_EXECUTABLE_OUTPUT_NAME} COMMAND mksfo '${PSP_EXECUTABLE_OUTPUT_NAME}' PARAM.SFO COMMAND psp-prxgen ${PSP_EXECUTABLE_OUTPUT_NAME} ${PSP_EXECUTABLE_OUTPUT_NAME}.prx COMMAND pack-pbp EBOOT.PBP PARAM.SFO NULL NULL NULL NULL NULL ${PSP_EXECUTABLE_OUTPUT_NAME}.prx NULL ) endfunction() set(PSP 1) # Use this command to build the PSP port of Allegro: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-psp-gcc.cmake . # # or for out of source: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-psp-gcc.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # The name of the target operating system. set(CMAKE_SYSTEM_NAME Generic) # Location of target environment. find_program(psp-config_SCRIPT psp-config) if (psp-config_SCRIPT) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --psp-prefix OUTPUT_VARIABLE PSP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --pspsdk-path OUTPUT_VARIABLE PSPSDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) else (psp-config_SCRIPT) message(FATAL_ERROR "psp-config was not found.\nInstall the PSPDEV toolchain or update the $PATH environment variable.") endif (psp-config_SCRIPT) set(CMAKE_SYSTEM_INCLUDE_PATH "${PSP_PREFIX}/include") set(CMAKE_SYSTEM_LIBRARY_PATH "${PSP_PREFIX}/lib") set(CMAKE_SYSTEM_PROGRAM_PATH "${PSP_PREFIX}/bin") # Which compilers to use for C and C++. set(CMAKE_C_COMPILER psp-gcc) set(CMAKE_CXX_COMPILER psp-g++) # Needed to pass the compiler tests. set(LINK_DIRECTORIES ${PSPSDK_PATH}/lib) set(LINK_LIBRARIES -lc -lpspuser -lpspkernel -lc) # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH ${PSP_PREFIX}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # After building the ELF binary build the PSP executable. function(add_psp_executable nm) get_target_property(PSP_EXECUTABLE_OUTPUT_NAME ${nm} OUTPUT_NAME) if (NOT PSP_EXECUTABLE_OUTPUT_NAME) set(PSP_EXECUTABLE_OUTPUT_NAME ${nm}) endif(NOT PSP_EXECUTABLE_OUTPUT_NAME) set_target_properties( ${nm} PROPERTIES LINK_FLAGS "-specs=${PSPSDK_PATH}/lib/prxspecs -Wl,-q,-T${PSPSDK_PATH}/lib/linkfile.prx ${PSPSDK_PATH}/lib/prxexports.o" ) add_custom_command( TARGET ${nm} POST_BUILD COMMAND psp-fixup-imports ${PSP_EXECUTABLE_OUTPUT_NAME} COMMAND mksfo '${PSP_EXECUTABLE_OUTPUT_NAME}' PARAM.SFO COMMAND psp-prxgen ${PSP_EXECUTABLE_OUTPUT_NAME} ${PSP_EXECUTABLE_OUTPUT_NAME}.prx COMMAND pack-pbp EBOOT.PBP PARAM.SFO NULL NULL NULL NULL NULL ${PSP_EXECUTABLE_OUTPUT_NAME}.prx NULL ) endfunction() set(PSP 1) # Use this command to build the PSP port of Allegro: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-psp-gcc.cmake . # # or for out of source: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-psp-gcc.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # The name of the target operating system. set(CMAKE_SYSTEM_NAME Generic) # Location of target environment. find_program(psp-config_SCRIPT psp-config) if (psp-config_SCRIPT) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --psp-prefix OUTPUT_VARIABLE PSP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --pspsdk-path OUTPUT_VARIABLE PSPSDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) else (psp-config_SCRIPT) message(FATAL_ERROR "psp-config was not found.\nInstall the PSPDEV toolchain or update the $PATH environment variable.") endif (psp-config_SCRIPT) set(CMAKE_SYSTEM_INCLUDE_PATH "${PSP_PREFIX}/include") set(CMAKE_SYSTEM_LIBRARY_PATH "${PSP_PREFIX}/lib") set(CMAKE_SYSTEM_PROGRAM_PATH "${PSP_PREFIX}/bin") # Which compilers to use for C and C++. set(CMAKE_C_COMPILER psp-gcc) set(CMAKE_CXX_COMPILER psp-g++) # Needed to pass the compiler tests. set(LINK_DIRECTORIES ${PSPSDK_PATH}/lib) set(LINK_LIBRARIES -lc -lpspuser -lpspkernel -lc) # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH ${PSP_PREFIX}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # After building the ELF binary build the PSP executable. function(add_psp_executable nm) get_target_property(PSP_EXECUTABLE_OUTPUT_NAME ${nm} OUTPUT_NAME) if (NOT PSP_EXECUTABLE_OUTPUT_NAME) set(PSP_EXECUTABLE_OUTPUT_NAME ${nm}) endif(NOT PSP_EXECUTABLE_OUTPUT_NAME) set_target_properties( ${nm} PROPERTIES LINK_FLAGS "-specs=${PSPSDK_PATH}/lib/prxspecs -Wl,-q,-T${PSPSDK_PATH}/lib/linkfile.prx ${PSPSDK_PATH}/lib/prxexports.o" ) add_custom_command( TARGET ${nm} POST_BUILD COMMAND psp-fixup-imports ${PSP_EXECUTABLE_OUTPUT_NAME} COMMAND mksfo '${PSP_EXECUTABLE_OUTPUT_NAME}' PARAM.SFO COMMAND psp-prxgen ${PSP_EXECUTABLE_OUTPUT_NAME} ${PSP_EXECUTABLE_OUTPUT_NAME}.prx COMMAND pack-pbp EBOOT.PBP PARAM.SFO NULL NULL NULL NULL NULL ${PSP_EXECUTABLE_OUTPUT_NAME}.prx NULL ) endfunction() set(PSP 1) allegro-4.4.3.1/cmake/Toolchain-mingw.cmake0000664000175000017500000000520113437077643017417 0ustar siegesiege# Use this command to build the Windows port of Allegro # with a mingw cross compiler: # # cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw.cmake . # # or for out of source: # # cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # You might want to set MINGDIR to prevent make install making a mess # in your normal directories. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # Assume the target architecture. # XXX for some reason the value set here gets cleared before we reach the # main CMakeLists.txt; see that file for a workaround. # set(CMAKE_SYSTEM_PROCESSOR i686) # Which compilers to use for C and C++, and location of target # environment. if(EXISTS /usr/i586-mingw32msvc) # First look in standard location as used by Debian/Ubuntu/etc. set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) elseif(EXISTS /opt/mingw) # Otherwise you can get a MinGW environment using the script at # . It downloads and builds MinGW and # most of the dependencies for you. This is a suitable location. set(CMAKE_C_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-gcc) set(CMAKE_CXX_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-g++) set(CMAKE_FIND_ROOT_PATH /opt/mingw/usr/i686-pc-mingw32) else() # Else fill in local path which the user will likely adjust. # This is the location assumed by set(CMAKE_C_COMPILER /usr/local/cross-tools/bin/i386-mingw32-gcc) set(CMAKE_CXX_COMPILER /usr/local/cross-tools/bin/i386-mingw32-g++) set(CMAKE_FIND_ROOT_PATH /usr/local/cross-tools) endif() # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Tell pkg-config not to look at the target environment's .pc files. # Setting PKG_CONFIG_LIBDIR sets the default search directory, but we have to # set PKG_CONFIG_PATH as well to prevent pkg-config falling back to the host's # path. set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) set(ENV{PKG_CONFIG_PATH} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) set(INSTALL_PREFIX ${CMAKE_FIND_ROOT_PATH}) if(ENV{MINGDIR} STREQUAL "") set(ENV{MINGDIR} ${CMAKE_FIND_ROOT_PATH}) endif() allegro-4.4.3.1/cmake/FindTslib.cmake0000664000175000017500000000122413437077643016237 0ustar siegesiege# - Find tslib # # TSLIB_INCLUDE_DIR - where to find tslib.h. # TSLIB_LIBRARIES - List of libraries when using tslib. # TSLIB_FOUND - True if tslib found. if(TSLIB_INCLUDE_DIR) # Already in cache, be silent set(TSLIB_FIND_QUIETLY TRUE) endif(TSLIB_INCLUDE_DIR) find_path(TSLIB_INCLUDE_DIR tslib.h) find_library(TSLIB_LIBRARY NAMES ts) # Handle the QUIETLY and REQUIRED arguments and set TSLIB_FOUND # to TRUE if all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(TSLIB DEFAULT_MSG TSLIB_INCLUDE_DIR TSLIB_LIBRARY) mark_as_advanced(TSLIB_INCLUDE_DIR) mark_as_advanced(TSLIB_LIBRARY) allegro-4.4.3.1/cmake/FindDXGuid.cmake0000664000175000017500000000137513437077643016315 0ustar siegesiege# - Find dxguid # Find the dxguid libraries # # DXGUID_LIBRARIES - List of libraries # DXGUID_FOUND - True if dxguid found. if(MSVC) find_library(DXGUID_LIBRARY NAMES dxguid PATHS "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib" PATH_SUFFIXES x86 x64 ) else() find_library(DXGUID_LIBRARY NAMES dxguid) endif() # Handle the QUIETLY and REQUIRED arguments and set DXGUID_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DXGUID DEFAULT_MSG DXGUID_LIBRARY) if(DXGUID_FOUND) set(DXGUID_LIBRARIES ${DXGUID_LIBRARY}) else(DXGUID_FOUND) set(DXGUID_LIBRARIES) endif(DXGUID_FOUND) mark_as_advanced(DXGUID_INCLUDE_DIR DXGUID_LIBRARY) allegro-4.4.3.1/cmake/FindDSound.cmake0000664000175000017500000000215413437077643016361 0ustar siegesiege# - Find DirectSound # Find the DirectSound includes and libraries # # DSOUND_INCLUDE_DIR - where to find dsound.h # DSOUND_LIBRARIES - List of libraries when using dsound. # DSOUND_FOUND - True if dsound found. if(DSOUND_INCLUDE_DIR) # Already in cache, be silent set(DSOUND_FIND_QUIETLY TRUE) endif(DSOUND_INCLUDE_DIR) # Makes my life easier. if(MSVC) set(HINT_INCLUDE "C:/Program Files/Microsoft DirectX SDK (August 2008)/Include") set(HINT_LIB "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib") endif(MSVC) find_path(DSOUND_INCLUDE_DIR dsound.h PATHS ${HINT_INCLUDE}) find_library(DSOUND_LIBRARY NAMES dsound PATHS ${HINT_LIB} PATH_SUFFIXES x86 x64 ) # Handle the QUIETLY and REQUIRED arguments and set DSOUND_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DSOUND DEFAULT_MSG DSOUND_INCLUDE_DIR DSOUND_LIBRARY) if(DSOUND_FOUND) set(DSOUND_LIBRARIES ${DSOUND_LIBRARY}) else(DSOUND_FOUND) set(DSOUND_LIBRARIES) endif(DSOUND_FOUND) mark_as_advanced(DSOUND_INCLUDE_DIR DSOUND_LIBRARY) allegro-4.4.3.1/cmake/AllegroFindOSS.cmake0000664000175000017500000000432713437077643017143 0ustar siegesiege# - Find Open Sound System # # OSS_FOUND - True if OSS headers found. # This file is Allegro-specific and requires the following variables to be # set elsewhere: # ALLEGRO_HAVE_MACHINE_SOUNDCARD_H # ALLEGRO_HAVE_LINUX_SOUNDCARD_H # ALLEGRO_HAVE_SYS_SOUNDCARD_H # ALLEGRO_HAVE_SOUNDCARD_H if(OSS_INCLUDE_DIR) # Already in cache, be silent set(OSS_FIND_QUIETLY TRUE) endif(OSS_INCLUDE_DIR) set(CMAKE_REQUIRED_DEFINITIONS) if(ALLEGRO_HAVE_SOUNDCARD_H OR ALLEGRO_HAVE_SYS_SOUNDCARD_H OR ALLEGRO_HAVE_MACHINE_SOUNDCARD_H OR ALLEGRO_LINUX_SYS_SOUNDCARD_H) if(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS -DALLEGRO_HAVE_MACHINE_SOUNDCARD_H) endif(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) if(ALLEGRO_HAVE_LINUX_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DALLEGRO_HAVE_LINUX_SOUNDCARD_H) endif(ALLEGRO_HAVE_LINUX_SOUNDCARD_H) if(ALLEGRO_HAVE_SYS_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DALLEGRO_HAVE_SYS_SOUNDCARD_H) endif(ALLEGRO_HAVE_SYS_SOUNDCARD_H) if(ALLEGRO_HAVE_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DALLEGRO_HAVE_SOUNDCARD_H) endif(ALLEGRO_HAVE_SOUNDCARD_H) check_c_source_compiles(" #ifdef ALLEGRO_HAVE_SOUNDCARD_H #include #endif #ifdef ALLEGRO_HAVE_SYS_SOUNDCARD_H #include #endif #ifdef ALLEGRO_HAVE_LINUX_SOUNDCARD_H #include #endif #ifdef ALLEGRO_HAVE_MACHINE_SOUNDCARD_H #include #endif int main(void) { audio_buf_info abi; return 0; }" OSS_COMPILES ) set(CMAKE_REQUIRED_DEFINITIONS) endif(ALLEGRO_HAVE_SOUNDCARD_H OR ALLEGRO_HAVE_SYS_SOUNDCARD_H OR ALLEGRO_HAVE_MACHINE_SOUNDCARD_H OR ALLEGRO_LINUX_SYS_SOUNDCARD_H) # Handle the QUIETLY and REQUIRED arguments and set OSS_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OSS DEFAULT_MSG OSS_COMPILES) mark_as_advanced(OSS_COMPILES) allegro-4.4.3.1/cmake/FindDDraw.cmake0000664000175000017500000000213113437077643016161 0ustar siegesiege# - Find DirectDraw # Find the DirectDraw includes and libraries # # DDRAW_INCLUDE_DIR - where to find ddraw.h # DDRAW_LIBRARIES - List of libraries when using ddraw. # DDRAW_FOUND - True if ddraw found. if(DDRAW_INCLUDE_DIR) # Already in cache, be silent set(DDRAW_FIND_QUIETLY TRUE) endif(DDRAW_INCLUDE_DIR) # Makes my life easier. if(MSVC) set(HINT_INCLUDE "C:/Program Files/Microsoft DirectX SDK (August 2008)/Include") set(HINT_LIB "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib") endif(MSVC) find_path(DDRAW_INCLUDE_DIR ddraw.h PATH ${HINT_INCLUDE} ) find_library(DDRAW_LIBRARY NAMES ddraw PATHS ${HINT_LIB} PATH_SUFFIXES x86 x64 ) # Handle the QUIETLY and REQUIRED arguments and set DDRAW_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DDRAW DEFAULT_MSG DDRAW_INCLUDE_DIR DDRAW_LIBRARY) if(DDRAW_FOUND) set(DDRAW_LIBRARIES ${DDRAW_LIBRARY}) else(DDRAW_FOUND) set(DDRAW_LIBRARIES) endif(DDRAW_FOUND) mark_as_advanced(DDRAW_INCLUDE_DIR DDRAW_LIBRARY) allegro-4.4.3.1/cmake/FindDInput.cmake0000664000175000017500000000217413437077643016372 0ustar siegesiege# - Find DirectInput # Find the DirectInput includes and libraries # # DINPUT_INCLUDE_DIR - where to find dinput.h # DINPUT_LIBRARIES - List of libraries when using dinput. # DINPUT_FOUND - True if dinput found. if(DINPUT_INCLUDE_DIR) # Already in cache, be silent set(DINPUT_FIND_QUIETLY TRUE) endif(DINPUT_INCLUDE_DIR) # Makes my life easier. if(MSVC) set(HINT_INCLUDE "C:/Program Files/Microsoft DirectX SDK (August 2008)/Include") set(HINT_LIB "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib") endif(MSVC) find_path(DINPUT_INCLUDE_DIR dinput.h PATH ${HINT_INCLUDE} ) find_library(DINPUT_LIBRARY NAMES dinput dinput8 PATHS ${HINT_LIB} PATH_SUFFIXES x86 x64 ) # Handle the QUIETLY and REQUIRED arguments and set DINPUT_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DINPUT DEFAULT_MSG DINPUT_INCLUDE_DIR DINPUT_LIBRARY) if(DINPUT_FOUND) set(DINPUT_LIBRARIES ${DINPUT_LIBRARY}) else(DINPUT_FOUND) set(DINPUT_LIBRARIES) endif(DINPUT_FOUND) mark_as_advanced(DINPUT_INCLUDE_DIR DINPUT_LIBRARY) allegro-4.4.3.1/include/0000775000175000017500000000000013437077643013723 5ustar siegesiegeallegro-4.4.3.1/include/macalleg.h0000664000175000017500000000526513437077643015651 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOs header file for the Allegro library. * This should be included by everyone and everything. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #ifndef MAC_ALLEGRO_H #define MAC_ALLEGRO_H #ifndef ALLEGRO_H #error Please include allegro.h before macalleg.h! #endif #if (!defined SCAN_EXPORT) && (!defined SCAN_DEPEND) #endif #include //theses includes aways are needed in normal mac programs #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "allegro/platform/macdef.h" #ifdef __cplusplus extern "C" { #endif typedef BITMAP BITMAP; typedef struct{ CGrafPtr cg; long rowBytes; unsigned char* first; unsigned char* last; long flags; int cachealigned; Ptr data; }mac_bitmap; #define MEMORY_ALIGN 4 #define GETMACBITMAP(bmp)((mac_bitmap*)(bmp->extra)) #pragma options align=mac68k typedef struct mac_sample{ short formatType; short numberSyns; short idFirstSynth; long INIToptions; short numCommands; short command1; short param1; long param2; SoundHeader s; }mac_sample; typedef mac_sample **hmac_sample; #pragma options align=reset typedef struct mac_voice{ SndChannelPtr channel; SndListHandle sample; short headsize; long headeroff; int loop; int loop_start; int loop_end; int vol; int pan; int frequency; SAMPLE * al_sample; }mac_voice; AL_VAR(QDGlobals , qd); AL_VAR(GFX_VTABLE,__mac_sys_vtable8); AL_VAR(GFX_VTABLE,__mac_sys_vtable15); AL_VAR(GFX_VTABLE,__mac_sys_vtable24); extern void _mac_lock(void *address, unsigned long size); extern void _mac_unlock(void *address, unsigned long size); #ifdef __cplusplus } #endif #endif /* ifndef MAC_ALLEGRO_H */ allegro-4.4.3.1/include/allegro/0000775000175000017500000000000013437077643015350 5ustar siegesiegeallegro-4.4.3.1/include/allegro/compiled.h0000664000175000017500000000330713437077643017320 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Compiled sprites. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_COMPILED_H #define ALLEGRO_COMPILED_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; #if (defined ALLEGRO_I386) && (!defined ALLEGRO_NO_ASM) /* compiled sprite structure */ typedef struct COMPILED_SPRITE { short planar; /* set if it's a planar (mode-X) sprite */ short color_depth; /* color depth of the image */ short w, h; /* size of the sprite */ struct { void *draw; /* routines to draw the image */ int len; /* length of the drawing functions */ } proc[4]; } COMPILED_SPRITE; #else /* emulate compiled sprites using RLE on other platforms */ struct RLE_SPRITE; typedef struct RLE_SPRITE COMPILED_SPRITE; #endif AL_FUNC(COMPILED_SPRITE *, get_compiled_sprite, (struct BITMAP *bitmap, int planar)); AL_FUNC(void, destroy_compiled_sprite, (COMPILED_SPRITE *sprite)); AL_FUNC(void, draw_compiled_sprite, (struct BITMAP *bmp, AL_CONST COMPILED_SPRITE *sprite, int x, int y)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_COMPILED_H */ allegro-4.4.3.1/include/allegro/gui.h0000664000175000017500000002353613437077643016316 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * GUI routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_GUI_H #define ALLEGRO_GUI_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; struct DIALOG; typedef AL_METHOD(int, DIALOG_PROC, (int msg, struct DIALOG *d, int c)); typedef struct DIALOG { DIALOG_PROC proc; int x, y, w, h; /* position and size of the object */ int fg, bg; /* foreground and background colors */ int key; /* keyboard shortcut (ASCII code) */ int flags; /* flags about the object state */ int d1, d2; /* any data the object might require */ void *dp, *dp2, *dp3; /* pointers to more object data */ } DIALOG; /* a popup menu */ typedef struct MENU { char *text; /* menu item text */ AL_METHOD(int, proc, (void)); /* callback function */ struct MENU *child; /* to allow nested menus */ int flags; /* flags about the menu state */ void *dp; /* any data the menu might require */ } MENU; /* stored information about the state of an active GUI dialog */ typedef struct DIALOG_PLAYER { int obj; int res; int mouse_obj; int focus_obj; int joy_on; int click_wait; int mouse_ox, mouse_oy; int mouse_oz; int mouse_b; DIALOG *dialog; } DIALOG_PLAYER; /* stored information about the state of an active GUI menu */ typedef struct MENU_PLAYER { MENU *menu; /* the menu itself */ int bar; /* set if it is a top level menu bar */ int size; /* number of items in the menu */ int sel; /* selected item */ int x, y, w, h; /* screen position of the menu */ int (*proc)(void); /* callback function */ BITMAP *saved; /* saved what was underneath it */ int mouse_button_was_pressed; /* set if mouse button pressed on last iteration */ int back_from_child; /* set if a child was activated on last iteration */ int timestamp; /* timestamp for gui_timer events */ int mouse_sel; /* item the mouse is currently over */ int redraw; /* set if redrawing is required */ int auto_open; /* set if menu auto-opening is activated */ int ret; /* return value */ DIALOG *dialog; /* d_menu_proc() parent dialog (if any) */ struct MENU_PLAYER *parent; /* the parent menu, or NULL for root */ struct MENU_PLAYER *child; /* the child menu, or NULL for none */ } MENU_PLAYER; /* bits for the flags field */ #define D_EXIT 1 /* object makes the dialog exit */ #define D_SELECTED 2 /* object is selected */ #define D_GOTFOCUS 4 /* object has the input focus */ #define D_GOTMOUSE 8 /* mouse is on top of object */ #define D_HIDDEN 16 /* object is not visible */ #define D_DISABLED 32 /* object is visible but inactive */ #define D_DIRTY 64 /* object needs to be redrawn */ #define D_INTERNAL 128 /* reserved for internal use */ #define D_USER 256 /* from here on is free for your own use */ /* return values for the dialog procedures */ #define D_O_K 0 /* normal exit status */ #define D_CLOSE 1 /* request to close the dialog */ #define D_REDRAW 2 /* request to redraw the dialog */ #define D_REDRAWME 4 /* request to redraw this object */ #define D_WANTFOCUS 8 /* this object wants the input focus */ #define D_USED_CHAR 16 /* object has used the keypress */ #define D_REDRAW_ALL 32 /* request to redraw all active dialogs */ #define D_DONTWANTMOUSE 64 /* this object does not want mouse focus */ /* messages for the dialog procedures */ #define MSG_START 1 /* start the dialog, initialise */ #define MSG_END 2 /* dialog is finished - cleanup */ #define MSG_DRAW 3 /* draw the object */ #define MSG_CLICK 4 /* mouse click on the object */ #define MSG_DCLICK 5 /* double click on the object */ #define MSG_KEY 6 /* keyboard shortcut */ #define MSG_CHAR 7 /* other keyboard input */ #define MSG_UCHAR 8 /* unicode keyboard input */ #define MSG_XCHAR 9 /* broadcast character to all objects */ #define MSG_WANTFOCUS 10 /* does object want the input focus? */ #define MSG_GOTFOCUS 11 /* got the input focus */ #define MSG_LOSTFOCUS 12 /* lost the input focus */ #define MSG_GOTMOUSE 13 /* mouse on top of object */ #define MSG_LOSTMOUSE 14 /* mouse moved away from object */ #define MSG_IDLE 15 /* update any background stuff */ #define MSG_RADIO 16 /* clear radio buttons */ #define MSG_WHEEL 17 /* mouse wheel moved */ #define MSG_LPRESS 18 /* mouse left button pressed */ #define MSG_LRELEASE 19 /* mouse left button released */ #define MSG_MPRESS 20 /* mouse middle button pressed */ #define MSG_MRELEASE 21 /* mouse middle button released */ #define MSG_RPRESS 22 /* mouse right button pressed */ #define MSG_RRELEASE 23 /* mouse right button released */ #define MSG_WANTMOUSE 24 /* does object want the mouse? */ #define MSG_USER 25 /* from here on are free... */ /* some dialog procedures */ AL_FUNC(int, d_yield_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_clear_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_box_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_shadow_box_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_bitmap_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_text_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_ctext_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_rtext_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_button_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_check_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_radio_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_icon_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_keyboard_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_edit_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_list_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_text_list_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_textbox_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_slider_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, d_menu_proc, (int msg, DIALOG *d, int c)); AL_VAR(DIALOG_PROC, gui_shadow_box_proc); AL_VAR(DIALOG_PROC, gui_ctext_proc); AL_VAR(DIALOG_PROC, gui_button_proc); AL_VAR(DIALOG_PROC, gui_edit_proc); AL_VAR(DIALOG_PROC, gui_list_proc); AL_VAR(DIALOG_PROC, gui_text_list_proc); AL_FUNCPTR(void, gui_menu_draw_menu, (int x, int y, int w, int h)); AL_FUNCPTR(void, gui_menu_draw_menu_item, (MENU *m, int x, int y, int w, int h, int bar, int sel)); AL_VAR(DIALOG *, active_dialog); AL_VAR(MENU *, active_menu); AL_VAR(int, gui_mouse_focus); AL_VAR(int, gui_fg_color); AL_VAR(int, gui_mg_color); AL_VAR(int, gui_bg_color); AL_VAR(int, gui_font_baseline); AL_FUNCPTR(int, gui_mouse_x, (void)); AL_FUNCPTR(int, gui_mouse_y, (void)); AL_FUNCPTR(int, gui_mouse_z, (void)); AL_FUNCPTR(int, gui_mouse_b, (void)); AL_FUNC(void, gui_set_screen, (BITMAP *bmp)); AL_FUNC(BITMAP *, gui_get_screen, (void)); AL_FUNC(int, gui_textout_ex, (struct BITMAP *bmp, AL_CONST char *s, int x, int y, int color, int bg, int centre)); AL_FUNC(int, gui_strlen, (AL_CONST char *s)); AL_FUNC(void, position_dialog, (DIALOG *dialog, int x, int y)); AL_FUNC(void, centre_dialog, (DIALOG *dialog)); AL_FUNC(void, set_dialog_color, (DIALOG *dialog, int fg, int bg)); AL_FUNC(int, find_dialog_focus, (DIALOG *dialog)); AL_FUNC(int, offer_focus, (DIALOG *dialog, int obj, int *focus_obj, int force)); AL_FUNC(int, object_message, (DIALOG *dialog, int msg, int c)); AL_FUNC(int, dialog_message, (DIALOG *dialog, int msg, int c, int *obj)); AL_FUNC(int, broadcast_dialog_message, (int msg, int c)); AL_FUNC(int, do_dialog, (DIALOG *dialog, int focus_obj)); AL_FUNC(int, popup_dialog, (DIALOG *dialog, int focus_obj)); AL_FUNC(DIALOG_PLAYER *, init_dialog, (DIALOG *dialog, int focus_obj)); AL_FUNC(int, update_dialog, (DIALOG_PLAYER *player)); AL_FUNC(int, shutdown_dialog, (DIALOG_PLAYER *player)); AL_FUNC(int, do_menu, (MENU *menu, int x, int y)); AL_FUNC(MENU_PLAYER *, init_menu, (MENU *menu, int x, int y)); AL_FUNC(int, update_menu, (MENU_PLAYER *player)); AL_FUNC(int, shutdown_menu, (MENU_PLAYER *player)); AL_FUNC(int, alert, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)); AL_FUNC(int, alert3, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)); AL_FUNC(int, file_select_ex, (AL_CONST char *message, char *path, AL_CONST char *ext, int size, int w, int h)); AL_FUNC(int, gfx_mode_select, (int *card, int *w, int *h)); AL_FUNC(int, gfx_mode_select_ex, (int *card, int *w, int *h, int *color_depth)); AL_FUNC(int, gfx_mode_select_filter, (int *card, int *w, int *h, int *color_depth, int (*filter)(int, int, int, int))); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_GUI_H */ allegro-4.4.3.1/include/allegro/digi.h0000664000175000017500000002031113437077643016432 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Digital sound routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DIGI_H #define ALLEGRO_DIGI_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct PACKFILE; #define DIGI_VOICES 64 /* Theoretical maximums: */ /* actual drivers may not be */ /* able to handle this many */ typedef struct SAMPLE /* a sample */ { int bits; /* 8 or 16 */ int stereo; /* sample type flag */ int freq; /* sample frequency */ int priority; /* 0-255 */ unsigned long len; /* length (in samples) */ unsigned long loop_start; /* loop start position */ unsigned long loop_end; /* loop finish position */ unsigned long param; /* for internal use by the driver */ void *data; /* sample data */ } SAMPLE; #define DIGI_AUTODETECT -1 /* for passing to install_sound() */ #define DIGI_NONE 0 typedef struct DIGI_DRIVER /* driver for playing digital sfx */ { int id; /* driver ID code */ AL_CONST char *name; /* driver name */ AL_CONST char *desc; /* description string */ AL_CONST char *ascii_name; /* ASCII format name string */ int voices; /* available voices */ int basevoice; /* voice number offset */ int max_voices; /* maximum voices we can support */ int def_voices; /* default number of voices to use */ /* setup routines */ AL_METHOD(int, detect, (int input)); AL_METHOD(int, init, (int input, int voices)); AL_METHOD(void, exit, (int input)); AL_METHOD(int, set_mixer_volume, (int volume)); AL_METHOD(int, get_mixer_volume, (void)); /* for use by the audiostream functions */ AL_METHOD(void *, lock_voice, (int voice, int start, int end)); AL_METHOD(void, unlock_voice, (int voice)); AL_METHOD(int, buffer_size, (void)); /* voice control functions */ AL_METHOD(void, init_voice, (int voice, AL_CONST SAMPLE *sample)); AL_METHOD(void, release_voice, (int voice)); AL_METHOD(void, start_voice, (int voice)); AL_METHOD(void, stop_voice, (int voice)); AL_METHOD(void, loop_voice, (int voice, int playmode)); /* position control functions */ AL_METHOD(int, get_position, (int voice)); AL_METHOD(void, set_position, (int voice, int position)); /* volume control functions */ AL_METHOD(int, get_volume, (int voice)); AL_METHOD(void, set_volume, (int voice, int volume)); AL_METHOD(void, ramp_volume, (int voice, int tyme, int endvol)); AL_METHOD(void, stop_volume_ramp, (int voice)); /* pitch control functions */ AL_METHOD(int, get_frequency, (int voice)); AL_METHOD(void, set_frequency, (int voice, int frequency)); AL_METHOD(void, sweep_frequency, (int voice, int tyme, int endfreq)); AL_METHOD(void, stop_frequency_sweep, (int voice)); /* pan control functions */ AL_METHOD(int, get_pan, (int voice)); AL_METHOD(void, set_pan, (int voice, int pan)); AL_METHOD(void, sweep_pan, (int voice, int tyme, int endpan)); AL_METHOD(void, stop_pan_sweep, (int voice)); /* effect control functions */ AL_METHOD(void, set_echo, (int voice, int strength, int delay)); AL_METHOD(void, set_tremolo, (int voice, int rate, int depth)); AL_METHOD(void, set_vibrato, (int voice, int rate, int depth)); /* input functions */ int rec_cap_bits; int rec_cap_stereo; AL_METHOD(int, rec_cap_rate, (int bits, int stereo)); AL_METHOD(int, rec_cap_parm, (int rate, int bits, int stereo)); AL_METHOD(int, rec_source, (int source)); AL_METHOD(int, rec_start, (int rate, int bits, int stereo)); AL_METHOD(void, rec_stop, (void)); AL_METHOD(int, rec_read, (void *buf)); } DIGI_DRIVER; AL_ARRAY(_DRIVER_INFO, _digi_driver_list); /* macros for constructing the driver lists */ #define BEGIN_DIGI_DRIVER_LIST \ _DRIVER_INFO _digi_driver_list[] = \ { #define END_DIGI_DRIVER_LIST \ { 0, NULL, 0 } \ }; AL_VAR(DIGI_DRIVER *, digi_driver); AL_VAR(DIGI_DRIVER *, digi_input_driver); AL_VAR(int, digi_card); AL_VAR(int, digi_input_card); AL_FUNC(int, detect_digi_driver, (int driver_id)); AL_FUNC(SAMPLE *, load_sample, (AL_CONST char *filename)); AL_FUNC(SAMPLE *, load_wav, (AL_CONST char *filename)); AL_FUNC(SAMPLE *, load_wav_pf, (struct PACKFILE *f)); AL_FUNC(SAMPLE *, load_voc, (AL_CONST char *filename)); AL_FUNC(SAMPLE *, load_voc_pf, (struct PACKFILE *f)); AL_FUNC(int, save_sample, (AL_CONST char *filename, SAMPLE *spl)); AL_FUNC(SAMPLE *, create_sample, (int bits, int stereo, int freq, int len)); AL_FUNC(void, destroy_sample, (SAMPLE *spl)); AL_FUNC(int, play_sample, (AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop)); AL_FUNC(void, stop_sample, (AL_CONST SAMPLE *spl)); AL_FUNC(void, adjust_sample, (AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop)); AL_FUNC(int, allocate_voice, (AL_CONST SAMPLE *spl)); AL_FUNC(void, deallocate_voice, (int voice)); AL_FUNC(void, reallocate_voice, (int voice, AL_CONST SAMPLE *spl)); AL_FUNC(void, release_voice, (int voice)); AL_FUNC(void, voice_start, (int voice)); AL_FUNC(void, voice_stop, (int voice)); AL_FUNC(void, voice_set_priority, (int voice, int priority)); AL_FUNC(SAMPLE *, voice_check, (int voice)); #define PLAYMODE_PLAY 0 #define PLAYMODE_LOOP 1 #define PLAYMODE_FORWARD 0 #define PLAYMODE_BACKWARD 2 #define PLAYMODE_BIDIR 4 AL_FUNC(void, voice_set_playmode, (int voice, int playmode)); AL_FUNC(int, voice_get_position, (int voice)); AL_FUNC(void, voice_set_position, (int voice, int position)); AL_FUNC(int, voice_get_volume, (int voice)); AL_FUNC(void, voice_set_volume, (int voice, int volume)); AL_FUNC(void, voice_ramp_volume, (int voice, int tyme, int endvol)); AL_FUNC(void, voice_stop_volumeramp, (int voice)); AL_FUNC(int, voice_get_frequency, (int voice)); AL_FUNC(void, voice_set_frequency, (int voice, int frequency)); AL_FUNC(void, voice_sweep_frequency, (int voice, int tyme, int endfreq)); AL_FUNC(void, voice_stop_frequency_sweep, (int voice)); AL_FUNC(int, voice_get_pan, (int voice)); AL_FUNC(void, voice_set_pan, (int voice, int pan)); AL_FUNC(void, voice_sweep_pan, (int voice, int tyme, int endpan)); AL_FUNC(void, voice_stop_pan_sweep, (int voice)); AL_FUNC(void, voice_set_echo, (int voice, int strength, int delay)); AL_FUNC(void, voice_set_tremolo, (int voice, int rate, int depth)); AL_FUNC(void, voice_set_vibrato, (int voice, int rate, int depth)); #define SOUND_INPUT_MIC 1 #define SOUND_INPUT_LINE 2 #define SOUND_INPUT_CD 3 AL_FUNC(int, get_sound_input_cap_bits, (void)); AL_FUNC(int, get_sound_input_cap_stereo, (void)); AL_FUNC(int, get_sound_input_cap_rate, (int bits, int stereo)); AL_FUNC(int, get_sound_input_cap_parm, (int rate, int bits, int stereo)); AL_FUNC(int, set_sound_input_source, (int source)); AL_FUNC(int, start_sound_input, (int rate, int bits, int stereo)); AL_FUNC(void, stop_sound_input, (void)); AL_FUNC(int, read_sound_input, (void *buffer)); AL_FUNCPTR(void, digi_recorder, (void)); AL_FUNC(void, lock_sample, (struct SAMPLE *spl)); AL_FUNC(void, register_sample_file_type, (AL_CONST char *ext, AL_METHOD(struct SAMPLE *, load, (AL_CONST char *filename)), AL_METHOD(int, save, (AL_CONST char *filename, struct SAMPLE *spl)))); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_DIGI_H */ allegro-4.4.3.1/include/allegro/stream.h0000664000175000017500000000315313437077643017016 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Streaming sound routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_STREAM_H #define ALLEGRO_STREAM_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct SAMPLE; typedef struct AUDIOSTREAM { int voice; /* the voice we are playing on */ struct SAMPLE *samp; /* the sample we are using */ int len; /* buffer length */ int bufcount; /* number of buffers per sample half */ int bufnum; /* current refill buffer */ int active; /* which half is currently playing */ void *locked; /* the locked buffer */ } AUDIOSTREAM; AL_FUNC(AUDIOSTREAM *, play_audio_stream, (int len, int bits, int stereo, int freq, int vol, int pan)); AL_FUNC(void, stop_audio_stream, (AUDIOSTREAM *stream)); AL_FUNC(void *, get_audio_stream_buffer, (AUDIOSTREAM *stream)); AL_FUNC(void, free_audio_stream_buffer, (AUDIOSTREAM *stream)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_STREAM_H */ allegro-4.4.3.1/include/allegro/inline/0000775000175000017500000000000013437077643016626 5ustar siegesiegeallegro-4.4.3.1/include/allegro/inline/gfx.inl0000664000175000017500000001255513437077643020126 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Graphics inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_GFX_INL #define ALLEGRO_GFX_INL #include "allegro/debug.h" #define ALLEGRO_IMPORT_GFX_ASM #include "asm.inl" #undef ALLEGRO_IMPORT_GFX_ASM #ifdef __cplusplus extern "C" { #endif #ifdef ALLEGRO_NO_ASM /* use generic C versions */ AL_INLINE(int, _default_ds, (void), { return 0; }) #ifdef ALLEGRO_BCC32 /* BCC32 is a somewhat unusual platform because it mixes a MSVC/MinGW generated DLL * (for which ALLEGRO_NO_ASM is not defined) with Borland C++ compiled programs for * which ALLEGRO_NO_ASM is defined. As a result, Borland C++ compiled programs can't * use the inlined version of bmp_write_line(), bmp_read_line() and bmp_unwrite_line() * because the write_bank() and read_bank() methods of the BITMAP class don't expect * the same calling convention on both sides. */ AL_FUNC(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne)); AL_FUNC(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne)); AL_FUNC(void, bmp_unwrite_line, (BITMAP *bmp)); #else typedef AL_METHOD(uintptr_t, _BMP_BANK_SWITCHER, (BITMAP *bmp, int lyne)); typedef AL_METHOD(void, _BMP_UNBANK_SWITCHER, (BITMAP *bmp)); AL_INLINE(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne), { _BMP_BANK_SWITCHER switcher = (_BMP_BANK_SWITCHER)bmp->write_bank; return switcher(bmp, lyne); }) AL_INLINE(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne), { _BMP_BANK_SWITCHER switcher = (_BMP_BANK_SWITCHER)bmp->read_bank; return switcher(bmp, lyne); }) AL_INLINE(void, bmp_unwrite_line, (BITMAP *bmp), { _BMP_UNBANK_SWITCHER switcher = (_BMP_UNBANK_SWITCHER)bmp->vtable->unwrite_bank; switcher(bmp); }) #endif /* defined ALLEGRO_BCC32 */ #endif /* C vs. inline asm */ AL_INLINE(int, is_windowed_mode, (void), { ASSERT (gfx_driver); return gfx_driver->windowed; }) AL_INLINE(void, clear_to_color, (BITMAP *bitmap, int color), { ASSERT(bitmap); bitmap->vtable->clear_to_color(bitmap, color); }) AL_INLINE(int, bitmap_color_depth, (BITMAP *bmp), { ASSERT(bmp); return bmp->vtable->color_depth; }) AL_INLINE(int, bitmap_mask_color, (BITMAP *bmp), { ASSERT(bmp); return bmp->vtable->mask_color; }) AL_INLINE(int, is_same_bitmap, (BITMAP *bmp1, BITMAP *bmp2), { unsigned long m1; unsigned long m2; if ((!bmp1) || (!bmp2)) return FALSE; if (bmp1 == bmp2) return TRUE; m1 = bmp1->id & BMP_ID_MASK; m2 = bmp2->id & BMP_ID_MASK; return ((m1) && (m1 == m2)); }) AL_INLINE(int, is_linear_bitmap, (BITMAP *bmp), { ASSERT(bmp); return (bmp->id & BMP_ID_PLANAR) == 0; }) AL_INLINE(int, is_planar_bitmap, (BITMAP *bmp), { ASSERT(bmp); return (bmp->id & BMP_ID_PLANAR) != 0; }) AL_INLINE(int, is_memory_bitmap, (BITMAP *bmp), { ASSERT(bmp); return (bmp->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) == 0; }) AL_INLINE(int, is_screen_bitmap, (BITMAP *bmp), { ASSERT(bmp); return is_same_bitmap(bmp, screen); }) AL_INLINE(int, is_video_bitmap, (BITMAP *bmp), { ASSERT(bmp); return (bmp->id & BMP_ID_VIDEO) != 0; }) AL_INLINE(int, is_system_bitmap, (BITMAP *bmp), { ASSERT(bmp); return (bmp->id & BMP_ID_SYSTEM) != 0; }) AL_INLINE(int, is_sub_bitmap, (BITMAP *bmp), { ASSERT(bmp); return (bmp->id & BMP_ID_SUB) != 0; }) #ifdef ALLEGRO_MPW #define acquire_bitmap(bmp) #define release_bitmap(bmp) #define acquire_screen() #define release_screen() #else AL_INLINE(void, acquire_bitmap, (BITMAP *bmp), { ASSERT(bmp); if (bmp->vtable->acquire) bmp->vtable->acquire(bmp); }) AL_INLINE(void, release_bitmap, (BITMAP *bmp), { ASSERT(bmp); if (bmp->vtable->release) bmp->vtable->release(bmp); }) AL_INLINE(void, acquire_screen, (void), { acquire_bitmap(screen); }) AL_INLINE(void, release_screen, (void), { release_bitmap(screen); }) #endif AL_INLINE(int, is_inside_bitmap, (BITMAP *bmp, int x, int y, int clip), { ASSERT(bmp); if (clip) { if (bmp->clip) /* internal clipping is inclusive-exclusive */ return (x >= bmp->cl) && (y >= bmp->ct) && (x < bmp->cr) && (y < bmp->cb); else return TRUE; } else /* bitmap dimensions are always non-negative */ return (unsigned int)x < (unsigned int)bmp->w && (unsigned int)y < (unsigned int)bmp->h; }) AL_INLINE(void, get_clip_rect, (BITMAP *bitmap, int *x1, int *y_1, int *x2, int *y2), { ASSERT(bitmap); /* internal clipping is inclusive-exclusive */ *x1 = bitmap->cl; *y_1 = bitmap->ct; *x2 = bitmap->cr-1; *y2 = bitmap->cb-1; }) AL_INLINE(void, set_clip_state, (BITMAP *bitmap, int state), { ASSERT(bitmap); bitmap->clip = state; }) AL_INLINE(int, get_clip_state, (BITMAP *bitmap), { ASSERT(bitmap); return bitmap->clip; }) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_GFX_INL */ allegro-4.4.3.1/include/allegro/inline/draw.inl0000664000175000017500000003125113437077643020271 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Draw inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DRAW_INL #define ALLEGRO_DRAW_INL #include "allegro/debug.h" #include "allegro/3d.h" #include "gfx.inl" #ifdef __cplusplus extern "C" { #endif AL_INLINE(int, getpixel, (BITMAP *bmp, int x, int y), { ASSERT(bmp); return bmp->vtable->getpixel(bmp, x, y); }) AL_INLINE(void, putpixel, (BITMAP *bmp, int x, int y, int color), { ASSERT(bmp); bmp->vtable->putpixel(bmp, x, y, color); }) AL_INLINE(void, _allegro_vline, (BITMAP *bmp, int x, int y_1, int y2, int color), { ASSERT(bmp); bmp->vtable->vline(bmp, x, y_1, y2, color); }) AL_INLINE(void, _allegro_hline, (BITMAP *bmp, int x1, int y, int x2, int color), { ASSERT(bmp); bmp->vtable->hline(bmp, x1, y, x2, color); }) /* The curses API also contains functions called vline and hline so we have * called our functions _allegro_vline and _allegro_hline. User programs * should use the vline/hline aliases as they are the official names. */ #ifndef ALLEGRO_NO_VHLINE_ALIAS AL_ALIAS_VOID_RET(vline(BITMAP *bmp, int x, int y_1, int y2, int color), _allegro_vline(bmp, x, y_1, y2, color)) AL_ALIAS_VOID_RET(hline(BITMAP *bmp, int x1, int y, int x2, int color), _allegro_hline(bmp, x1, y, x2, color)) #endif AL_INLINE(void, line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), { ASSERT(bmp); bmp->vtable->line(bmp, x1, y_1, x2, y2, color); }) AL_INLINE(void, fastline, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), { ASSERT(bmp); bmp->vtable->fastline(bmp, x1, y_1, x2, y2, color); }) AL_INLINE(void, rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), { ASSERT(bmp); bmp->vtable->rectfill(bmp, x1, y_1, x2, y2, color); }) AL_INLINE(void, triangle, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color), { ASSERT(bmp); bmp->vtable->triangle(bmp, x1, y_1, x2, y2, x3, y3, color); }) AL_INLINE(void, polygon, (BITMAP *bmp, int vertices, AL_CONST int *points, int color), { ASSERT(bmp); bmp->vtable->polygon(bmp, vertices, points, color); }) AL_INLINE(void, rect, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), { ASSERT(bmp); bmp->vtable->rect(bmp, x1, y_1, x2, y2, color); }) AL_INLINE(void, circle, (BITMAP *bmp, int x, int y, int radius, int color), { ASSERT(bmp); bmp->vtable->circle(bmp, x, y, radius, color); }) AL_INLINE(void, circlefill, (BITMAP *bmp, int x, int y, int radius, int color), { ASSERT(bmp); bmp->vtable->circlefill(bmp, x, y, radius, color); }) AL_INLINE(void, ellipse, (BITMAP *bmp, int x, int y, int rx, int ry, int color), { ASSERT(bmp); bmp->vtable->ellipse(bmp, x, y, rx, ry, color); }) AL_INLINE(void, ellipsefill, (BITMAP *bmp, int x, int y, int rx, int ry, int color), { ASSERT(bmp); bmp->vtable->ellipsefill(bmp, x, y, rx, ry, color); }) AL_INLINE(void, arc, (BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color), { ASSERT(bmp); bmp->vtable->arc(bmp, x, y, ang1, ang2, r, color); }) AL_INLINE(void, spline, (BITMAP *bmp, AL_CONST int points[8], int color), { ASSERT(bmp); bmp->vtable->spline(bmp, points, color); }) AL_INLINE(void, floodfill, (BITMAP *bmp, int x, int y, int color), { ASSERT(bmp); bmp->vtable->floodfill(bmp, x, y, color); }) AL_INLINE(void, polygon3d, (BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]), { ASSERT(bmp); bmp->vtable->polygon3d(bmp, type, texture, vc, vtx); }) AL_INLINE(void, polygon3d_f, (BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]), { ASSERT(bmp); bmp->vtable->polygon3d_f(bmp, type, texture, vc, vtx); }) AL_INLINE(void, triangle3d, (BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3), { ASSERT(bmp); bmp->vtable->triangle3d(bmp, type, texture, v1, v2, v3); }) AL_INLINE(void, triangle3d_f, (BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3), { ASSERT(bmp); bmp->vtable->triangle3d_f(bmp, type, texture, v1, v2, v3); }) AL_INLINE(void, quad3d, (BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4), { ASSERT(bmp); bmp->vtable->quad3d(bmp, type, texture, v1, v2, v3, v4); }) AL_INLINE(void, quad3d_f, (BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4), { ASSERT(bmp); bmp->vtable->quad3d_f(bmp, type, texture, v1, v2, v3, v4); }) AL_INLINE(void, draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), { ASSERT(bmp); ASSERT(sprite); if (sprite->vtable->color_depth == 8) { bmp->vtable->draw_256_sprite(bmp, sprite, x, y); } else { ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_sprite(bmp, sprite, x, y); } }) AL_INLINE(void, draw_sprite_ex, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip), { ASSERT(bmp); ASSERT(sprite); if (mode == DRAW_SPRITE_TRANS) { ASSERT((bmp->vtable->color_depth == sprite->vtable->color_depth) || (sprite->vtable->color_depth == 32) || ((sprite->vtable->color_depth == 8) && (bmp->vtable->color_depth == 32))); bmp->vtable->draw_sprite_ex(bmp, sprite, x, y, mode, flip); } else { ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_sprite_ex(bmp, sprite, x, y, mode, flip); } }) AL_INLINE(void, draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y),{ ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_sprite_v_flip(bmp, sprite, x, y); }) AL_INLINE(void, draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y),{ ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_sprite_h_flip(bmp, sprite, x, y); }) AL_INLINE(void, draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y), { ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_sprite_vh_flip(bmp, sprite, x, y); }) AL_INLINE(void, draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), { ASSERT(bmp); ASSERT(sprite); if (sprite->vtable->color_depth == 32) { ASSERT(bmp->vtable->draw_trans_rgba_sprite); bmp->vtable->draw_trans_rgba_sprite(bmp, sprite, x, y); } else { ASSERT((bmp->vtable->color_depth == sprite->vtable->color_depth) || ((bmp->vtable->color_depth == 32) && (sprite->vtable->color_depth == 8))); bmp->vtable->draw_trans_sprite(bmp, sprite, x, y); } }) AL_INLINE(void, draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color), { ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_lit_sprite(bmp, sprite, x, y, color); }) AL_INLINE(void, draw_gouraud_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4), { ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp->vtable->draw_gouraud_sprite(bmp, sprite, x, y, c1, c2, c3, c4); }) AL_INLINE(void, draw_character_ex, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg), { ASSERT(bmp); ASSERT(sprite); ASSERT(sprite->vtable->color_depth == 8); bmp->vtable->draw_character(bmp, sprite, x, y, color, bg); }) AL_INLINE(void, rotate_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000, FALSE); }) AL_INLINE(void, rotate_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000, TRUE); }) AL_INLINE(void, rotate_scaled_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, (y<<16) + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, FALSE); }) AL_INLINE(void, rotate_scaled_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, (y<<16) + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, TRUE); }) AL_INLINE(void, pivot_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, FALSE); }) AL_INLINE(void, pivot_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, TRUE); }) AL_INLINE(void, pivot_scaled_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, FALSE); }) AL_INLINE(void, pivot_scaled_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale), { ASSERT(bmp); ASSERT(sprite); bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, TRUE); }) AL_INLINE(void, _putpixel, (BITMAP *bmp, int x, int y, int color), { uintptr_t addr; bmp_select(bmp); addr = bmp_write_line(bmp, y); bmp_write8(addr+x, color); bmp_unwrite_line(bmp); }) AL_INLINE(int, _getpixel, (BITMAP *bmp, int x, int y), { uintptr_t addr; int c; bmp_select(bmp); addr = bmp_read_line(bmp, y); c = bmp_read8(addr+x); bmp_unwrite_line(bmp); return c; }) AL_INLINE(void, _putpixel15, (BITMAP *bmp, int x, int y, int color), { uintptr_t addr; bmp_select(bmp); addr = bmp_write_line(bmp, y); bmp_write15(addr+x*sizeof(short), color); bmp_unwrite_line(bmp); }) AL_INLINE(int, _getpixel15, (BITMAP *bmp, int x, int y), { uintptr_t addr; int c; bmp_select(bmp); addr = bmp_read_line(bmp, y); c = bmp_read15(addr+x*sizeof(short)); bmp_unwrite_line(bmp); return c; }) AL_INLINE(void, _putpixel16, (BITMAP *bmp, int x, int y, int color), { uintptr_t addr; bmp_select(bmp); addr = bmp_write_line(bmp, y); bmp_write16(addr+x*sizeof(short), color); bmp_unwrite_line(bmp); }) AL_INLINE(int, _getpixel16, (BITMAP *bmp, int x, int y), { uintptr_t addr; int c; bmp_select(bmp); addr = bmp_read_line(bmp, y); c = bmp_read16(addr+x*sizeof(short)); bmp_unwrite_line(bmp); return c; }) AL_INLINE(void, _putpixel24, (BITMAP *bmp, int x, int y, int color), { uintptr_t addr; bmp_select(bmp); addr = bmp_write_line(bmp, y); bmp_write24(addr+x*3, color); bmp_unwrite_line(bmp); }) AL_INLINE(int, _getpixel24, (BITMAP *bmp, int x, int y), { uintptr_t addr; int c; bmp_select(bmp); addr = bmp_read_line(bmp, y); c = bmp_read24(addr+x*3); bmp_unwrite_line(bmp); return c; }) AL_INLINE(void, _putpixel32, (BITMAP *bmp, int x, int y, int color), { uintptr_t addr; bmp_select(bmp); addr = bmp_write_line(bmp, y); bmp_write32(addr+x*sizeof(int32_t), color); bmp_unwrite_line(bmp); }) AL_INLINE(int, _getpixel32, (BITMAP *bmp, int x, int y), { uintptr_t addr; int c; bmp_select(bmp); addr = bmp_read_line(bmp, y); c = bmp_read32(addr+x*sizeof(int32_t)); bmp_unwrite_line(bmp); return c; }) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_DRAW_INL */ allegro-4.4.3.1/include/allegro/inline/fmaths.inl0000664000175000017500000001132613437077643020617 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fixed point math inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FMATHS_INL #define ALLEGRO_FMATHS_INL #define ALLEGRO_IMPORT_MATH_ASM #include "asm.inl" #undef ALLEGRO_IMPORT_MATH_ASM #ifdef __cplusplus extern "C" { #endif /* ftofix and fixtof are used in generic C versions of fixmul and fixdiv */ AL_INLINE(fixed, ftofix, (double x), { if (x > 32767.0) { *allegro_errno = ERANGE; return 0x7FFFFFFF; } if (x < -32767.0) { *allegro_errno = ERANGE; return -0x7FFFFFFF; } return (fixed)(x * 65536.0 + (x < 0 ? -0.5 : 0.5)); }) AL_INLINE(double, fixtof, (fixed x), { return (double)x / 65536.0; }) #ifdef ALLEGRO_NO_ASM /* use generic C versions */ AL_INLINE(fixed, fixadd, (fixed x, fixed y), { fixed result = x + y; if (result >= 0) { if ((x < 0) && (y < 0)) { *allegro_errno = ERANGE; return -0x7FFFFFFF; } else return result; } else { if ((x > 0) && (y > 0)) { *allegro_errno = ERANGE; return 0x7FFFFFFF; } else return result; } }) AL_INLINE(fixed, fixsub, (fixed x, fixed y), { fixed result = x - y; if (result >= 0) { if ((x < 0) && (y > 0)) { *allegro_errno = ERANGE; return -0x7FFFFFFF; } else return result; } else { if ((x > 0) && (y < 0)) { *allegro_errno = ERANGE; return 0x7FFFFFFF; } else return result; } }) /* In benchmarks conducted circa May 2005 we found that, in the main: * - IA32 machines performed faster with one implementation; * - AMD64 and G4 machines performed faster with another implementation. * * Benchmarks were mainly done with differing versions of gcc. * Results varied with other compilers, optimisation levels, etc. * so this is not optimal, though a tenable compromise. * * Note that the following implementation are NOT what were benchmarked. * We had forgotten to put in overflow detection in those versions. * If you don't need overflow detection then previous versions in the * CVS tree might be worth looking at. * * PS. Don't move the #ifs inside the AL_INLINE; BCC doesn't like it. */ #if (defined ALLEGRO_I386) || (!defined LONG_LONG) AL_INLINE(fixed, fixmul, (fixed x, fixed y), { return ftofix(fixtof(x) * fixtof(y)); }) #else AL_INLINE(fixed, fixmul, (fixed x, fixed y), { LONG_LONG lx = x; LONG_LONG ly = y; LONG_LONG lres = (lx*ly); if (lres > 0x7FFFFFFF0000LL) { *allegro_errno = ERANGE; return 0x7FFFFFFF; } else if (lres < -0x7FFFFFFF0000LL) { *allegro_errno = ERANGE; return 0x80000000; } else { int res = lres >> 16; return res; } }) #endif /* fixmul() C implementations */ AL_INLINE(fixed, fixdiv, (fixed x, fixed y), { if (y == 0) { *allegro_errno = ERANGE; return (x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF; } else return ftofix(fixtof(x) / fixtof(y)); }) AL_INLINE(int, fixfloor, (fixed x), { /* (x >> 16) is not portable */ if (x >= 0) return (x >> 16); else return ~((~x) >> 16); }) AL_INLINE(int, fixceil, (fixed x), { if (x > 0x7FFF0000) { *allegro_errno = ERANGE; return 0x7FFF; } return fixfloor(x + 0xFFFF); }) #endif /* C vs. inline asm */ AL_INLINE(fixed, itofix, (int x), { return x << 16; }) AL_INLINE(int, fixtoi, (fixed x), { return fixfloor(x) + ((x & 0x8000) >> 15); }) AL_INLINE(fixed, fixcos, (fixed x), { return _cos_tbl[((x + 0x4000) >> 15) & 0x1FF]; }) AL_INLINE(fixed, fixsin, (fixed x), { return _cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF]; }) AL_INLINE(fixed, fixtan, (fixed x), { return _tan_tbl[((x + 0x4000) >> 15) & 0xFF]; }) AL_INLINE(fixed, fixacos, (fixed x), { if ((x < -65536) || (x > 65536)) { *allegro_errno = EDOM; return 0; } return _acos_tbl[(x+65536+127)>>8]; }) AL_INLINE(fixed, fixasin, (fixed x), { if ((x < -65536) || (x > 65536)) { *allegro_errno = EDOM; return 0; } return 0x00400000 - _acos_tbl[(x+65536+127)>>8]; }) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_FMATHS_INL */ allegro-4.4.3.1/include/allegro/inline/3dmaths.inl0000664000175000017500000000305313437077643020676 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 3D maths inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_3DMATHS_INL #define ALLEGRO_3DMATHS_INL #ifdef __cplusplus extern "C" { #endif AL_INLINE(fixed, dot_product, (fixed x1, fixed y_1, fixed z1, fixed x2, fixed y2, fixed z2), { return fixmul(x1, x2) + fixmul(y_1, y2) + fixmul(z1, z2); }) AL_INLINE(float, dot_product_f, (float x1, float y_1, float z1, float x2, float y2, float z2), { return (x1 * x2) + (y_1 * y2) + (z1 * z2); }) AL_INLINE(void, persp_project, (fixed x, fixed y, fixed z, fixed *xout, fixed *yout), { *xout = fixmul(fixdiv(x, z), _persp_xscale) + _persp_xoffset; *yout = fixmul(fixdiv(y, z), _persp_yscale) + _persp_yoffset; }) AL_INLINE(void, persp_project_f, (float x, float y, float z, float *xout, float *yout), { float z1 = 1.0f / z; *xout = ((x * z1) * _persp_xscale_f) + _persp_xoffset_f; *yout = ((y * z1) * _persp_yscale_f) + _persp_yoffset_f; }) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_3DMATHS_INL */ allegro-4.4.3.1/include/allegro/inline/rle.inl0000664000175000017500000000344213437077643020117 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * RLE sprite inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_RLE_INL #define ALLEGRO_RLE_INL #include "allegro/debug.h" #ifdef __cplusplus extern "C" { #endif AL_INLINE(void, draw_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y), { ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->color_depth); bmp->vtable->draw_rle_sprite(bmp, sprite, x, y); }) AL_INLINE(void, draw_trans_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y), { ASSERT(bmp); ASSERT(sprite); if (sprite->color_depth == 32) { ASSERT(bmp->vtable->draw_trans_rgba_rle_sprite); bmp->vtable->draw_trans_rgba_rle_sprite(bmp, sprite, x, y); } else { ASSERT(bmp->vtable->color_depth == sprite->color_depth); bmp->vtable->draw_trans_rle_sprite(bmp, sprite, x, y); } }) AL_INLINE(void, draw_lit_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color), { ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->color_depth); bmp->vtable->draw_lit_rle_sprite(bmp, sprite, x, y, color); }) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_RLE_INL */ allegro-4.4.3.1/include/allegro/inline/fix.inl0000664000175000017500000003016113437077643020121 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fix class inline functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FIX_INL #define ALLEGRO_FIX_INL #ifdef __cplusplus inline fix operator + (const fix x, const fix y) { fix t; t.v = x.v + y.v; return t; } inline fix operator + (const fix x, const int y) { fix t; t.v = x.v + itofix(y); return t; } inline fix operator + (const int x, const fix y) { fix t; t.v = itofix(x) + y.v; return t; } inline fix operator + (const fix x, const long y) { fix t; t.v = x.v + itofix(y); return t; } inline fix operator + (const long x, const fix y) { fix t; t.v = itofix(x) + y.v; return t; } inline fix operator + (const fix x, const float y) { fix t; t.v = x.v + ftofix(y); return t; } inline fix operator + (const float x, const fix y) { fix t; t.v = ftofix(x) + y.v; return t; } inline fix operator + (const fix x, const double y) { fix t; t.v = x.v + ftofix(y); return t; } inline fix operator + (const double x, const fix y) { fix t; t.v = ftofix(x) + y.v; return t; } inline fix operator - (const fix x, const fix y) { fix t; t.v = x.v - y.v; return t; } inline fix operator - (const fix x, const int y) { fix t; t.v = x.v - itofix(y); return t; } inline fix operator - (const int x, const fix y) { fix t; t.v = itofix(x) - y.v; return t; } inline fix operator - (const fix x, const long y) { fix t; t.v = x.v - itofix(y); return t; } inline fix operator - (const long x, const fix y) { fix t; t.v = itofix(x) - y.v; return t; } inline fix operator - (const fix x, const float y) { fix t; t.v = x.v - ftofix(y); return t; } inline fix operator - (const float x, const fix y) { fix t; t.v = ftofix(x) - y.v; return t; } inline fix operator - (const fix x, const double y) { fix t; t.v = x.v - ftofix(y); return t; } inline fix operator - (const double x, const fix y) { fix t; t.v = ftofix(x) - y.v; return t; } inline fix operator * (const fix x, const fix y) { fix t; t.v = fixmul(x.v, y.v); return t; } inline fix operator * (const fix x, const int y) { fix t; t.v = x.v * y; return t; } inline fix operator * (const int x, const fix y) { fix t; t.v = x * y.v; return t; } inline fix operator * (const fix x, const long y) { fix t; t.v = x.v * y; return t; } inline fix operator * (const long x, const fix y) { fix t; t.v = x * y.v; return t; } inline fix operator * (const fix x, const float y) { fix t; t.v = ftofix(fixtof(x.v) * y); return t; } inline fix operator * (const float x, const fix y) { fix t; t.v = ftofix(x * fixtof(y.v)); return t; } inline fix operator * (const fix x, const double y) { fix t; t.v = ftofix(fixtof(x.v) * y); return t; } inline fix operator * (const double x, const fix y) { fix t; t.v = ftofix(x * fixtof(y.v)); return t; } inline fix operator / (const fix x, const fix y) { fix t; t.v = fixdiv(x.v, y.v); return t; } inline fix operator / (const fix x, const int y) { fix t; t.v = x.v / y; return t; } inline fix operator / (const int x, const fix y) { fix t; t.v = fixdiv(itofix(x), y.v); return t; } inline fix operator / (const fix x, const long y) { fix t; t.v = x.v / y; return t; } inline fix operator / (const long x, const fix y) { fix t; t.v = fixdiv(itofix(x), y.v); return t; } inline fix operator / (const fix x, const float y) { fix t; t.v = ftofix(fixtof(x.v) / y); return t; } inline fix operator / (const float x, const fix y) { fix t; t.v = ftofix(x / fixtof(y.v)); return t; } inline fix operator / (const fix x, const double y) { fix t; t.v = ftofix(fixtof(x.v) / y); return t; } inline fix operator / (const double x, const fix y) { fix t; t.v = ftofix(x / fixtof(y.v)); return t; } inline fix operator << (const fix x, const int y) { fix t; t.v = x.v << y; return t; } inline fix operator >> (const fix x, const int y) { fix t; t.v = x.v >> y; return t; } inline int operator == (const fix x, const fix y) { return (x.v == y.v); } inline int operator == (const fix x, const int y) { return (x.v == itofix(y)); } inline int operator == (const int x, const fix y) { return (itofix(x) == y.v); } inline int operator == (const fix x, const long y) { return (x.v == itofix(y)); } inline int operator == (const long x, const fix y) { return (itofix(x) == y.v); } inline int operator == (const fix x, const float y) { return (x.v == ftofix(y)); } inline int operator == (const float x, const fix y) { return (ftofix(x) == y.v); } inline int operator == (const fix x, const double y) { return (x.v == ftofix(y)); } inline int operator == (const double x, const fix y) { return (ftofix(x) == y.v); } inline int operator != (const fix x, const fix y) { return (x.v != y.v); } inline int operator != (const fix x, const int y) { return (x.v != itofix(y)); } inline int operator != (const int x, const fix y) { return (itofix(x) != y.v); } inline int operator != (const fix x, const long y) { return (x.v != itofix(y)); } inline int operator != (const long x, const fix y) { return (itofix(x) != y.v); } inline int operator != (const fix x, const float y) { return (x.v != ftofix(y)); } inline int operator != (const float x, const fix y) { return (ftofix(x) != y.v); } inline int operator != (const fix x, const double y) { return (x.v != ftofix(y)); } inline int operator != (const double x, const fix y) { return (ftofix(x) != y.v); } inline int operator < (const fix x, const fix y) { return (x.v < y.v); } inline int operator < (const fix x, const int y) { return (x.v < itofix(y)); } inline int operator < (const int x, const fix y) { return (itofix(x) < y.v); } inline int operator < (const fix x, const long y) { return (x.v < itofix(y)); } inline int operator < (const long x, const fix y) { return (itofix(x) < y.v); } inline int operator < (const fix x, const float y) { return (x.v < ftofix(y)); } inline int operator < (const float x, const fix y) { return (ftofix(x) < y.v); } inline int operator < (const fix x, const double y) { return (x.v < ftofix(y)); } inline int operator < (const double x, const fix y) { return (ftofix(x) < y.v); } inline int operator > (const fix x, const fix y) { return (x.v > y.v); } inline int operator > (const fix x, const int y) { return (x.v > itofix(y)); } inline int operator > (const int x, const fix y) { return (itofix(x) > y.v); } inline int operator > (const fix x, const long y) { return (x.v > itofix(y)); } inline int operator > (const long x, const fix y) { return (itofix(x) > y.v); } inline int operator > (const fix x, const float y) { return (x.v > ftofix(y)); } inline int operator > (const float x, const fix y) { return (ftofix(x) > y.v); } inline int operator > (const fix x, const double y) { return (x.v > ftofix(y)); } inline int operator > (const double x, const fix y) { return (ftofix(x) > y.v); } inline int operator <= (const fix x, const fix y) { return (x.v <= y.v); } inline int operator <= (const fix x, const int y) { return (x.v <= itofix(y)); } inline int operator <= (const int x, const fix y) { return (itofix(x) <= y.v); } inline int operator <= (const fix x, const long y) { return (x.v <= itofix(y)); } inline int operator <= (const long x, const fix y) { return (itofix(x) <= y.v); } inline int operator <= (const fix x, const float y) { return (x.v <= ftofix(y)); } inline int operator <= (const float x, const fix y) { return (ftofix(x) <= y.v); } inline int operator <= (const fix x, const double y) { return (x.v <= ftofix(y)); } inline int operator <= (const double x, const fix y) { return (ftofix(x) <= y.v); } inline int operator >= (const fix x, const fix y) { return (x.v >= y.v); } inline int operator >= (const fix x, const int y) { return (x.v >= itofix(y)); } inline int operator >= (const int x, const fix y) { return (itofix(x) >= y.v); } inline int operator >= (const fix x, const long y) { return (x.v >= itofix(y)); } inline int operator >= (const long x, const fix y) { return (itofix(x) >= y.v); } inline int operator >= (const fix x, const float y) { return (x.v >= ftofix(y)); } inline int operator >= (const float x, const fix y) { return (ftofix(x) >= y.v); } inline int operator >= (const fix x, const double y) { return (x.v >= ftofix(y)); } inline int operator >= (const double x, const fix y) { return (ftofix(x) >= y.v); } inline fix sqrt(fix x) { fix t; t.v = fixsqrt(x.v); return t; } inline fix cos(fix x) { fix t; t.v = fixcos(x.v); return t; } inline fix sin(fix x) { fix t; t.v = fixsin(x.v); return t; } inline fix tan(fix x) { fix t; t.v = fixtan(x.v); return t; } inline fix acos(fix x) { fix t; t.v = fixacos(x.v); return t; } inline fix asin(fix x) { fix t; t.v = fixasin(x.v); return t; } inline fix atan(fix x) { fix t; t.v = fixatan(x.v); return t; } inline fix atan2(fix x, fix y) { fix t; t.v = fixatan2(x.v, y.v); return t; } inline void get_translation_matrix(MATRIX *m, fix x, fix y, fix z) { get_translation_matrix(m, x.v, y.v, z.v); } inline void get_scaling_matrix(MATRIX *m, fix x, fix y, fix z) { get_scaling_matrix(m, x.v, y.v, z.v); } inline void get_x_rotate_matrix(MATRIX *m, fix r) { get_x_rotate_matrix(m, r.v); } inline void get_y_rotate_matrix(MATRIX *m, fix r) { get_y_rotate_matrix(m, r.v); } inline void get_z_rotate_matrix(MATRIX *m, fix r) { get_z_rotate_matrix(m, r.v); } inline void get_rotation_matrix(MATRIX *m, fix x, fix y, fix z) { get_rotation_matrix(m, x.v, y.v, z.v); } inline void get_align_matrix(MATRIX *m, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup) { get_align_matrix(m, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v); } inline void get_vector_rotation_matrix(MATRIX *m, fix x, fix y, fix z, fix a) { get_vector_rotation_matrix(m, x.v, y.v, z.v, a.v); } inline void get_transformation_matrix(MATRIX *m, fix scale, fix xrot, fix yrot, fix zrot, fix x, fix y, fix z) { get_transformation_matrix(m, scale.v, xrot.v, yrot.v, zrot.v, x.v, y.v, z.v); } inline void get_camera_matrix(MATRIX *m, fix x, fix y, fix z, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup, fix fov, fix aspect) { get_camera_matrix(m, x.v, y.v, z.v, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v, fov.v, aspect.v); } inline void qtranslate_matrix(MATRIX *m, fix x, fix y, fix z) { qtranslate_matrix(m, x.v, y.v, z.v); } inline void qscale_matrix(MATRIX *m, fix scale) { qscale_matrix(m, scale.v); } inline fix vector_length(fix x, fix y, fix z) { fix t; t.v = vector_length(x.v, y.v, z.v); return t; } inline void normalize_vector(fix *x, fix *y, fix *z) { normalize_vector(&x->v, &y->v, &z->v); } inline void cross_product(fix x1, fix y_1, fix z1, fix x2, fix y2, fix z2, fix *xout, fix *yout, fix *zout) { cross_product(x1.v, y_1.v, z1.v, x2.v, y2.v, z2.v, &xout->v, &yout->v, &zout->v); } inline fix dot_product(fix x1, fix y_1, fix z1, fix x2, fix y2, fix z2) { fix t; t.v = dot_product(x1.v, y_1.v, z1.v, x2.v, y2.v, z2.v); return t; } inline void apply_matrix(MATRIX *m, fix x, fix y, fix z, fix *xout, fix *yout, fix *zout) { apply_matrix(m, x.v, y.v, z.v, &xout->v, &yout->v, &zout->v); } inline void persp_project(fix x, fix y, fix z, fix *xout, fix *yout) { persp_project(x.v, y.v, z.v, &xout->v, &yout->v); } #endif /* ifdef __cplusplus */ #endif /* ifndef ALLEGRO_FIX_INL */ allegro-4.4.3.1/include/allegro/inline/asm.inl0000664000175000017500000000255313437077643020117 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Imports asm definitions of various inline functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifdef __cplusplus extern "C" { #endif #ifndef ALLEGRO_NO_ASM #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) /* use i386 asm, GCC syntax */ #include "allegro/platform/al386gcc.h" #elif (defined ALLEGRO_MSVC) && (defined ALLEGRO_I386) /* use i386 asm, MSVC syntax */ #include "allegro/platform/al386vc.h" #elif (defined ALLEGRO_WATCOM) && (defined ALLEGRO_I386) /* use i386 asm, Watcom syntax */ #include "allegro/platform/al386wat.h" #else /* asm not supported */ #define ALLEGRO_NO_ASM #endif #endif /* Define ALLEGRO_USE_C for backwards compatibility. It should not be used * anywhere else in the sources for now. */ #ifdef ALLEGRO_NO_ASM #define ALLEGRO_USE_C #endif #ifdef __cplusplus } #endif allegro-4.4.3.1/include/allegro/inline/color.inl0000664000175000017500000000623213437077643020453 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Color inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_COLOR_INL #define ALLEGRO_COLOR_INL #ifdef __cplusplus extern "C" { #endif AL_INLINE(int, makecol15, (int r, int g, int b), { return (((r >> 3) << _rgb_r_shift_15) | ((g >> 3) << _rgb_g_shift_15) | ((b >> 3) << _rgb_b_shift_15)); }) AL_INLINE(int, makecol16, (int r, int g, int b), { return (((r >> 3) << _rgb_r_shift_16) | ((g >> 2) << _rgb_g_shift_16) | ((b >> 3) << _rgb_b_shift_16)); }) AL_INLINE(int, makecol24, (int r, int g, int b), { return ((r << _rgb_r_shift_24) | (g << _rgb_g_shift_24) | (b << _rgb_b_shift_24)); }) AL_INLINE(int, makecol32, (int r, int g, int b), { return ((r << _rgb_r_shift_32) | (g << _rgb_g_shift_32) | (b << _rgb_b_shift_32)); }) AL_INLINE(int, makeacol32, (int r, int g, int b, int a), { return ((r << _rgb_r_shift_32) | (g << _rgb_g_shift_32) | (b << _rgb_b_shift_32) | (a << _rgb_a_shift_32)); }) AL_INLINE(int, getr8, (int c), { return _rgb_scale_6[(int)_current_palette[c].r]; }) AL_INLINE(int, getg8, (int c), { return _rgb_scale_6[(int)_current_palette[c].g]; }) AL_INLINE(int, getb8, (int c), { return _rgb_scale_6[(int)_current_palette[c].b]; }) AL_INLINE(int, getr15, (int c), { return _rgb_scale_5[(c >> _rgb_r_shift_15) & 0x1F]; }) AL_INLINE(int, getg15, (int c), { return _rgb_scale_5[(c >> _rgb_g_shift_15) & 0x1F]; }) AL_INLINE(int, getb15, (int c), { return _rgb_scale_5[(c >> _rgb_b_shift_15) & 0x1F]; }) AL_INLINE(int, getr16, (int c), { return _rgb_scale_5[(c >> _rgb_r_shift_16) & 0x1F]; }) AL_INLINE(int, getg16, (int c), { return _rgb_scale_6[(c >> _rgb_g_shift_16) & 0x3F]; }) AL_INLINE(int, getb16, (int c), { return _rgb_scale_5[(c >> _rgb_b_shift_16) & 0x1F]; }) AL_INLINE(int, getr24, (int c), { return ((c >> _rgb_r_shift_24) & 0xFF); }) AL_INLINE(int, getg24, (int c), { return ((c >> _rgb_g_shift_24) & 0xFF); }) AL_INLINE(int, getb24, (int c), { return ((c >> _rgb_b_shift_24) & 0xFF); }) AL_INLINE(int, getr32, (int c), { return ((c >> _rgb_r_shift_32) & 0xFF); }) AL_INLINE(int, getg32, (int c), { return ((c >> _rgb_g_shift_32) & 0xFF); }) AL_INLINE(int, getb32, (int c), { return ((c >> _rgb_b_shift_32) & 0xFF); }) AL_INLINE(int, geta32, (int c), { return ((c >> _rgb_a_shift_32) & 0xFF); }) #ifndef ALLEGRO_DOS AL_INLINE(void, _set_color, (int idx, AL_CONST RGB *p), { set_color(idx, p); }) #endif #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_COLOR_INL */ allegro-4.4.3.1/include/allegro/inline/system.inl0000664000175000017500000000264213437077643020662 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * System inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_SYSTEM_INL #define ALLEGRO_SYSTEM_INL #include "allegro/debug.h" #ifdef __cplusplus extern "C" { #endif AL_INLINE(void, set_window_title, (AL_CONST char *name), { ASSERT(system_driver); if (system_driver->set_window_title) system_driver->set_window_title(name); }) AL_INLINE(int, desktop_color_depth, (void), { ASSERT(system_driver); if (system_driver->desktop_color_depth) return system_driver->desktop_color_depth(); else return 0; }) AL_INLINE(int, get_desktop_resolution, (int *width, int *height), { ASSERT(system_driver); if (system_driver->get_desktop_resolution) return system_driver->get_desktop_resolution(width, height); else return -1; }) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_SYSTEM_INL */ allegro-4.4.3.1/include/allegro/inline/matrix.inl0000664000175000017500000000230013437077643020631 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Matrix math inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_MATRIX_INL #define ALLEGRO_MATRIX_INL #ifdef __cplusplus extern "C" { #endif #define CALC_ROW(n) (fixmul(x, m->v[n][0]) + \ fixmul(y, m->v[n][1]) + \ fixmul(z, m->v[n][2]) + \ m->t[n]) AL_INLINE(void, apply_matrix, (MATRIX *m, fixed x, fixed y, fixed z, fixed *xout, fixed *yout, fixed *zout), { *xout = CALC_ROW(0); *yout = CALC_ROW(1); *zout = CALC_ROW(2); }) #undef CALC_ROW #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_MATRIX_INL */ allegro-4.4.3.1/include/allegro/matrix.h0000664000175000017500000000734013437077643017031 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Matrix math routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_MATRIX_H #define ALLEGRO_MATRIX_H #include "base.h" #include "fixed.h" #include "fmaths.h" #ifdef __cplusplus extern "C" { #endif typedef struct MATRIX /* transformation matrix (fixed point) */ { fixed v[3][3]; /* scaling and rotation */ fixed t[3]; /* translation */ } MATRIX; typedef struct MATRIX_f /* transformation matrix (floating point) */ { float v[3][3]; /* scaling and rotation */ float t[3]; /* translation */ } MATRIX_f; AL_VAR(MATRIX, identity_matrix); AL_VAR(MATRIX_f, identity_matrix_f); AL_FUNC(void, get_translation_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); AL_FUNC(void, get_translation_matrix_f, (MATRIX_f *m, float x, float y, float z)); AL_FUNC(void, get_scaling_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); AL_FUNC(void, get_scaling_matrix_f, (MATRIX_f *m, float x, float y, float z)); AL_FUNC(void, get_x_rotate_matrix, (MATRIX *m, fixed r)); AL_FUNC(void, get_x_rotate_matrix_f, (MATRIX_f *m, float r)); AL_FUNC(void, get_y_rotate_matrix, (MATRIX *m, fixed r)); AL_FUNC(void, get_y_rotate_matrix_f, (MATRIX_f *m, float r)); AL_FUNC(void, get_z_rotate_matrix, (MATRIX *m, fixed r)); AL_FUNC(void, get_z_rotate_matrix_f, (MATRIX_f *m, float r)); AL_FUNC(void, get_rotation_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); AL_FUNC(void, get_rotation_matrix_f, (MATRIX_f *m, float x, float y, float z)); AL_FUNC(void, get_align_matrix, (MATRIX *m, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup)); AL_FUNC(void, get_align_matrix_f, (MATRIX_f *m, float xfront, float yfront, float zfront, float xup, float yup, float zup)); AL_FUNC(void, get_vector_rotation_matrix, (MATRIX *m, fixed x, fixed y, fixed z, fixed a)); AL_FUNC(void, get_vector_rotation_matrix_f, (MATRIX_f *m, float x, float y, float z, float a)); AL_FUNC(void, get_transformation_matrix, (MATRIX *m, fixed scale, fixed xrot, fixed yrot, fixed zrot, fixed x, fixed y, fixed z)); AL_FUNC(void, get_transformation_matrix_f, (MATRIX_f *m, float scale, float xrot, float yrot, float zrot, float x, float y, float z)); AL_FUNC(void, get_camera_matrix, (MATRIX *m, fixed x, fixed y, fixed z, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup, fixed fov, fixed aspect)); AL_FUNC(void, get_camera_matrix_f, (MATRIX_f *m, float x, float y, float z, float xfront, float yfront, float zfront, float xup, float yup, float zup, float fov, float aspect)); AL_FUNC(void, qtranslate_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); AL_FUNC(void, qtranslate_matrix_f, (MATRIX_f *m, float x, float y, float z)); AL_FUNC(void, qscale_matrix, (MATRIX *m, fixed scale)); AL_FUNC(void, qscale_matrix_f, (MATRIX_f *m, float scale)); AL_FUNC(void, matrix_mul, (AL_CONST MATRIX *m1, AL_CONST MATRIX *m2, MATRIX *out)); AL_FUNC(void, matrix_mul_f, (AL_CONST MATRIX_f *m1, AL_CONST MATRIX_f *m2, MATRIX_f *out)); AL_FUNC(void, apply_matrix_f, (AL_CONST MATRIX_f *m, float x, float y, float z, float *xout, float *yout, float *zout)); #ifdef __cplusplus } #endif #include "inline/matrix.inl" #endif /* ifndef ALLEGRO_MATRIX_H */ allegro-4.4.3.1/include/allegro/color.h0000664000175000017500000001366613437077643016653 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Color manipulation routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_COLOR_H #define ALLEGRO_COLOR_H #include "base.h" #include "palette.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; AL_VAR(PALETTE, black_palette); AL_VAR(PALETTE, desktop_palette); AL_VAR(PALETTE, default_palette); typedef struct { unsigned char data[32][32][32]; } RGB_MAP; typedef struct { unsigned char data[PAL_SIZE][PAL_SIZE]; } COLOR_MAP; AL_VAR(RGB_MAP *, rgb_map); AL_VAR(COLOR_MAP *, color_map); AL_VAR(PALETTE, _current_palette); AL_VAR(int, _rgb_r_shift_15); AL_VAR(int, _rgb_g_shift_15); AL_VAR(int, _rgb_b_shift_15); AL_VAR(int, _rgb_r_shift_16); AL_VAR(int, _rgb_g_shift_16); AL_VAR(int, _rgb_b_shift_16); AL_VAR(int, _rgb_r_shift_24); AL_VAR(int, _rgb_g_shift_24); AL_VAR(int, _rgb_b_shift_24); AL_VAR(int, _rgb_r_shift_32); AL_VAR(int, _rgb_g_shift_32); AL_VAR(int, _rgb_b_shift_32); AL_VAR(int, _rgb_a_shift_32); AL_ARRAY(int, _rgb_scale_5); AL_ARRAY(int, _rgb_scale_6); #define MASK_COLOR_8 0 #define MASK_COLOR_15 0x7C1F #define MASK_COLOR_16 0xF81F #define MASK_COLOR_24 0xFF00FF #define MASK_COLOR_32 0xFF00FF AL_VAR(int *, palette_color); AL_FUNC(void, set_color, (int idx, AL_CONST RGB *p)); AL_FUNC(void, set_palette, (AL_CONST PALETTE p)); AL_FUNC(void, set_palette_range, (AL_CONST PALETTE p, int from, int to, int retracesync)); AL_FUNC(void, get_color, (int idx, RGB *p)); AL_FUNC(void, get_palette, (PALETTE p)); AL_FUNC(void, get_palette_range, (PALETTE p, int from, int to)); AL_FUNC(void, fade_interpolate, (AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to)); AL_FUNC(void, fade_from_range, (AL_CONST PALETTE source, AL_CONST PALETTE dest, int speed, int from, int to)); AL_FUNC(void, fade_in_range, (AL_CONST PALETTE p, int speed, int from, int to)); AL_FUNC(void, fade_out_range, (int speed, int from, int to)); AL_FUNC(void, fade_from, (AL_CONST PALETTE source, AL_CONST PALETTE dest, int speed)); AL_FUNC(void, fade_in, (AL_CONST PALETTE p, int speed)); AL_FUNC(void, fade_out, (int speed)); AL_FUNC(void, select_palette, (AL_CONST PALETTE p)); AL_FUNC(void, unselect_palette, (void)); AL_FUNC(void, generate_332_palette, (PALETTE pal)); AL_FUNC(int, generate_optimized_palette, (struct BITMAP *image, PALETTE pal, AL_CONST signed char rsvdcols[256])); AL_FUNC(void, create_rgb_table, (RGB_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos)))); AL_FUNC(void, create_light_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos)))); AL_FUNC(void, create_trans_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos)))); AL_FUNC(void, create_color_table, (COLOR_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, blend, (AL_CONST PALETTE pal, int x, int y, RGB *rgb)), AL_METHOD(void, callback, (int pos)))); AL_FUNC(void, create_blender_table, (COLOR_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos)))); typedef AL_METHOD(unsigned long, BLENDER_FUNC, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(void, set_blender_mode, (BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, int r, int g, int b, int a)); AL_FUNC(void, set_blender_mode_ex, (BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, BLENDER_FUNC b32, BLENDER_FUNC b15x, BLENDER_FUNC b16x, BLENDER_FUNC b24x, int r, int g, int b, int a)); AL_FUNC(void, set_alpha_blender, (void)); AL_FUNC(void, set_write_alpha_blender, (void)); AL_FUNC(void, set_trans_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_add_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_burn_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_color_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_difference_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_dissolve_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_dodge_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_hue_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_invert_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_luminance_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_multiply_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_saturation_blender, (int r, int g, int b, int a)); AL_FUNC(void, set_screen_blender, (int r, int g, int b, int a)); AL_FUNC(void, hsv_to_rgb, (float h, float s, float v, int *r, int *g, int *b)); AL_FUNC(void, rgb_to_hsv, (int r, int g, int b, float *h, float *s, float *v)); AL_FUNC(int, bestfit_color, (AL_CONST PALETTE pal, int r, int g, int b)); AL_FUNC(int, makecol, (int r, int g, int b)); AL_FUNC(int, makecol8, (int r, int g, int b)); AL_FUNC(int, makecol_depth, (int color_depth, int r, int g, int b)); AL_FUNC(int, makeacol, (int r, int g, int b, int a)); AL_FUNC(int, makeacol_depth, (int color_depth, int r, int g, int b, int a)); AL_FUNC(int, makecol15_dither, (int r, int g, int b, int x, int y)); AL_FUNC(int, makecol16_dither, (int r, int g, int b, int x, int y)); AL_FUNC(int, getr, (int c)); AL_FUNC(int, getg, (int c)); AL_FUNC(int, getb, (int c)); AL_FUNC(int, geta, (int c)); AL_FUNC(int, getr_depth, (int color_depth, int c)); AL_FUNC(int, getg_depth, (int color_depth, int c)); AL_FUNC(int, getb_depth, (int color_depth, int c)); AL_FUNC(int, geta_depth, (int color_depth, int c)); #ifdef __cplusplus } #endif #include "inline/color.inl" #endif /* ifndef ALLEGRO_COLOR_H */ allegro-4.4.3.1/include/allegro/midi.h0000664000175000017500000001165713437077643016455 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MIDI music routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_MIDI_H #define ALLEGRO_MIDI_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct PACKFILE; /* Theoretical maximums: */ #define MIDI_VOICES 64 /* actual drivers may not be */ #define MIDI_TRACKS 32 /* able to handle this many */ typedef struct MIDI /* a midi file */ { int divisions; /* number of ticks per quarter note */ struct { unsigned char *data; /* MIDI message stream */ int len; /* length of the track data */ } track[MIDI_TRACKS]; } MIDI; #define MIDI_AUTODETECT -1 #define MIDI_NONE 0 #define MIDI_DIGMID AL_ID('D','I','G','I') typedef struct MIDI_DRIVER /* driver for playing midi music */ { int id; /* driver ID code */ AL_CONST char *name; /* driver name */ AL_CONST char *desc; /* description string */ AL_CONST char *ascii_name; /* ASCII format name string */ int voices; /* available voices */ int basevoice; /* voice number offset */ int max_voices; /* maximum voices we can support */ int def_voices; /* default number of voices to use */ int xmin, xmax; /* reserved voice range */ /* setup routines */ AL_METHOD(int, detect, (int input)); AL_METHOD(int, init, (int input, int voices)); AL_METHOD(void, exit, (int input)); AL_METHOD(int, set_mixer_volume, (int volume)); AL_METHOD(int, get_mixer_volume, (void)); /* raw MIDI output to MPU-401, etc. */ AL_METHOD(void, raw_midi, (int data)); /* dynamic patch loading routines */ AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); /* note control functions */ AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); AL_METHOD(void, key_off, (int voice)); AL_METHOD(void, set_volume, (int voice, int vol)); AL_METHOD(void, set_pitch, (int voice, int note, int bend)); AL_METHOD(void, set_pan, (int voice, int pan)); AL_METHOD(void, set_vibrato, (int voice, int amount)); } MIDI_DRIVER; AL_VAR(MIDI_DRIVER, midi_digmid); AL_ARRAY(_DRIVER_INFO, _midi_driver_list); /* macros for constructing the driver lists */ #define BEGIN_MIDI_DRIVER_LIST \ _DRIVER_INFO _midi_driver_list[] = \ { #define END_MIDI_DRIVER_LIST \ { 0, NULL, 0 } \ }; #define MIDI_DRIVER_DIGMID \ { MIDI_DIGMID, &midi_digmid, TRUE }, AL_VAR(MIDI_DRIVER *, midi_driver); AL_VAR(MIDI_DRIVER *, midi_input_driver); AL_VAR(int, midi_card); AL_VAR(int, midi_input_card); AL_VAR(volatile long, midi_pos); /* current position in the midi file, in beats */ AL_VAR(volatile long, midi_time); /* current position in the midi file, in seconds */ AL_VAR(long, midi_loop_start); /* where to loop back to at EOF */ AL_VAR(long, midi_loop_end); /* loop when we hit this position */ AL_FUNC(int, detect_midi_driver, (int driver_id)); AL_FUNC(MIDI *, load_midi, (AL_CONST char *filename)); AL_FUNC(MIDI *, load_midi_pf, (struct PACKFILE *f)); AL_FUNC(void, destroy_midi, (MIDI *midi)); AL_FUNC(int, play_midi, (MIDI *midi, int loop)); AL_FUNC(int, play_looped_midi, (MIDI *midi, int loop_start, int loop_end)); AL_FUNC(void, stop_midi, (void)); AL_FUNC(void, midi_pause, (void)); AL_FUNC(void, midi_resume, (void)); AL_FUNC(int, midi_seek, (int target)); AL_FUNC(int, get_midi_length, (MIDI *midi)); AL_FUNC(void, midi_out, (unsigned char *data, int length)); AL_FUNC(int, load_midi_patches, (void)); AL_FUNCPTR(void, midi_msg_callback, (int msg, int byte1, int byte2)); AL_FUNCPTR(void, midi_meta_callback, (int type, AL_CONST unsigned char *data, int length)); AL_FUNCPTR(void, midi_sysex_callback, (AL_CONST unsigned char *data, int length)); AL_FUNCPTR(void, midi_recorder, (unsigned char data)); AL_FUNC(void, lock_midi, (struct MIDI *midi)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_MIDI_H */ allegro-4.4.3.1/include/allegro/keyboard.h0000664000175000017500000003570213437077643017330 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Keyboard routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_KEYBOARD_H #define ALLEGRO_KEYBOARD_H #include "base.h" #ifdef __cplusplus extern "C" { #endif typedef struct KEYBOARD_DRIVER { int id; AL_CONST char *name; AL_CONST char *desc; AL_CONST char *ascii_name; int autorepeat; AL_METHOD(int, init, (void)); AL_METHOD(void, exit, (void)); AL_METHOD(void, poll, (void)); AL_METHOD(void, set_leds, (int leds)); AL_METHOD(void, set_rate, (int delay, int rate)); AL_METHOD(void, wait_for_input, (void)); AL_METHOD(void, stop_waiting_for_input, (void)); AL_METHOD(int, scancode_to_ascii, (int scancode)); AL_METHOD(AL_CONST char *, scancode_to_name, (int scancode)); } KEYBOARD_DRIVER; AL_VAR(KEYBOARD_DRIVER *, keyboard_driver); AL_ARRAY(_DRIVER_INFO, _keyboard_driver_list); AL_FUNC(int, install_keyboard, (void)); AL_FUNC(void, remove_keyboard, (void)); AL_FUNC(int, poll_keyboard, (void)); AL_FUNC(int, keyboard_needs_poll, (void)); AL_FUNCPTR(int, keyboard_callback, (int key)); AL_FUNCPTR(int, keyboard_ucallback, (int key, int *scancode)); AL_FUNCPTR(void, keyboard_lowlevel_callback, (int scancode)); AL_FUNC(void, install_keyboard_hooks, (AL_METHOD(int, keypressed, (void)), AL_METHOD(int, readkey, (void)))); AL_ARRAY(volatile char, key); AL_VAR(volatile int, key_shifts); AL_VAR(int, three_finger_flag); AL_VAR(int, key_led_flag); AL_FUNC(int, keypressed, (void)); AL_FUNC(int, readkey, (void)); AL_FUNC(int, ureadkey, (int *scancode)); AL_FUNC(void, simulate_keypress, (int keycode)); AL_FUNC(void, simulate_ukeypress, (int keycode, int scancode)); AL_FUNC(void, clear_keybuf, (void)); AL_FUNC(void, set_leds, (int leds)); AL_FUNC(void, set_keyboard_rate, (int delay, int repeat)); AL_FUNC(int, scancode_to_ascii, (int scancode)); AL_FUNC(AL_CONST char *, scancode_to_name, (int scancode)); /* The KEY_ macros are no longer #defined directly to avoid conflicting with * linux (which has its own KEY_ constants). "__allegro_"-prefixed constants * are used by the Allegro-Linux keyboard driver, but everyone else should * continue to use the KEY_ constants. */ enum { __allegro_KB_SHIFT_FLAG = 0x0001, __allegro_KB_CTRL_FLAG = 0x0002, __allegro_KB_ALT_FLAG = 0x0004, __allegro_KB_LWIN_FLAG = 0x0008, __allegro_KB_RWIN_FLAG = 0x0010, __allegro_KB_MENU_FLAG = 0x0020, __allegro_KB_COMMAND_FLAG = 0x0040, __allegro_KB_SCROLOCK_FLAG = 0x0100, __allegro_KB_NUMLOCK_FLAG = 0x0200, __allegro_KB_CAPSLOCK_FLAG = 0x0400, __allegro_KB_INALTSEQ_FLAG = 0x0800, __allegro_KB_ACCENT1_FLAG = 0x1000, __allegro_KB_ACCENT2_FLAG = 0x2000, __allegro_KB_ACCENT3_FLAG = 0x4000, __allegro_KB_ACCENT4_FLAG = 0x8000 }; enum { __allegro_KEY_A = 1, __allegro_KEY_B = 2, __allegro_KEY_C = 3, __allegro_KEY_D = 4, __allegro_KEY_E = 5, __allegro_KEY_F = 6, __allegro_KEY_G = 7, __allegro_KEY_H = 8, __allegro_KEY_I = 9, __allegro_KEY_J = 10, __allegro_KEY_K = 11, __allegro_KEY_L = 12, __allegro_KEY_M = 13, __allegro_KEY_N = 14, __allegro_KEY_O = 15, __allegro_KEY_P = 16, __allegro_KEY_Q = 17, __allegro_KEY_R = 18, __allegro_KEY_S = 19, __allegro_KEY_T = 20, __allegro_KEY_U = 21, __allegro_KEY_V = 22, __allegro_KEY_W = 23, __allegro_KEY_X = 24, __allegro_KEY_Y = 25, __allegro_KEY_Z = 26, __allegro_KEY_0 = 27, __allegro_KEY_1 = 28, __allegro_KEY_2 = 29, __allegro_KEY_3 = 30, __allegro_KEY_4 = 31, __allegro_KEY_5 = 32, __allegro_KEY_6 = 33, __allegro_KEY_7 = 34, __allegro_KEY_8 = 35, __allegro_KEY_9 = 36, __allegro_KEY_0_PAD = 37, __allegro_KEY_1_PAD = 38, __allegro_KEY_2_PAD = 39, __allegro_KEY_3_PAD = 40, __allegro_KEY_4_PAD = 41, __allegro_KEY_5_PAD = 42, __allegro_KEY_6_PAD = 43, __allegro_KEY_7_PAD = 44, __allegro_KEY_8_PAD = 45, __allegro_KEY_9_PAD = 46, __allegro_KEY_F1 = 47, __allegro_KEY_F2 = 48, __allegro_KEY_F3 = 49, __allegro_KEY_F4 = 50, __allegro_KEY_F5 = 51, __allegro_KEY_F6 = 52, __allegro_KEY_F7 = 53, __allegro_KEY_F8 = 54, __allegro_KEY_F9 = 55, __allegro_KEY_F10 = 56, __allegro_KEY_F11 = 57, __allegro_KEY_F12 = 58, __allegro_KEY_ESC = 59, __allegro_KEY_TILDE = 60, __allegro_KEY_MINUS = 61, __allegro_KEY_EQUALS = 62, __allegro_KEY_BACKSPACE = 63, __allegro_KEY_TAB = 64, __allegro_KEY_OPENBRACE = 65, __allegro_KEY_CLOSEBRACE = 66, __allegro_KEY_ENTER = 67, __allegro_KEY_COLON = 68, __allegro_KEY_QUOTE = 69, __allegro_KEY_BACKSLASH = 70, __allegro_KEY_BACKSLASH2 = 71, __allegro_KEY_COMMA = 72, __allegro_KEY_STOP = 73, __allegro_KEY_SLASH = 74, __allegro_KEY_SPACE = 75, __allegro_KEY_INSERT = 76, __allegro_KEY_DEL = 77, __allegro_KEY_HOME = 78, __allegro_KEY_END = 79, __allegro_KEY_PGUP = 80, __allegro_KEY_PGDN = 81, __allegro_KEY_LEFT = 82, __allegro_KEY_RIGHT = 83, __allegro_KEY_UP = 84, __allegro_KEY_DOWN = 85, __allegro_KEY_SLASH_PAD = 86, __allegro_KEY_ASTERISK = 87, __allegro_KEY_MINUS_PAD = 88, __allegro_KEY_PLUS_PAD = 89, __allegro_KEY_DEL_PAD = 90, __allegro_KEY_ENTER_PAD = 91, __allegro_KEY_PRTSCR = 92, __allegro_KEY_PAUSE = 93, __allegro_KEY_ABNT_C1 = 94, __allegro_KEY_YEN = 95, __allegro_KEY_KANA = 96, __allegro_KEY_CONVERT = 97, __allegro_KEY_NOCONVERT = 98, __allegro_KEY_AT = 99, __allegro_KEY_CIRCUMFLEX = 100, __allegro_KEY_COLON2 = 101, __allegro_KEY_KANJI = 102, __allegro_KEY_EQUALS_PAD = 103, /* MacOS X */ __allegro_KEY_BACKQUOTE = 104, /* MacOS X */ __allegro_KEY_SEMICOLON = 105, /* MacOS X */ __allegro_KEY_COMMAND = 106, /* MacOS X */ __allegro_KEY_UNKNOWN1 = 107, __allegro_KEY_UNKNOWN2 = 108, __allegro_KEY_UNKNOWN3 = 109, __allegro_KEY_UNKNOWN4 = 110, __allegro_KEY_UNKNOWN5 = 111, __allegro_KEY_UNKNOWN6 = 112, __allegro_KEY_UNKNOWN7 = 113, __allegro_KEY_UNKNOWN8 = 114, __allegro_KEY_MODIFIERS = 115, __allegro_KEY_LSHIFT = 115, __allegro_KEY_RSHIFT = 116, __allegro_KEY_LCONTROL = 117, __allegro_KEY_RCONTROL = 118, __allegro_KEY_ALT = 119, __allegro_KEY_ALTGR = 120, __allegro_KEY_LWIN = 121, __allegro_KEY_RWIN = 122, __allegro_KEY_MENU = 123, __allegro_KEY_SCRLOCK = 124, __allegro_KEY_NUMLOCK = 125, __allegro_KEY_CAPSLOCK = 126, __allegro_KEY_MAX = 127 }; #ifndef ALLEGRO_NO_KEY_DEFINES #define KB_SHIFT_FLAG __allegro_KB_SHIFT_FLAG #define KB_CTRL_FLAG __allegro_KB_CTRL_FLAG #define KB_ALT_FLAG __allegro_KB_ALT_FLAG #define KB_LWIN_FLAG __allegro_KB_LWIN_FLAG #define KB_RWIN_FLAG __allegro_KB_RWIN_FLAG #define KB_MENU_FLAG __allegro_KB_MENU_FLAG #define KB_COMMAND_FLAG __allegro_KB_COMMAND_FLAG #define KB_SCROLOCK_FLAG __allegro_KB_SCROLOCK_FLAG #define KB_NUMLOCK_FLAG __allegro_KB_NUMLOCK_FLAG #define KB_CAPSLOCK_FLAG __allegro_KB_CAPSLOCK_FLAG #define KB_INALTSEQ_FLAG __allegro_KB_INALTSEQ_FLAG #define KB_ACCENT1_FLAG __allegro_KB_ACCENT1_FLAG #define KB_ACCENT2_FLAG __allegro_KB_ACCENT2_FLAG #define KB_ACCENT3_FLAG __allegro_KB_ACCENT3_FLAG #define KB_ACCENT4_FLAG __allegro_KB_ACCENT4_FLAG #define KEY_A __allegro_KEY_A #define KEY_B __allegro_KEY_B #define KEY_C __allegro_KEY_C #define KEY_D __allegro_KEY_D #define KEY_E __allegro_KEY_E #define KEY_F __allegro_KEY_F #define KEY_G __allegro_KEY_G #define KEY_H __allegro_KEY_H #define KEY_I __allegro_KEY_I #define KEY_J __allegro_KEY_J #define KEY_K __allegro_KEY_K #define KEY_L __allegro_KEY_L #define KEY_M __allegro_KEY_M #define KEY_N __allegro_KEY_N #define KEY_O __allegro_KEY_O #define KEY_P __allegro_KEY_P #define KEY_Q __allegro_KEY_Q #define KEY_R __allegro_KEY_R #define KEY_S __allegro_KEY_S #define KEY_T __allegro_KEY_T #define KEY_U __allegro_KEY_U #define KEY_V __allegro_KEY_V #define KEY_W __allegro_KEY_W #define KEY_X __allegro_KEY_X #define KEY_Y __allegro_KEY_Y #define KEY_Z __allegro_KEY_Z #define KEY_0 __allegro_KEY_0 #define KEY_1 __allegro_KEY_1 #define KEY_2 __allegro_KEY_2 #define KEY_3 __allegro_KEY_3 #define KEY_4 __allegro_KEY_4 #define KEY_5 __allegro_KEY_5 #define KEY_6 __allegro_KEY_6 #define KEY_7 __allegro_KEY_7 #define KEY_8 __allegro_KEY_8 #define KEY_9 __allegro_KEY_9 #define KEY_0_PAD __allegro_KEY_0_PAD #define KEY_1_PAD __allegro_KEY_1_PAD #define KEY_2_PAD __allegro_KEY_2_PAD #define KEY_3_PAD __allegro_KEY_3_PAD #define KEY_4_PAD __allegro_KEY_4_PAD #define KEY_5_PAD __allegro_KEY_5_PAD #define KEY_6_PAD __allegro_KEY_6_PAD #define KEY_7_PAD __allegro_KEY_7_PAD #define KEY_8_PAD __allegro_KEY_8_PAD #define KEY_9_PAD __allegro_KEY_9_PAD #define KEY_F1 __allegro_KEY_F1 #define KEY_F2 __allegro_KEY_F2 #define KEY_F3 __allegro_KEY_F3 #define KEY_F4 __allegro_KEY_F4 #define KEY_F5 __allegro_KEY_F5 #define KEY_F6 __allegro_KEY_F6 #define KEY_F7 __allegro_KEY_F7 #define KEY_F8 __allegro_KEY_F8 #define KEY_F9 __allegro_KEY_F9 #define KEY_F10 __allegro_KEY_F10 #define KEY_F11 __allegro_KEY_F11 #define KEY_F12 __allegro_KEY_F12 #define KEY_ESC __allegro_KEY_ESC #define KEY_TILDE __allegro_KEY_TILDE #define KEY_MINUS __allegro_KEY_MINUS #define KEY_EQUALS __allegro_KEY_EQUALS #define KEY_BACKSPACE __allegro_KEY_BACKSPACE #define KEY_TAB __allegro_KEY_TAB #define KEY_OPENBRACE __allegro_KEY_OPENBRACE #define KEY_CLOSEBRACE __allegro_KEY_CLOSEBRACE #define KEY_ENTER __allegro_KEY_ENTER #define KEY_COLON __allegro_KEY_COLON #define KEY_QUOTE __allegro_KEY_QUOTE #define KEY_BACKSLASH __allegro_KEY_BACKSLASH #define KEY_BACKSLASH2 __allegro_KEY_BACKSLASH2 #define KEY_COMMA __allegro_KEY_COMMA #define KEY_STOP __allegro_KEY_STOP #define KEY_SLASH __allegro_KEY_SLASH #define KEY_SPACE __allegro_KEY_SPACE #define KEY_INSERT __allegro_KEY_INSERT #define KEY_DEL __allegro_KEY_DEL #define KEY_HOME __allegro_KEY_HOME #define KEY_END __allegro_KEY_END #define KEY_PGUP __allegro_KEY_PGUP #define KEY_PGDN __allegro_KEY_PGDN #define KEY_LEFT __allegro_KEY_LEFT #define KEY_RIGHT __allegro_KEY_RIGHT #define KEY_UP __allegro_KEY_UP #define KEY_DOWN __allegro_KEY_DOWN #define KEY_SLASH_PAD __allegro_KEY_SLASH_PAD #define KEY_ASTERISK __allegro_KEY_ASTERISK #define KEY_MINUS_PAD __allegro_KEY_MINUS_PAD #define KEY_PLUS_PAD __allegro_KEY_PLUS_PAD #define KEY_DEL_PAD __allegro_KEY_DEL_PAD #define KEY_ENTER_PAD __allegro_KEY_ENTER_PAD #define KEY_PRTSCR __allegro_KEY_PRTSCR #define KEY_PAUSE __allegro_KEY_PAUSE #define KEY_ABNT_C1 __allegro_KEY_ABNT_C1 #define KEY_YEN __allegro_KEY_YEN #define KEY_KANA __allegro_KEY_KANA #define KEY_CONVERT __allegro_KEY_CONVERT #define KEY_NOCONVERT __allegro_KEY_NOCONVERT #define KEY_AT __allegro_KEY_AT #define KEY_CIRCUMFLEX __allegro_KEY_CIRCUMFLEX #define KEY_COLON2 __allegro_KEY_COLON2 #define KEY_KANJI __allegro_KEY_KANJI #define KEY_EQUALS_PAD __allegro_KEY_EQUALS_PAD #define KEY_BACKQUOTE __allegro_KEY_BACKQUOTE #define KEY_SEMICOLON __allegro_KEY_SEMICOLON #define KEY_COMMAND __allegro_KEY_COMMAND #define KEY_UNKNOWN1 __allegro_KEY_UNKNOWN1 #define KEY_UNKNOWN2 __allegro_KEY_UNKNOWN2 #define KEY_UNKNOWN3 __allegro_KEY_UNKNOWN3 #define KEY_UNKNOWN4 __allegro_KEY_UNKNOWN4 #define KEY_UNKNOWN5 __allegro_KEY_UNKNOWN5 #define KEY_UNKNOWN6 __allegro_KEY_UNKNOWN6 #define KEY_UNKNOWN7 __allegro_KEY_UNKNOWN7 #define KEY_UNKNOWN8 __allegro_KEY_UNKNOWN8 #define KEY_MODIFIERS __allegro_KEY_MODIFIERS #define KEY_LSHIFT __allegro_KEY_LSHIFT #define KEY_RSHIFT __allegro_KEY_RSHIFT #define KEY_LCONTROL __allegro_KEY_LCONTROL #define KEY_RCONTROL __allegro_KEY_RCONTROL #define KEY_ALT __allegro_KEY_ALT #define KEY_ALTGR __allegro_KEY_ALTGR #define KEY_LWIN __allegro_KEY_LWIN #define KEY_RWIN __allegro_KEY_RWIN #define KEY_MENU __allegro_KEY_MENU #define KEY_SCRLOCK __allegro_KEY_SCRLOCK #define KEY_NUMLOCK __allegro_KEY_NUMLOCK #define KEY_CAPSLOCK __allegro_KEY_CAPSLOCK #define KEY_MAX __allegro_KEY_MAX #endif /* ALLEGRO_NO_KEY_DEFINES */ #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_KEYBOARD_H */ allegro-4.4.3.1/include/allegro/file.h0000664000175000017500000001662313437077643016450 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * File I/O. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FILE_H #define ALLEGRO_FILE_H #include "base.h" #ifdef __cplusplus extern "C" { #endif AL_FUNC(char *, fix_filename_case, (char *path)); AL_FUNC(char *, fix_filename_slashes, (char *path)); AL_FUNC(char *, canonicalize_filename, (char *dest, AL_CONST char *filename, int size)); AL_FUNC(char *, make_absolute_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); AL_FUNC(char *, make_relative_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); AL_FUNC(int, is_relative_filename, (AL_CONST char *filename)); AL_FUNC(char *, replace_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); AL_FUNC(char *, replace_extension, (char *dest, AL_CONST char *filename, AL_CONST char *ext, int size)); AL_FUNC(char *, append_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); AL_FUNC(char *, get_filename, (AL_CONST char *path)); AL_FUNC(char *, get_extension, (AL_CONST char *filename)); AL_FUNC(void, put_backslash, (char *filename)); AL_FUNC(int, file_exists, (AL_CONST char *filename, int attrib, int *aret)); AL_FUNC(int, exists, (AL_CONST char *filename)); AL_FUNC(uint64_t, file_size_ex, (AL_CONST char *filename)); AL_FUNC(time_t, file_time, (AL_CONST char *filename)); AL_FUNC(int, delete_file, (AL_CONST char *filename)); AL_FUNC(int, for_each_file_ex, (AL_CONST char *name, int in_attrib, int out_attrib, AL_METHOD(int, callback, (AL_CONST char *filename, int attrib, void *param)), void *param)); AL_FUNC(int, set_allegro_resource_path, (int priority, AL_CONST char *path)); AL_FUNC(int, find_allegro_resource, (char *dest, AL_CONST char *resource, AL_CONST char *ext, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *envvar, AL_CONST char *subdir, int size)); struct al_ffblk /* file info block for the al_find*() routines */ { int attrib; /* actual attributes of the file found */ time_t time; /* modification time of file */ long size; /* size of file */ char name[512]; /* name of file */ void *ff_data; /* private hook */ }; AL_FUNC(uint64_t, al_ffblk_get_size, (struct al_ffblk *info)); AL_FUNC(int, al_findfirst, (AL_CONST char *pattern, struct al_ffblk *info, int attrib)); AL_FUNC(int, al_findnext, (struct al_ffblk *info)); AL_FUNC(void, al_findclose, (struct al_ffblk *info)); #ifndef EOF #define EOF (-1) #endif #define F_READ "r" #define F_WRITE "w" #define F_READ_PACKED "rp" #define F_WRITE_PACKED "wp" #define F_WRITE_NOPACK "w!" #define F_BUF_SIZE 4096 /* 4K buffer for caching data */ #define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ #define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ #define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ #define PACKFILE_FLAG_WRITE 1 /* the file is being written */ #define PACKFILE_FLAG_PACK 2 /* data is compressed */ #define PACKFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ #define PACKFILE_FLAG_EOF 8 /* reached the end-of-file */ #define PACKFILE_FLAG_ERROR 16 /* an error has occurred */ #define PACKFILE_FLAG_OLD_CRYPT 32 /* backward compatibility mode */ #define PACKFILE_FLAG_EXEDAT 64 /* reading from our executable */ typedef struct PACKFILE_VTABLE PACKFILE_VTABLE; typedef struct PACKFILE PACKFILE; struct LZSS_PACK_DATA; struct LZSS_UNPACK_DATA; struct _al_normal_packfile_details { int hndl; /* DOS file handle */ int flags; /* PACKFILE_FLAG_* constants */ unsigned char *buf_pos; /* position in buffer */ int buf_size; /* number of bytes in the buffer */ long todo; /* number of bytes still on the disk */ struct PACKFILE *parent; /* nested, parent file */ struct LZSS_PACK_DATA *pack_data; /* for LZSS compression */ struct LZSS_UNPACK_DATA *unpack_data; /* for LZSS decompression */ char *filename; /* name of the file */ char *passdata; /* encryption key data */ char *passpos; /* current key position */ unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ }; struct PACKFILE /* our very own FILE structure... */ { AL_CONST PACKFILE_VTABLE *vtable; void *userdata; int is_normal_packfile; /* The following is only to be used for the "normal" PACKFILE vtable, * i.e. what is implemented by Allegro itself. If is_normal_packfile is * false then the following is not even allocated. This must be the last * member in the structure. */ struct _al_normal_packfile_details normal; }; struct PACKFILE_VTABLE { AL_METHOD(int, pf_fclose, (void *userdata)); AL_METHOD(int, pf_getc, (void *userdata)); AL_METHOD(int, pf_ungetc, (int c, void *userdata)); AL_METHOD(long, pf_fread, (void *p, long n, void *userdata)); AL_METHOD(int, pf_putc, (int c, void *userdata)); AL_METHOD(long, pf_fwrite, (AL_CONST void *p, long n, void *userdata)); AL_METHOD(int, pf_fseek, (void *userdata, int offset)); AL_METHOD(int, pf_feof, (void *userdata)); AL_METHOD(int, pf_ferror, (void *userdata)); }; #define uconvert_tofilename(s, buf) uconvert(s, U_CURRENT, buf, get_filename_encoding(), sizeof(buf)) AL_FUNC(void, set_filename_encoding, (int encoding)); AL_FUNC(int, get_filename_encoding, (void)); AL_FUNC(void, packfile_password, (AL_CONST char *password)); AL_FUNC(PACKFILE *, pack_fopen, (AL_CONST char *filename, AL_CONST char *mode)); AL_FUNC(PACKFILE *, pack_fopen_vtable, (AL_CONST PACKFILE_VTABLE *vtable, void *userdata)); AL_FUNC(int, pack_fclose, (PACKFILE *f)); AL_FUNC(int, pack_fseek, (PACKFILE *f, int offset)); AL_FUNC(PACKFILE *, pack_fopen_chunk, (PACKFILE *f, int pack)); AL_FUNC(PACKFILE *, pack_fclose_chunk, (PACKFILE *f)); AL_FUNC(int, pack_getc, (PACKFILE *f)); AL_FUNC(int, pack_putc, (int c, PACKFILE *f)); AL_FUNC(int, pack_feof, (PACKFILE *f)); AL_FUNC(int, pack_ferror, (PACKFILE *f)); AL_FUNC(int, pack_igetw, (PACKFILE *f)); AL_FUNC(long, pack_igetl, (PACKFILE *f)); AL_FUNC(int, pack_iputw, (int w, PACKFILE *f)); AL_FUNC(long, pack_iputl, (long l, PACKFILE *f)); AL_FUNC(int, pack_mgetw, (PACKFILE *f)); AL_FUNC(long, pack_mgetl, (PACKFILE *f)); AL_FUNC(int, pack_mputw, (int w, PACKFILE *f)); AL_FUNC(long, pack_mputl, (long l, PACKFILE *f)); AL_FUNC(long, pack_fread, (void *p, long n, PACKFILE *f)); AL_FUNC(long, pack_fwrite, (AL_CONST void *p, long n, PACKFILE *f)); AL_FUNC(int, pack_ungetc, (int c, PACKFILE *f)); AL_FUNC(char *, pack_fgets, (char *p, int max, PACKFILE *f)); AL_FUNC(int, pack_fputs, (AL_CONST char *p, PACKFILE *f)); AL_FUNC(void *, pack_get_userdata, (PACKFILE *f)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_FILE_H */ allegro-4.4.3.1/include/allegro/fmaths.h0000664000175000017500000000211313437077643017000 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fixed point math routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FMATH_H #define ALLEGRO_FMATH_H #include "base.h" #include "fixed.h" #ifdef __cplusplus extern "C" { #endif AL_FUNC(fixed, fixsqrt, (fixed x)); AL_FUNC(fixed, fixhypot, (fixed x, fixed y)); AL_FUNC(fixed, fixatan, (fixed x)); AL_FUNC(fixed, fixatan2, (fixed y, fixed x)); AL_ARRAY(fixed, _cos_tbl); AL_ARRAY(fixed, _tan_tbl); AL_ARRAY(fixed, _acos_tbl); #ifdef __cplusplus } #endif #include "inline/fmaths.inl" #endif /* ifndef ALLEGRO_FMATH_H */ allegro-4.4.3.1/include/allegro/sound.h0000664000175000017500000000334513437077643016656 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sound support routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_SOUND_H #define ALLEGRO_SOUND_H #include "base.h" #include "digi.h" #include "stream.h" #include "midi.h" #ifdef __cplusplus extern "C" { #endif AL_FUNC(void, reserve_voices, (int digi_voices, int midi_voices)); AL_FUNC(void, set_volume_per_voice, (int scale)); AL_FUNC(int, install_sound, (int digi, int midi, AL_CONST char *cfg_path)); AL_FUNC(void, remove_sound, (void)); AL_FUNC(int, install_sound_input, (int digi, int midi)); AL_FUNC(void, remove_sound_input, (void)); AL_FUNC(void, set_volume, (int digi_volume, int midi_volume)); AL_FUNC(void, set_hardware_volume, (int digi_volume, int midi_volume)); AL_FUNC(void, get_volume, (int *digi_volume, int *midi_volume)); AL_FUNC(void, get_hardware_volume, (int *digi_volume, int *midi_volume)); AL_FUNC(void, set_mixer_quality, (int quality)); AL_FUNC(int, get_mixer_quality, (void)); AL_FUNC(int, get_mixer_frequency, (void)); AL_FUNC(int, get_mixer_bits, (void)); AL_FUNC(int, get_mixer_channels, (void)); AL_FUNC(int, get_mixer_voices, (void)); AL_FUNC(int, get_mixer_buffer_length, (void)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_SOUND_H */ allegro-4.4.3.1/include/allegro/3dmaths.h0000664000175000017500000000354613437077643017074 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 3D oriented math routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_3DMATHS_H #define ALLEGRO_3DMATHS_H #include "base.h" #include "fixed.h" #ifdef __cplusplus extern "C" { #endif struct QUAT; struct MATRIX_f; AL_FUNC(fixed, vector_length, (fixed x, fixed y, fixed z)); AL_FUNC(float, vector_length_f, (float x, float y, float z)); AL_FUNC(void, normalize_vector, (fixed *x, fixed *y, fixed *z)); AL_FUNC(void, normalize_vector_f, (float *x, float *y, float *z)); AL_FUNC(void, cross_product, (fixed x1, fixed y_1, fixed z1, fixed x2, fixed y2, fixed z2, fixed *xout, fixed *yout, fixed *zout)); AL_FUNC(void, cross_product_f, (float x1, float y_1, float z1, float x2, float y2, float z2, float *xout, float *yout, float *zout)); AL_VAR(fixed, _persp_xscale); AL_VAR(fixed, _persp_yscale); AL_VAR(fixed, _persp_xoffset); AL_VAR(fixed, _persp_yoffset); AL_VAR(float, _persp_xscale_f); AL_VAR(float, _persp_yscale_f); AL_VAR(float, _persp_xoffset_f); AL_VAR(float, _persp_yoffset_f); AL_FUNC(void, set_projection_viewport, (int x, int y, int w, int h)); AL_FUNC(void, quat_to_matrix, (AL_CONST struct QUAT *q, struct MATRIX_f *m)); AL_FUNC(void, matrix_to_quat, (AL_CONST struct MATRIX_f *m, struct QUAT *q)); #ifdef __cplusplus } #endif #include "inline/3dmaths.inl" #endif /* ifndef ALLEGRO_3DMATHS_H */ allegro-4.4.3.1/include/allegro/system.h0000664000175000017500000002123113437077643017044 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * System level: initialization, cleanup, etc. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_SYSTEM_H #define ALLEGRO_SYSTEM_H #include "base.h" #include "unicode.h" #include "config.h" #ifdef __cplusplus extern "C" { #endif struct RGB; struct BITMAP; struct GFX_VTABLE; struct GFX_MODE; #define ALLEGRO_ERROR_SIZE 256 AL_ARRAY(char, allegro_id); AL_ARRAY(char, allegro_error); #define OSTYPE_UNKNOWN 0 #define OSTYPE_WIN3 AL_ID('W','I','N','3') #define OSTYPE_WIN95 AL_ID('W','9','5',' ') #define OSTYPE_WIN98 AL_ID('W','9','8',' ') #define OSTYPE_WINME AL_ID('W','M','E',' ') #define OSTYPE_WINNT AL_ID('W','N','T',' ') #define OSTYPE_WIN2000 AL_ID('W','2','K',' ') #define OSTYPE_WINXP AL_ID('W','X','P',' ') #define OSTYPE_WIN2003 AL_ID('W','2','K','3') #define OSTYPE_WINVISTA AL_ID('W','V','S','T') #define OSTYPE_WIN7 AL_ID('W','I','N','7') #define OSTYPE_OS2 AL_ID('O','S','2',' ') #define OSTYPE_WARP AL_ID('W','A','R','P') #define OSTYPE_DOSEMU AL_ID('D','E','M','U') #define OSTYPE_OPENDOS AL_ID('O','D','O','S') #define OSTYPE_LINUX AL_ID('T','U','X',' ') #define OSTYPE_SUNOS AL_ID('S','U','N',' ') #define OSTYPE_FREEBSD AL_ID('F','B','S','D') #define OSTYPE_NETBSD AL_ID('N','B','S','D') #define OSTYPE_OPENBSD AL_ID('O','B','S','D') #define OSTYPE_IRIX AL_ID('I','R','I','X') #define OSTYPE_DARWIN AL_ID('D','A','R','W') #define OSTYPE_QNX AL_ID('Q','N','X',' ') #define OSTYPE_UNIX AL_ID('U','N','I','X') #define OSTYPE_BEOS AL_ID('B','E','O','S') #define OSTYPE_HAIKU AL_ID('H','A','I','K') #define OSTYPE_MACOS AL_ID('M','A','C',' ') #define OSTYPE_MACOSX AL_ID('M','A','C','X') #define OSTYPE_PSP AL_ID('K','P','S','P') AL_VAR(int, os_type); AL_VAR(int, os_version); AL_VAR(int, os_revision); AL_VAR(int, os_multitasking); #define SYSTEM_AUTODETECT 0 #define SYSTEM_NONE AL_ID('N','O','N','E') #define MAKE_VERSION(a, b, c) (((a)<<16)|((b)<<8)|(c)) AL_FUNC(int, _install_allegro_version_check, (int system_id, int *errno_ptr, AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void)))), int version)); AL_INLINE(int, install_allegro, (int system_id, int *errno_ptr, AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void))))), { return _install_allegro_version_check(system_id, errno_ptr, atexit_ptr, \ MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)); }) #define allegro_init() _install_allegro_version_check(SYSTEM_AUTODETECT, &errno, \ (int (*)(void (*)(void)))atexit, \ MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)) AL_FUNC(void, allegro_exit, (void)); AL_PRINTFUNC(void, allegro_message, (AL_CONST char *msg, ...), 1, 2); AL_FUNC(void, get_executable_name, (char *output, int size)); AL_FUNC(int, set_close_button_callback, (AL_METHOD(void, proc, (void)))); AL_FUNC(void, check_cpu, (void)); /* CPU Capabilities flags for x86 capable chips */ #define CPU_ID 0x0001 #define CPU_FPU 0x0002 #define CPU_MMX 0x0004 #define CPU_MMXPLUS 0x0008 #define CPU_SSE 0x0010 #define CPU_SSE2 0x0020 #define CPU_3DNOW 0x0040 #define CPU_ENH3DNOW 0x0080 #define CPU_CMOV 0x0100 #define CPU_AMD64 0x0200 #define CPU_IA64 0x0400 #define CPU_SSE3 0x0800 #define CPU_SSSE3 0x1000 #define CPU_SSE41 0x2000 #define CPU_SSE42 0x4000 /* CPU families - PC */ #define CPU_FAMILY_UNKNOWN 0 #define CPU_FAMILY_I386 3 #define CPU_FAMILY_I486 4 #define CPU_FAMILY_I586 5 #define CPU_FAMILY_I686 6 #define CPU_FAMILY_ITANIUM 7 #define CPU_FAMILY_EXTENDED 15 /* CPUID only returns 15 bits, we need extra information from the CPU */ /* model to identify Pentium IV, Xeon and Athlon 64 processors. */ /* CPU families - Power PC */ #define CPU_FAMILY_POWERPC 18 /* CPU models - PC */ /* 486 */ #define CPU_MODEL_I486DX 0 #define CPU_MODEL_I486DX50 1 #define CPU_MODEL_I486SX 2 #define CPU_MODEL_I487SX 3 #define CPU_MODEL_I486SL 4 #define CPU_MODEL_I486SX2 5 #define CPU_MODEL_I486DX2 7 #define CPU_MODEL_I486DX4 8 /* Intel/586 */ #define CPU_MODEL_PENTIUM 1 #define CPU_MODEL_PENTIUMP54C 2 #define CPU_MODEL_PENTIUMOVERDRIVE 3 #define CPU_MODEL_PENTIUMOVERDRIVEDX4 4 #define CPU_MODEL_CYRIX 14 #define CPU_MODEL_UNKNOWN 15 /* AMD/586 */ #define CPU_MODEL_K5 0 #define CPU_MODEL_K6 6 /* Intel/686 */ #define CPU_MODEL_PENTIUMPROA 0 #define CPU_MODEL_PENTIUMPRO 1 #define CPU_MODEL_PENTIUMIIKLAMATH 3 #define CPU_MODEL_PENTIUMII 5 #define CPU_MODEL_CELERON 6 #define CPU_MODEL_PENTIUMIIIKATMAI 7 #define CPU_MODEL_PENTIUMIIICOPPERMINE 8 #define CPU_MODEL_PENTIUMIIIMOBILE 9 /* AMD/686 */ #define CPU_MODEL_ATHLON 2 #define CPU_MODEL_DURON 3 /* Information when CPU_FAMILY is 15 */ #define CPU_MODEL_PENTIUMIV 0 #define CPU_MODEL_XEON 2 #define CPU_MODEL_ATHLON64 4 #define CPU_MODEL_OPTERON 5 /* Information for Power PC processors */ /* these defines are taken from */ #define CPU_MODEL_POWERPC_601 1 #define CPU_MODEL_POWERPC_602 2 #define CPU_MODEL_POWERPC_603 3 #define CPU_MODEL_POWERPC_603e 4 #define CPU_MODEL_POWERPC_603ev 5 #define CPU_MODEL_POWERPC_604 6 #define CPU_MODEL_POWERPC_604e 7 #define CPU_MODEL_POWERPC_620 8 #define CPU_MODEL_POWERPC_750 9 #define CPU_MODEL_POWERPC_7400 10 #define CPU_MODEL_POWERPC_7450 11 AL_ARRAY(char, cpu_vendor); AL_VAR(int, cpu_family); AL_VAR(int, cpu_model); AL_VAR(int, cpu_capabilities); typedef struct SYSTEM_DRIVER { int id; AL_CONST char *name; AL_CONST char *desc; AL_CONST char *ascii_name; AL_METHOD(int, init, (void)); AL_METHOD(void, exit, (void)); AL_METHOD(void, get_executable_name, (char *output, int size)); AL_METHOD(int, find_resource, (char *dest, AL_CONST char *resource, int size)); AL_METHOD(void, set_window_title, (AL_CONST char *name)); AL_METHOD(int, set_close_button_callback, (AL_METHOD(void, proc, (void)))); AL_METHOD(void, message, (AL_CONST char *msg)); AL_METHOD(void, assert, (AL_CONST char *msg)); AL_METHOD(void, save_console_state, (void)); AL_METHOD(void, restore_console_state, (void)); AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); AL_METHOD(void, read_hardware_palette, (void)); AL_METHOD(void, set_palette_range, (AL_CONST struct RGB *p, int from, int to, int retracesync)); AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); AL_METHOD(int, set_display_switch_mode, (int mode)); AL_METHOD(void, display_switch_lock, (int lock, int foreground)); AL_METHOD(int, desktop_color_depth, (void)); AL_METHOD(int, get_desktop_resolution, (int *width, int *height)); AL_METHOD(void, get_gfx_safe_mode, (int *driver, struct GFX_MODE *mode)); AL_METHOD(void, yield_timeslice, (void)); AL_METHOD(void *, create_mutex, (void)); AL_METHOD(void, destroy_mutex, (void *handle)); AL_METHOD(void, lock_mutex, (void *handle)); AL_METHOD(void, unlock_mutex, (void *handle)); AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); } SYSTEM_DRIVER; AL_VAR(SYSTEM_DRIVER, system_none); AL_VAR(SYSTEM_DRIVER *, system_driver); AL_ARRAY(_DRIVER_INFO, _system_driver_list); #ifdef __cplusplus } #endif #include "inline/system.inl" #endif /* ifndef ALLEGRO_SYSTEM_H */ allegro-4.4.3.1/include/allegro/debug.h0000664000175000017500000000247613437077643016620 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Debug facilities. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DEBUG_H #define ALLEGRO_DEBUG_H #include "base.h" #ifdef __cplusplus extern "C" { #endif AL_FUNC(void, al_assert, (AL_CONST char *file, int linenr)); AL_PRINTFUNC(void, al_trace, (AL_CONST char *msg, ...), 1, 2); AL_FUNC(void, register_assert_handler, (AL_METHOD(int, handler, (AL_CONST char *msg)))); AL_FUNC(void, register_trace_handler, (AL_METHOD(int, handler, (AL_CONST char *msg)))); #ifdef DEBUGMODE #define ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } #define TRACE al_trace #else #define ASSERT(condition) #define TRACE 1 ? (void) 0 : al_trace #endif #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_DEBUG_H */ allegro-4.4.3.1/include/allegro/gfx.h0000664000175000017500000005266413437077643016322 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Basic graphics support routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_GFX_H #define ALLEGRO_GFX_H #include "3d.h" #include "base.h" #include "fixed.h" #ifdef __cplusplus extern "C" { #endif struct RLE_SPRITE; struct FONT_GLYPH; struct RGB; #define GFX_TEXT -1 #define GFX_AUTODETECT 0 #define GFX_AUTODETECT_FULLSCREEN 1 #define GFX_AUTODETECT_WINDOWED 2 #define GFX_SAFE AL_ID('S','A','F','E') #define GFX_NONE AL_ID('N','O','N','E') /* drawing modes for draw_sprite_ex() */ #define DRAW_SPRITE_NORMAL 0 #define DRAW_SPRITE_LIT 1 #define DRAW_SPRITE_TRANS 2 /* flipping modes for draw_sprite_ex() */ #define DRAW_SPRITE_NO_FLIP 0x0 #define DRAW_SPRITE_H_FLIP 0x1 #define DRAW_SPRITE_V_FLIP 0x2 #define DRAW_SPRITE_VH_FLIP 0x3 /* Blender mode defines, for the gfx_driver->set_blender_mode() function */ #define blender_mode_none 0 #define blender_mode_trans 1 #define blender_mode_add 2 #define blender_mode_burn 3 #define blender_mode_color 4 #define blender_mode_difference 5 #define blender_mode_dissolve 6 #define blender_mode_dodge 7 #define blender_mode_hue 8 #define blender_mode_invert 9 #define blender_mode_luminance 10 #define blender_mode_multiply 11 #define blender_mode_saturation 12 #define blender_mode_screen 13 #define blender_mode_alpha 14 typedef struct GFX_MODE { int width, height, bpp; } GFX_MODE; typedef struct GFX_MODE_LIST { int num_modes; /* number of gfx modes */ GFX_MODE *mode; /* pointer to the actual mode list array */ } GFX_MODE_LIST; typedef struct GFX_DRIVER /* creates and manages the screen bitmap */ { int id; AL_CONST char *name; AL_CONST char *desc; AL_CONST char *ascii_name; AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); AL_METHOD(void, exit, (struct BITMAP *b)); AL_METHOD(int, scroll, (int x, int y)); AL_METHOD(void, vsync, (void)); AL_METHOD(void, set_palette, (AL_CONST struct RGB *p, int from, int to, int retracesync)); AL_METHOD(int, request_scroll, (int x, int y)); AL_METHOD(int, poll_scroll, (void)); AL_METHOD(void, enable_triple_buffer, (void)); AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); AL_METHOD(void, hide_mouse, (void)); AL_METHOD(void, move_mouse, (int x, int y)); AL_METHOD(void, drawing_mode, (void)); AL_METHOD(void, save_video_state, (void)); AL_METHOD(void, restore_video_state, (void)); AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); AL_METHOD(GFX_MODE_LIST *, fetch_mode_list, (void)); int w, h; /* physical (not virtual!) screen size */ int linear; /* true if video memory is linear */ long bank_size; /* bank size, in bytes */ long bank_gran; /* bank granularity, in bytes */ long vid_mem; /* video memory size, in bytes */ long vid_phys_base; /* physical address of video memory */ int windowed; /* true if driver runs windowed */ } GFX_DRIVER; AL_VAR(GFX_DRIVER *, gfx_driver); AL_ARRAY(_DRIVER_INFO, _gfx_driver_list); /* macros for constructing the driver list */ #define BEGIN_GFX_DRIVER_LIST \ _DRIVER_INFO _gfx_driver_list[] = \ { #define END_GFX_DRIVER_LIST \ { 0, NULL, 0 } \ }; #define GFX_CAN_SCROLL 0x00000001 #define GFX_CAN_TRIPLE_BUFFER 0x00000002 #define GFX_HW_CURSOR 0x00000004 #define GFX_HW_HLINE 0x00000008 #define GFX_HW_HLINE_XOR 0x00000010 #define GFX_HW_HLINE_SOLID_PATTERN 0x00000020 #define GFX_HW_HLINE_COPY_PATTERN 0x00000040 #define GFX_HW_FILL 0x00000080 #define GFX_HW_FILL_XOR 0x00000100 #define GFX_HW_FILL_SOLID_PATTERN 0x00000200 #define GFX_HW_FILL_COPY_PATTERN 0x00000400 #define GFX_HW_LINE 0x00000800 #define GFX_HW_LINE_XOR 0x00001000 #define GFX_HW_TRIANGLE 0x00002000 #define GFX_HW_TRIANGLE_XOR 0x00004000 #define GFX_HW_GLYPH 0x00008000 #define GFX_HW_VRAM_BLIT 0x00010000 #define GFX_HW_VRAM_BLIT_MASKED 0x00020000 #define GFX_HW_MEM_BLIT 0x00040000 #define GFX_HW_MEM_BLIT_MASKED 0x00080000 #define GFX_HW_SYS_TO_VRAM_BLIT 0x00100000 #define GFX_HW_SYS_TO_VRAM_BLIT_MASKED 0x00200000 #define GFX_SYSTEM_CURSOR 0x00400000 #define GFX_HW_VRAM_STRETCH_BLIT 0x00800000 #define GFX_HW_VRAM_STRETCH_BLIT_MASKED 0x01000000 #define GFX_HW_SYS_STRETCH_BLIT 0x02000000 #define GFX_HW_SYS_STRETCH_BLIT_MASKED 0x04000000 AL_VAR(int, gfx_capabilities); /* current driver capabilities */ typedef struct GFX_VTABLE /* functions for drawing onto bitmaps */ { int color_depth; int mask_color; void *unwrite_bank; /* C function on some machines, asm on i386 */ AL_METHOD(void, set_clip, (struct BITMAP *bmp)); AL_METHOD(void, acquire, (struct BITMAP *bmp)); AL_METHOD(void, release, (struct BITMAP *bmp)); AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); AL_METHOD(int, getpixel, (struct BITMAP *bmp, int x, int y)); AL_METHOD(void, putpixel, (struct BITMAP *bmp, int x, int y, int color)); AL_METHOD(void, vline, (struct BITMAP *bmp, int x, int y_1, int y2, int color)); AL_METHOD(void, hline, (struct BITMAP *bmp, int x1, int y, int x2, int color)); AL_METHOD(void, hfill, (struct BITMAP *bmp, int x1, int y, int x2, int color)); AL_METHOD(void, line, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_METHOD(void, fastline, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_METHOD(void, rectfill, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_METHOD(void, triangle, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color)); AL_METHOD(void, draw_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_256_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_sprite_v_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_sprite_h_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_sprite_vh_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_trans_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_trans_rgba_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color)); AL_METHOD(void, draw_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_METHOD(void, draw_character, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)); AL_METHOD(void, draw_glyph, (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg)); AL_METHOD(void, blit_from_memory, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_to_memory, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_to_self, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_to_self_forward, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_to_self_backward, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, blit_between_formats, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_METHOD(void, clear_to_color, (struct BITMAP *bitmap, int color)); AL_METHOD(void, pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)); AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); AL_METHOD(void, draw_sprite_end, (void)); AL_METHOD(void, blit_end, (void)); AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color)); AL_METHOD(void, polygon3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[])); AL_METHOD(void, polygon3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[])); AL_METHOD(void, triangle3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)); AL_METHOD(void, triangle3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)); AL_METHOD(void, quad3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)); AL_METHOD(void, quad3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)); AL_METHOD(void, draw_sprite_ex, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int mode, int flip )); } GFX_VTABLE; AL_VAR(GFX_VTABLE, __linear_vtable8); AL_VAR(GFX_VTABLE, __linear_vtable15); AL_VAR(GFX_VTABLE, __linear_vtable16); AL_VAR(GFX_VTABLE, __linear_vtable24); AL_VAR(GFX_VTABLE, __linear_vtable32); typedef struct _VTABLE_INFO { int color_depth; GFX_VTABLE *vtable; } _VTABLE_INFO; AL_ARRAY(_VTABLE_INFO, _vtable_list); /* macros for constructing the vtable list */ #define BEGIN_COLOR_DEPTH_LIST \ _VTABLE_INFO _vtable_list[] = \ { #define END_COLOR_DEPTH_LIST \ { 0, NULL } \ }; #define COLOR_DEPTH_8 \ { 8, &__linear_vtable8 }, #define COLOR_DEPTH_15 \ { 15, &__linear_vtable15 }, #define COLOR_DEPTH_16 \ { 16, &__linear_vtable16 }, #define COLOR_DEPTH_24 \ { 24, &__linear_vtable24 }, #define COLOR_DEPTH_32 \ { 32, &__linear_vtable32 }, typedef struct BITMAP /* a bitmap structure */ { int w, h; /* width and height in pixels */ int clip; /* flag if clipping is turned on */ int cl, cr, ct, cb; /* clip left, right, top and bottom values */ GFX_VTABLE *vtable; /* drawing functions */ void *write_bank; /* C func on some machines, asm on i386 */ void *read_bank; /* C func on some machines, asm on i386 */ void *dat; /* the memory we allocated for the bitmap */ unsigned long id; /* for identifying sub-bitmaps */ void *extra; /* points to a structure with more info */ int x_ofs; /* horizontal offset (for sub-bitmaps) */ int y_ofs; /* vertical offset (for sub-bitmaps) */ int seg; /* bitmap segment */ ZERO_SIZE_ARRAY(unsigned char *, line); } BITMAP; #define BMP_ID_VIDEO 0x80000000 #define BMP_ID_SYSTEM 0x40000000 #define BMP_ID_SUB 0x20000000 #define BMP_ID_PLANAR 0x10000000 #define BMP_ID_NOBLIT 0x08000000 #define BMP_ID_LOCKED 0x04000000 #define BMP_ID_AUTOLOCK 0x02000000 #define BMP_ID_MASK 0x01FFFFFF AL_VAR(BITMAP *, screen); #define SCREEN_W (gfx_driver ? gfx_driver->w : 0) #define SCREEN_H (gfx_driver ? gfx_driver->h : 0) #define VIRTUAL_W (screen ? screen->w : 0) #define VIRTUAL_H (screen ? screen->h : 0) #define COLORCONV_NONE 0 #define COLORCONV_8_TO_15 1 #define COLORCONV_8_TO_16 2 #define COLORCONV_8_TO_24 4 #define COLORCONV_8_TO_32 8 #define COLORCONV_15_TO_8 0x10 #define COLORCONV_15_TO_16 0x20 #define COLORCONV_15_TO_24 0x40 #define COLORCONV_15_TO_32 0x80 #define COLORCONV_16_TO_8 0x100 #define COLORCONV_16_TO_15 0x200 #define COLORCONV_16_TO_24 0x400 #define COLORCONV_16_TO_32 0x800 #define COLORCONV_24_TO_8 0x1000 #define COLORCONV_24_TO_15 0x2000 #define COLORCONV_24_TO_16 0x4000 #define COLORCONV_24_TO_32 0x8000 #define COLORCONV_32_TO_8 0x10000 #define COLORCONV_32_TO_15 0x20000 #define COLORCONV_32_TO_16 0x40000 #define COLORCONV_32_TO_24 0x80000 #define COLORCONV_32A_TO_8 0x100000 #define COLORCONV_32A_TO_15 0x200000 #define COLORCONV_32A_TO_16 0x400000 #define COLORCONV_32A_TO_24 0x800000 #define COLORCONV_DITHER_PAL 0x1000000 #define COLORCONV_DITHER_HI 0x2000000 #define COLORCONV_KEEP_TRANS 0x4000000 #define COLORCONV_DITHER (COLORCONV_DITHER_PAL | \ COLORCONV_DITHER_HI) #define COLORCONV_EXPAND_256 (COLORCONV_8_TO_15 | \ COLORCONV_8_TO_16 | \ COLORCONV_8_TO_24 | \ COLORCONV_8_TO_32) #define COLORCONV_REDUCE_TO_256 (COLORCONV_15_TO_8 | \ COLORCONV_16_TO_8 | \ COLORCONV_24_TO_8 | \ COLORCONV_32_TO_8 | \ COLORCONV_32A_TO_8) #define COLORCONV_EXPAND_15_TO_16 COLORCONV_15_TO_16 #define COLORCONV_REDUCE_16_TO_15 COLORCONV_16_TO_15 #define COLORCONV_EXPAND_HI_TO_TRUE (COLORCONV_15_TO_24 | \ COLORCONV_15_TO_32 | \ COLORCONV_16_TO_24 | \ COLORCONV_16_TO_32) #define COLORCONV_REDUCE_TRUE_TO_HI (COLORCONV_24_TO_15 | \ COLORCONV_24_TO_16 | \ COLORCONV_32_TO_15 | \ COLORCONV_32_TO_16) #define COLORCONV_24_EQUALS_32 (COLORCONV_24_TO_32 | \ COLORCONV_32_TO_24) #define COLORCONV_TOTAL (COLORCONV_EXPAND_256 | \ COLORCONV_REDUCE_TO_256 | \ COLORCONV_EXPAND_15_TO_16 | \ COLORCONV_REDUCE_16_TO_15 | \ COLORCONV_EXPAND_HI_TO_TRUE | \ COLORCONV_REDUCE_TRUE_TO_HI | \ COLORCONV_24_EQUALS_32 | \ COLORCONV_32A_TO_15 | \ COLORCONV_32A_TO_16 | \ COLORCONV_32A_TO_24) #define COLORCONV_PARTIAL (COLORCONV_EXPAND_15_TO_16 | \ COLORCONV_REDUCE_16_TO_15 | \ COLORCONV_24_EQUALS_32) #define COLORCONV_MOST (COLORCONV_EXPAND_15_TO_16 | \ COLORCONV_REDUCE_16_TO_15 | \ COLORCONV_EXPAND_HI_TO_TRUE | \ COLORCONV_REDUCE_TRUE_TO_HI | \ COLORCONV_24_EQUALS_32) #define COLORCONV_KEEP_ALPHA (COLORCONV_TOTAL \ & ~(COLORCONV_32A_TO_8 | \ COLORCONV_32A_TO_15 | \ COLORCONV_32A_TO_16 | \ COLORCONV_32A_TO_24)) AL_FUNC(GFX_MODE_LIST *, get_gfx_mode_list, (int card)); AL_FUNC(void, destroy_gfx_mode_list, (GFX_MODE_LIST *gfx_mode_list)); AL_FUNC(void, set_color_depth, (int depth)); AL_FUNC(int, get_color_depth, (void)); AL_FUNC(void, set_color_conversion, (int mode)); AL_FUNC(int, get_color_conversion, (void)); AL_FUNC(void, request_refresh_rate, (int rate)); AL_FUNC(int, get_refresh_rate, (void)); AL_FUNC(int, set_gfx_mode, (int card, int w, int h, int v_w, int v_h)); AL_FUNC(int, scroll_screen, (int x, int y)); AL_FUNC(int, request_scroll, (int x, int y)); AL_FUNC(int, poll_scroll, (void)); AL_FUNC(int, show_video_bitmap, (BITMAP *bitmap)); AL_FUNC(int, request_video_bitmap, (BITMAP *bitmap)); AL_FUNC(int, enable_triple_buffer, (void)); AL_FUNC(BITMAP *, create_bitmap, (int width, int height)); AL_FUNC(BITMAP *, create_bitmap_ex, (int color_depth, int width, int height)); AL_FUNC(BITMAP *, create_sub_bitmap, (BITMAP *parent, int x, int y, int width, int height)); AL_FUNC(BITMAP *, create_video_bitmap, (int width, int height)); AL_FUNC(BITMAP *, create_system_bitmap, (int width, int height)); AL_FUNC(void, destroy_bitmap, (BITMAP *bitmap)); AL_FUNC(void, set_clip_rect, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); AL_FUNC(void, add_clip_rect, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); AL_FUNC(void, clear_bitmap, (BITMAP *bitmap)); AL_FUNC(void, vsync, (void)); /* Bitfield for relaying graphics driver type information */ #define GFX_TYPE_UNKNOWN 0 #define GFX_TYPE_WINDOWED 1 #define GFX_TYPE_FULLSCREEN 2 #define GFX_TYPE_DEFINITE 4 #define GFX_TYPE_MAGIC 8 AL_FUNC(int, get_gfx_mode_type, (int graphics_card)); AL_FUNC(int, get_gfx_mode, (void)); #define SWITCH_NONE 0 #define SWITCH_PAUSE 1 #define SWITCH_AMNESIA 2 #define SWITCH_BACKGROUND 3 #define SWITCH_BACKAMNESIA 4 #define SWITCH_IN 0 #define SWITCH_OUT 1 AL_FUNC(int, set_display_switch_mode, (int mode)); AL_FUNC(int, get_display_switch_mode, (void)); AL_FUNC(int, set_display_switch_callback, (int dir, AL_METHOD(void, cb, (void)))); AL_FUNC(void, remove_display_switch_callback, (AL_METHOD(void, cb, (void)))); AL_FUNC(void, lock_bitmap, (struct BITMAP *bmp)); #ifdef __cplusplus } #endif #include "inline/gfx.inl" #endif /* ifndef ALLEGRO_GFX_H */ allegro-4.4.3.1/include/allegro/joystick.h0000664000175000017500000000713113437077643017362 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_JOYSTICK_H #define ALLEGRO_JOYSTICK_H #include "base.h" #ifdef __cplusplus extern "C" { #endif #define JOY_TYPE_AUTODETECT -1 #define JOY_TYPE_NONE 0 #define MAX_JOYSTICKS 8 #define MAX_JOYSTICK_AXIS 3 #define MAX_JOYSTICK_STICKS 5 #define MAX_JOYSTICK_BUTTONS 32 /* information about a single joystick axis */ typedef struct JOYSTICK_AXIS_INFO { int pos; int d1, d2; AL_CONST char *name; } JOYSTICK_AXIS_INFO; /* information about one or more axis (a slider or directional control) */ typedef struct JOYSTICK_STICK_INFO { int flags; int num_axis; JOYSTICK_AXIS_INFO axis[MAX_JOYSTICK_AXIS]; AL_CONST char *name; } JOYSTICK_STICK_INFO; /* information about a joystick button */ typedef struct JOYSTICK_BUTTON_INFO { int b; AL_CONST char *name; } JOYSTICK_BUTTON_INFO; /* information about an entire joystick */ typedef struct JOYSTICK_INFO { int flags; int num_sticks; int num_buttons; JOYSTICK_STICK_INFO stick[MAX_JOYSTICK_STICKS]; JOYSTICK_BUTTON_INFO button[MAX_JOYSTICK_BUTTONS]; } JOYSTICK_INFO; /* joystick status flags */ #define JOYFLAG_DIGITAL 1 #define JOYFLAG_ANALOGUE 2 #define JOYFLAG_CALIB_DIGITAL 4 #define JOYFLAG_CALIB_ANALOGUE 8 #define JOYFLAG_CALIBRATE 16 #define JOYFLAG_SIGNED 32 #define JOYFLAG_UNSIGNED 64 /* alternative spellings */ #define JOYFLAG_ANALOG JOYFLAG_ANALOGUE #define JOYFLAG_CALIB_ANALOG JOYFLAG_CALIB_ANALOGUE /* global joystick information */ AL_ARRAY(JOYSTICK_INFO, joy); AL_VAR(int, num_joysticks); typedef struct JOYSTICK_DRIVER /* driver for reading joystick input */ { int id; AL_CONST char *name; AL_CONST char *desc; AL_CONST char *ascii_name; AL_METHOD(int, init, (void)); AL_METHOD(void, exit, (void)); AL_METHOD(int, poll, (void)); AL_METHOD(int, save_data, (void)); AL_METHOD(int, load_data, (void)); AL_METHOD(AL_CONST char *, calibrate_name, (int n)); AL_METHOD(int, calibrate, (int n)); } JOYSTICK_DRIVER; AL_VAR(JOYSTICK_DRIVER, joystick_none); AL_VAR(JOYSTICK_DRIVER *, joystick_driver); AL_ARRAY(_DRIVER_INFO, _joystick_driver_list); /* macros for constructing the driver list */ #define BEGIN_JOYSTICK_DRIVER_LIST \ _DRIVER_INFO _joystick_driver_list[] = \ { #define END_JOYSTICK_DRIVER_LIST \ { JOY_TYPE_NONE, &joystick_none, TRUE }, \ { 0, NULL, 0 } \ }; AL_FUNC(int, install_joystick, (int type)); AL_FUNC(void, remove_joystick, (void)); AL_FUNC(int, poll_joystick, (void)); AL_FUNC(int, save_joystick_data, (AL_CONST char *filename)); AL_FUNC(int, load_joystick_data, (AL_CONST char *filename)); AL_FUNC(AL_CONST char *, calibrate_joystick_name, (int n)); AL_FUNC(int, calibrate_joystick, (int n)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_JOYSTICK_H */ allegro-4.4.3.1/include/allegro/font.h0000664000175000017500000000454513437077643016477 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Font loading routines. * * By Evert Glebbeek. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FONT_H #define ALLEGRO_FONT_H #include "base.h" #ifdef __cplusplus extern "C" { #endif typedef struct FONT_GLYPH /* a single monochrome font character */ { short w, h; ZERO_SIZE_ARRAY(unsigned char, dat); } FONT_GLYPH; struct FONT_VTABLE; typedef struct FONT { void *data; int height; struct FONT_VTABLE *vtable; } FONT; AL_FUNC(int, font_has_alpha, (FONT *f)); AL_FUNC(void, make_trans_font, (FONT *f)); AL_FUNC(int, is_trans_font, (FONT *f)); AL_FUNC(int, is_color_font, (FONT *f)); AL_FUNC(int, is_mono_font, (FONT *f)); AL_FUNC(int, is_compatible_font, (FONT *f1, FONT *f2)); AL_FUNC(void, register_font_file_type, (AL_CONST char *ext, FONT *(*load)(AL_CONST char *filename, RGB *pal, void *param))); AL_FUNC(FONT *, load_font, (AL_CONST char *filename, RGB *pal, void *param)); AL_FUNC(FONT *, load_dat_font, (AL_CONST char *filename, RGB *pal, void *param)); AL_FUNC(FONT *, load_bios_font, (AL_CONST char *filename, RGB *pal, void *param)); AL_FUNC(FONT *, load_grx_font, (AL_CONST char *filename, RGB *pal, void *param)); AL_FUNC(FONT *, load_grx_or_bios_font, (AL_CONST char *filename, RGB *pal, void *param)); AL_FUNC(FONT *, load_bitmap_font, (AL_CONST char *fname, RGB *pal, void *param)); AL_FUNC(FONT *, load_txt_font, (AL_CONST char *fname, RGB *pal, void *param)); AL_FUNC(FONT *, grab_font_from_bitmap, (BITMAP *bmp)); AL_FUNC(int, get_font_ranges, (FONT *f)); AL_FUNC(int, get_font_range_begin, (FONT *f, int range)); AL_FUNC(int, get_font_range_end, (FONT *f, int range)); AL_FUNC(FONT *, extract_font_range, (FONT *f, int begin, int end)); AL_FUNC(FONT *, merge_fonts, (FONT *f1, FONT *f2)); AL_FUNC(int, transpose_font, (FONT *f, int drange)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_FONT_H */ allegro-4.4.3.1/include/allegro/fli.h0000664000175000017500000000403513437077643016275 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * FLI/FLC routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FLI_H #define ALLEGRO_FLI_H #include "base.h" #include "file.h" #include "palette.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; #define FLI_OK 0 /* FLI player return values */ #define FLI_EOF -1 #define FLI_ERROR -2 #define FLI_NOT_OPEN -3 AL_FUNC(int, play_fli, (AL_CONST char *filename, struct BITMAP *bmp, int loop, AL_METHOD(int, callback, (void)))); AL_FUNC(int, play_fli_pf, (PACKFILE *pf, struct BITMAP *bmp, AL_METHOD(int, callback, (void)))); AL_FUNC(int, play_memory_fli, (void *fli_data, struct BITMAP *bmp, int loop, AL_METHOD(int, callback, (void)))); AL_FUNC(int, open_fli, (AL_CONST char *filename)); AL_FUNC(int, open_fli_pf, (PACKFILE *pf)); AL_FUNC(int, open_memory_fli, (void *fli_data)); AL_FUNC(void, close_fli, (void)); AL_FUNC(int, next_fli_frame, (int loop)); AL_FUNC(void, reset_fli_variables, (void)); AL_VAR(struct BITMAP *, fli_bitmap); /* current frame of the FLI */ AL_VAR(PALETTE, fli_palette); /* current FLI palette */ AL_VAR(int, fli_bmp_dirty_from); /* what part of fli_bitmap is dirty */ AL_VAR(int, fli_bmp_dirty_to); AL_VAR(int, fli_pal_dirty_from); /* what part of fli_palette is dirty */ AL_VAR(int, fli_pal_dirty_to); AL_VAR(int, fli_frame); /* current frame number */ AL_VAR(volatile int, fli_timer); /* for timing FLI playback */ #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_FLI_H */ allegro-4.4.3.1/include/allegro/palette.h0000664000175000017500000000162213437077643017160 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Palette type. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_PALETTE_H #define ALLEGRO_PALETTE_H #ifdef __cplusplus extern "C" { #endif typedef struct RGB { unsigned char r, g, b; unsigned char filler; } RGB; #define PAL_SIZE 256 typedef RGB PALETTE[PAL_SIZE]; #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_PALETTE_H */ allegro-4.4.3.1/include/allegro/graphics.h0000664000175000017500000000160513437077643017323 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Container for all graphics related routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_GRAPHICS_H #define ALLEGRO_GRAPHICS_H #include "base.h" #include "gfx.h" #include "text.h" #include "3d.h" #include "draw.h" #include "color.h" #include "palette.h" #include "rle.h" #include "compiled.h" #endif /* ifndef ALLEGRO_GRAPHICS_H */ allegro-4.4.3.1/include/allegro/fix.h0000664000175000017500000002474013437077643016316 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * C++ wrapper for fixed point math type. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FIX_H #define ALLEGRO_FIX_H #include "fixed.h" #include "fmaths.h" #ifdef __cplusplus class fix /* C++ wrapper for the fixed point routines */ { public: fixed v; fix() : v(0) {} fix(const fix &x) : v(x.v) {} explicit fix(const int x) : v(itofix(x)) {} explicit fix(const long x) : v(itofix(x)) {} explicit fix(const unsigned int x) : v(itofix(x)) {} explicit fix(const unsigned long x) : v(itofix(x)) {} explicit fix(const float x) : v(ftofix(x)) {} explicit fix(const double x) : v(ftofix(x)) {} operator int() const { return fixtoi(v); } operator long() const { return fixtoi(v); } operator unsigned int() const { return fixtoi(v); } operator unsigned long() const { return fixtoi(v); } operator float() const { return fixtof(v); } operator double() const { return fixtof(v); } fix& operator = (const fix &x) { v = x.v; return *this; } fix& operator = (const int x) { v = itofix(x); return *this; } fix& operator = (const long x) { v = itofix(x); return *this; } fix& operator = (const unsigned int x) { v = itofix(x); return *this; } fix& operator = (const unsigned long x) { v = itofix(x); return *this; } fix& operator = (const float x) { v = ftofix(x); return *this; } fix& operator = (const double x) { v = ftofix(x); return *this; } fix& operator += (const fix x) { v += x.v; return *this; } fix& operator += (const int x) { v += itofix(x); return *this; } fix& operator += (const long x) { v += itofix(x); return *this; } fix& operator += (const float x) { v += ftofix(x); return *this; } fix& operator += (const double x) { v += ftofix(x); return *this; } fix& operator -= (const fix x) { v -= x.v; return *this; } fix& operator -= (const int x) { v -= itofix(x); return *this; } fix& operator -= (const long x) { v -= itofix(x); return *this; } fix& operator -= (const float x) { v -= ftofix(x); return *this; } fix& operator -= (const double x) { v -= ftofix(x); return *this; } fix& operator *= (const fix x) { v = fixmul(v, x.v); return *this; } fix& operator *= (const int x) { v *= x; return *this; } fix& operator *= (const long x) { v *= x; return *this; } fix& operator *= (const float x) { v = ftofix(fixtof(v) * x); return *this; } fix& operator *= (const double x) { v = ftofix(fixtof(v) * x); return *this; } fix& operator /= (const fix x) { v = fixdiv(v, x.v); return *this; } fix& operator /= (const int x) { v /= x; return *this; } fix& operator /= (const long x) { v /= x; return *this; } fix& operator /= (const float x) { v = ftofix(fixtof(v) / x); return *this; } fix& operator /= (const double x) { v = ftofix(fixtof(v) / x); return *this; } fix& operator <<= (const int x) { v <<= x; return *this; } fix& operator >>= (const int x) { v >>= x; return *this; } fix& operator ++ () { v += itofix(1); return *this; } fix& operator -- () { v -= itofix(1); return *this; } fix operator ++ (int) { fix t; t.v = v; v += itofix(1); return t; } fix operator -- (int) { fix t; t.v = v; v -= itofix(1); return t; } fix operator - () const { fix t; t.v = -v; return t; } inline friend fix operator + (const fix x, const fix y); inline friend fix operator + (const fix x, const int y); inline friend fix operator + (const int x, const fix y); inline friend fix operator + (const fix x, const long y); inline friend fix operator + (const long x, const fix y); inline friend fix operator + (const fix x, const float y); inline friend fix operator + (const float x, const fix y); inline friend fix operator + (const fix x, const double y); inline friend fix operator + (const double x, const fix y); inline friend fix operator - (const fix x, const fix y); inline friend fix operator - (const fix x, const int y); inline friend fix operator - (const int x, const fix y); inline friend fix operator - (const fix x, const long y); inline friend fix operator - (const long x, const fix y); inline friend fix operator - (const fix x, const float y); inline friend fix operator - (const float x, const fix y); inline friend fix operator - (const fix x, const double y); inline friend fix operator - (const double x, const fix y); inline friend fix operator * (const fix x, const fix y); inline friend fix operator * (const fix x, const int y); inline friend fix operator * (const int x, const fix y); inline friend fix operator * (const fix x, const long y); inline friend fix operator * (const long x, const fix y); inline friend fix operator * (const fix x, const float y); inline friend fix operator * (const float x, const fix y); inline friend fix operator * (const fix x, const double y); inline friend fix operator * (const double x, const fix y); inline friend fix operator / (const fix x, const fix y); inline friend fix operator / (const fix x, const int y); inline friend fix operator / (const int x, const fix y); inline friend fix operator / (const fix x, const long y); inline friend fix operator / (const long x, const fix y); inline friend fix operator / (const fix x, const float y); inline friend fix operator / (const float x, const fix y); inline friend fix operator / (const fix x, const double y); inline friend fix operator / (const double x, const fix y); inline friend fix operator << (const fix x, const int y); inline friend fix operator >> (const fix x, const int y); inline friend int operator == (const fix x, const fix y); inline friend int operator == (const fix x, const int y); inline friend int operator == (const int x, const fix y); inline friend int operator == (const fix x, const long y); inline friend int operator == (const long x, const fix y); inline friend int operator == (const fix x, const float y); inline friend int operator == (const float x, const fix y); inline friend int operator == (const fix x, const double y); inline friend int operator == (const double x, const fix y); inline friend int operator != (const fix x, const fix y); inline friend int operator != (const fix x, const int y); inline friend int operator != (const int x, const fix y); inline friend int operator != (const fix x, const long y); inline friend int operator != (const long x, const fix y); inline friend int operator != (const fix x, const float y); inline friend int operator != (const float x, const fix y); inline friend int operator != (const fix x, const double y); inline friend int operator != (const double x, const fix y); inline friend int operator < (const fix x, const fix y); inline friend int operator < (const fix x, const int y); inline friend int operator < (const int x, const fix y); inline friend int operator < (const fix x, const long y); inline friend int operator < (const long x, const fix y); inline friend int operator < (const fix x, const float y); inline friend int operator < (const float x, const fix y); inline friend int operator < (const fix x, const double y); inline friend int operator < (const double x, const fix y); inline friend int operator > (const fix x, const fix y); inline friend int operator > (const fix x, const int y); inline friend int operator > (const int x, const fix y); inline friend int operator > (const fix x, const long y); inline friend int operator > (const long x, const fix y); inline friend int operator > (const fix x, const float y); inline friend int operator > (const float x, const fix y); inline friend int operator > (const fix x, const double y); inline friend int operator > (const double x, const fix y); inline friend int operator <= (const fix x, const fix y); inline friend int operator <= (const fix x, const int y); inline friend int operator <= (const int x, const fix y); inline friend int operator <= (const fix x, const long y); inline friend int operator <= (const long x, const fix y); inline friend int operator <= (const fix x, const float y); inline friend int operator <= (const float x, const fix y); inline friend int operator <= (const fix x, const double y); inline friend int operator <= (const double x, const fix y); inline friend int operator >= (const fix x, const fix y); inline friend int operator >= (const fix x, const int y); inline friend int operator >= (const int x, const fix y); inline friend int operator >= (const fix x, const long y); inline friend int operator >= (const long x, const fix y); inline friend int operator >= (const fix x, const float y); inline friend int operator >= (const float x, const fix y); inline friend int operator >= (const fix x, const double y); inline friend int operator >= (const double x, const fix y); inline friend fix sqrt(fix x); inline friend fix cos(fix x); inline friend fix sin(fix x); inline friend fix tan(fix x); inline friend fix acos(fix x); inline friend fix asin(fix x); inline friend fix atan(fix x); inline friend fix atan2(fix x, fix y); }; #endif /* ifdef __cplusplus */ #include "inline/fix.inl" #endif /* ifndef ALLEGRO_FIX_H */ allegro-4.4.3.1/include/allegro/config.h0000664000175000017500000000546613437077643017001 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration file access routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_CONFIG_H #define ALLEGRO_CONFIG_H #include "base.h" #ifdef __cplusplus extern "C" { #endif AL_FUNC(void, set_config_file, (AL_CONST char *filename)); AL_FUNC(void, set_config_data, (AL_CONST char *data, int length)); AL_FUNC(void, override_config_file, (AL_CONST char *filename)); AL_FUNC(void, override_config_data, (AL_CONST char *data, int length)); AL_FUNC(void, flush_config_file, (void)); AL_FUNC(void, reload_config_texts, (AL_CONST char *new_language)); AL_FUNC(void, push_config_state, (void)); AL_FUNC(void, pop_config_state, (void)); AL_FUNC(void, hook_config_section, (AL_CONST char *section, AL_METHOD(int, intgetter, (AL_CONST char *, int)), AL_METHOD(AL_CONST char *, stringgetter, (AL_CONST char *, AL_CONST char *)), AL_METHOD(void, stringsetter, (AL_CONST char *, AL_CONST char *)))); AL_FUNC(int, config_is_hooked, (AL_CONST char *section)); AL_FUNC(AL_CONST char *, get_config_string, (AL_CONST char *section, AL_CONST char *name, AL_CONST char *def)); AL_FUNC(int, get_config_int, (AL_CONST char *section, AL_CONST char *name, int def)); AL_FUNC(int, get_config_hex, (AL_CONST char *section, AL_CONST char *name, int def)); AL_FUNC(float, get_config_float, (AL_CONST char *section, AL_CONST char *name, float def)); AL_FUNC(int, get_config_id, (AL_CONST char *section, AL_CONST char *name, int def)); AL_FUNC(char **, get_config_argv, (AL_CONST char *section, AL_CONST char *name, int *argc)); AL_FUNC(AL_CONST char *, get_config_text, (AL_CONST char *msg)); AL_FUNC(void, set_config_string, (AL_CONST char *section, AL_CONST char *name, AL_CONST char *val)); AL_FUNC(void, set_config_int, (AL_CONST char *section, AL_CONST char *name, int val)); AL_FUNC(void, set_config_hex, (AL_CONST char *section, AL_CONST char *name, int val)); AL_FUNC(void, set_config_float, (AL_CONST char *section, AL_CONST char *name, float val)); AL_FUNC(void, set_config_id, (AL_CONST char *section, AL_CONST char *name, int val)); AL_FUNC(int, list_config_entries, (AL_CONST char *section, AL_CONST char ***names)); AL_FUNC(int, list_config_sections, (AL_CONST char ***names)); AL_FUNC(void, free_config_entries, (AL_CONST char ***names)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_CONFIG_H */ allegro-4.4.3.1/include/allegro/draw.h0000664000175000017500000001303613437077643016461 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Drawing and sprite routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DRAW_H #define ALLEGRO_DRAW_H #include "base.h" #include "fixed.h" #include "gfx.h" #ifdef __cplusplus extern "C" { #endif #define DRAW_MODE_SOLID 0 /* flags for drawing_mode() */ #define DRAW_MODE_XOR 1 #define DRAW_MODE_COPY_PATTERN 2 #define DRAW_MODE_SOLID_PATTERN 3 #define DRAW_MODE_MASKED_PATTERN 4 #define DRAW_MODE_TRANS 5 AL_FUNC(void, drawing_mode, (int mode, struct BITMAP *pattern, int x_anchor, int y_anchor)); AL_FUNC(void, xor_mode, (int on)); AL_FUNC(void, solid_mode, (void)); AL_FUNC(void, do_line, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); AL_FUNC(void, _soft_triangle, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color)); AL_FUNC(void, _soft_polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); AL_FUNC(void, _soft_rect, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_FUNC(void, do_circle, (struct BITMAP *bmp, int x, int y, int radius, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); AL_FUNC(void, _soft_circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); AL_FUNC(void, _soft_circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); AL_FUNC(void, do_ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); AL_FUNC(void, _soft_ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); AL_FUNC(void, _soft_ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); AL_FUNC(void, do_arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); AL_FUNC(void, _soft_arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); AL_FUNC(void, calc_spline, (AL_CONST int points[8], int npts, int *x, int *y)); AL_FUNC(void, _soft_spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); AL_FUNC(void, _soft_floodfill, (struct BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, stretch_blit, (struct BITMAP *s, struct BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h)); AL_FUNC(void, masked_stretch_blit, (struct BITMAP *s, struct BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h)); AL_FUNC(void, stretch_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int w, int h)); AL_FUNC(void, _soft_draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); /* rotate+trans */ AL_FUNC(void, rotate_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle)); AL_FUNC(void, rotate_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle)); AL_FUNC(void, rotate_scaled_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale)); AL_FUNC(void, rotate_scaled_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale)); AL_FUNC(void, pivot_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle)); AL_FUNC(void, pivot_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle)); AL_FUNC(void, pivot_scaled_sprite_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale)); AL_FUNC(void, pivot_scaled_sprite_v_flip_trans, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale)); /* rotate+lit */ AL_FUNC(void, rotate_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, int color)); AL_FUNC(void, rotate_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, int color)); AL_FUNC(void, rotate_scaled_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale, int color)); AL_FUNC(void, rotate_scaled_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale, int color)); AL_FUNC(void, pivot_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, int color)); AL_FUNC(void, pivot_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, int color)); AL_FUNC(void, pivot_scaled_sprite_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale, int color)); AL_FUNC(void, pivot_scaled_sprite_v_flip_lit, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale, int color)); #ifdef __cplusplus } #endif #include "inline/draw.inl" #endif /* ifndef ALLEGRO_DRAW_H */ allegro-4.4.3.1/include/allegro/lzss.h0000664000175000017500000000246713437077643016525 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Compression routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_LZSS_H #define ALLEGRO_LZSS_H #include "base.h" #ifdef __cplusplus extern "C" { #endif typedef struct LZSS_PACK_DATA LZSS_PACK_DATA; typedef struct LZSS_UNPACK_DATA LZSS_UNPACK_DATA; AL_FUNC(LZSS_PACK_DATA *, create_lzss_pack_data, (void)); AL_FUNC(void, free_lzss_pack_data, (LZSS_PACK_DATA *dat)); AL_FUNC(int, lzss_write, (PACKFILE *file, LZSS_PACK_DATA *dat, int size, unsigned char *buf, int last)); AL_FUNC(LZSS_UNPACK_DATA *, create_lzss_unpack_data, (void)); AL_FUNC(void, free_lzss_unpack_data, (LZSS_UNPACK_DATA *dat)); AL_FUNC(int, lzss_read, (PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, unsigned char *buf)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_LZSS_H */ allegro-4.4.3.1/include/allegro/alinline.h0000664000175000017500000000157513437077643017324 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Inline functions (generic C). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "inline/system.inl" #include "inline/gfx.inl" #include "inline/color.inl" #include "inline/draw.inl" #include "inline/fmaths.inl" #include "inline/3dmaths.inl" #include "inline/matrix.inl" /* alcompat.h includes some inline functions */ #include "alcompat.h" allegro-4.4.3.1/include/allegro/mouse.h0000664000175000017500000000723113437077643016654 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mouse routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_MOUSE_H #define ALLEGRO_MOUSE_H #include "base.h" #ifdef __cplusplus extern "C" { #endif #define MOUSEDRV_AUTODETECT -1 #define MOUSEDRV_NONE 0 typedef struct MOUSE_DRIVER { int id; AL_CONST char *name; AL_CONST char *desc; AL_CONST char *ascii_name; AL_METHOD(int, init, (void)); AL_METHOD(void, exit, (void)); AL_METHOD(void, poll, (void)); AL_METHOD(void, timer_poll, (void)); AL_METHOD(void, position, (int x, int y)); AL_METHOD(void, set_range, (int x1, int y_1, int x2, int y2)); AL_METHOD(void, set_speed, (int xspeed, int yspeed)); AL_METHOD(void, get_mickeys, (int *mickeyx, int *mickeyy)); AL_METHOD(int, analyse_data, (AL_CONST char *buffer, int size)); AL_METHOD(void, enable_hardware_cursor, (int mode)); AL_METHOD(int, select_system_cursor, (int cursor)); } MOUSE_DRIVER; AL_VAR(MOUSE_DRIVER, mousedrv_none); AL_VAR(MOUSE_DRIVER *, mouse_driver); AL_ARRAY(_DRIVER_INFO, _mouse_driver_list); AL_FUNC(int, install_mouse, (void)); AL_FUNC(void, remove_mouse, (void)); AL_FUNC(int, poll_mouse, (void)); AL_FUNC(int, mouse_needs_poll, (void)); AL_FUNC(void, enable_hardware_cursor, (void)); AL_FUNC(void, disable_hardware_cursor, (void)); /* Mouse cursors */ #define MOUSE_CURSOR_NONE 0 #define MOUSE_CURSOR_ALLEGRO 1 #define MOUSE_CURSOR_ARROW 2 #define MOUSE_CURSOR_BUSY 3 #define MOUSE_CURSOR_QUESTION 4 #define MOUSE_CURSOR_EDIT 5 #define AL_NUM_MOUSE_CURSORS 6 AL_VAR(struct BITMAP *, mouse_sprite); AL_VAR(int, mouse_x_focus); AL_VAR(int, mouse_y_focus); AL_VAR(volatile int, mouse_x); AL_VAR(volatile int, mouse_y); AL_VAR(volatile int, mouse_z); AL_VAR(volatile int, mouse_w); AL_VAR(volatile int, mouse_b); AL_VAR(volatile int, mouse_pos); AL_VAR(volatile int, freeze_mouse_flag); #define MOUSE_FLAG_MOVE 1 #define MOUSE_FLAG_LEFT_DOWN 2 #define MOUSE_FLAG_LEFT_UP 4 #define MOUSE_FLAG_RIGHT_DOWN 8 #define MOUSE_FLAG_RIGHT_UP 16 #define MOUSE_FLAG_MIDDLE_DOWN 32 #define MOUSE_FLAG_MIDDLE_UP 64 #define MOUSE_FLAG_MOVE_Z 128 #define MOUSE_FLAG_MOVE_W 256 AL_FUNCPTR(void, mouse_callback, (int flags)); AL_FUNC(void, show_mouse, (struct BITMAP *bmp)); AL_FUNC(void, scare_mouse, (void)); AL_FUNC(void, scare_mouse_area, (int x, int y, int w, int h)); AL_FUNC(void, unscare_mouse, (void)); AL_FUNC(void, position_mouse, (int x, int y)); AL_FUNC(void, position_mouse_z, (int z)); AL_FUNC(void, position_mouse_w, (int w)); AL_FUNC(void, set_mouse_range, (int x1, int y_1, int x2, int y2)); AL_FUNC(void, set_mouse_speed, (int xspeed, int yspeed)); AL_FUNC(void, select_mouse_cursor, (int cursor)); AL_FUNC(void, set_mouse_cursor_bitmap, (int cursor, struct BITMAP *bmp)); AL_FUNC(void, set_mouse_sprite_focus, (int x, int y)); AL_FUNC(void, get_mouse_mickeys, (int *mickeyx, int *mickeyy)); AL_FUNC(void, set_mouse_sprite, (struct BITMAP *sprite)); AL_FUNC(int, show_os_cursor, (int cursor)); AL_FUNC(int, mouse_on_screen, (void)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_MOUSE_H */ allegro-4.4.3.1/include/allegro/base.h0000664000175000017500000000532313437077643016436 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Base header, defines basic stuff needed by pretty much * everything else. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_BASE_H #define ALLEGRO_BASE_H #ifndef ALLEGRO_NO_STD_HEADERS #include #include #include #include #include #include #include #endif #if (defined DEBUGMODE) && (defined FORTIFY) #include #endif #if (defined DEBUGMODE) && (defined DMALLOC) #include #endif #include "internal/alconfig.h" #ifdef __cplusplus extern "C" { #endif #define ALLEGRO_VERSION 4 #define ALLEGRO_SUB_VERSION 4 #define ALLEGRO_WIP_VERSION 3 #define ALLEGRO_VERSION_STR "4.4.3" #define ALLEGRO_DATE_STR "2019" #define ALLEGRO_DATE 20190303 /* yyyymmdd */ /*******************************************/ /************ Some global stuff ************/ /*******************************************/ /* Asm build disabled as of 4.3.10+. */ #ifndef ALLEGRO_NO_ASM #define ALLEGRO_NO_ASM #endif #ifndef TRUE #define TRUE -1 #define FALSE 0 #endif #undef MIN #undef MAX #undef MID #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) /* Returns the median of x, y, z */ #define MID(x,y,z) ((x) > (y) ? ((y) > (z) ? (y) : ((x) > (z) ? \ (z) : (x))) : ((y) > (z) ? ((z) > (x) ? (z) : \ (x)): (y))) /* Optimized version of MID for when x <= z. */ #define CLAMP(x,y,z) MAX((x), MIN((y), (z))) #undef ABS #define ABS(x) (((x) >= 0) ? (x) : (-(x))) #undef SGN #define SGN(x) (((x) >= 0) ? 1 : -1) #define AL_PI 3.14159265358979323846 #define AL_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) AL_VAR(int *, allegro_errno); typedef struct _DRIVER_INFO /* info about a hardware driver */ { int id; /* integer ID */ void *driver; /* the driver structure */ int autodetect; /* set to allow autodetection */ } _DRIVER_INFO; #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_BASE_H */ allegro-4.4.3.1/include/allegro/platform/0000775000175000017500000000000013437077643017174 5ustar siegesiegeallegro-4.4.3.1/include/allegro/platform/alosx.h0000664000175000017500000000627713437077643020507 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X specific header defines. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #ifndef ALOSX_H #define ALOSX_H #ifndef ALLEGRO_MACOSX #error bad include #endif #ifndef SCAN_DEPEND #include #include #include #include #include #include #if defined __OBJC__ && defined ALLEGRO_SRC #undef TRUE #undef FALSE #import #import #import #import #import #import #import #import #import #import #import #import #import #import #undef TRUE #undef FALSE #undef assert #define TRUE -1 #define FALSE 0 #endif #endif /* The following code comes from alunix.h */ /* Magic to capture name of executable file */ extern int __crt0_argc; extern char **__crt0_argv; #ifndef ALLEGRO_NO_MAGIC_MAIN #define ALLEGRO_MAGIC_MAIN #define main _mangled_main #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address = (void*) _mangled_main; #else #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address; #endif /* System driver */ #define SYSTEM_MACOSX AL_ID('O','S','X',' ') AL_VAR(SYSTEM_DRIVER, system_macosx); /* Timer driver */ #define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') AL_VAR(TIMER_DRIVER, timerdrv_unix_pthreads); /* Keyboard driver */ #define KEYBOARD_MACOSX AL_ID('O','S','X','K') AL_VAR(KEYBOARD_DRIVER, keyboard_macosx); /* Mouse driver */ #define MOUSE_MACOSX AL_ID('O','S','X','M') AL_VAR(MOUSE_DRIVER, mouse_macosx); /* Gfx drivers */ #define GFX_QUARTZ_WINDOW AL_ID('Q','Z','W','N') #define GFX_QUARTZ_FULLSCREEN AL_ID('Q','Z','F','L') AL_VAR(GFX_DRIVER, gfx_quartz_window); AL_VAR(GFX_DRIVER, gfx_quartz_full); /* Digital sound drivers */ #define DIGI_CORE_AUDIO AL_ID('D','C','A',' ') #define DIGI_SOUND_MANAGER AL_ID('S','N','D','M') AL_VAR(DIGI_DRIVER, digi_core_audio); AL_VAR(DIGI_DRIVER, digi_sound_manager); /* MIDI music drivers */ #define MIDI_CORE_AUDIO AL_ID('M','C','A',' ') #define MIDI_QUICKTIME AL_ID('Q','T','M',' ') AL_VAR(MIDI_DRIVER, midi_core_audio); AL_VAR(MIDI_DRIVER, midi_quicktime); /* Joystick drivers */ #define JOYSTICK_HID AL_ID('H','I','D','J') AL_VAR(JOYSTICK_DRIVER, joystick_hid); #endif allegro-4.4.3.1/include/allegro/platform/aintlnx.h0000664000175000017500000001731113437077643021025 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some definitions for internal use by the Linux console code. * * By George Foot. * * See readme.txt for copyright information. */ #ifndef AINTLNX_H #define AINTLNX_H #ifdef __cplusplus extern "C" { #endif /**************************************/ /************ Driver lists ************/ /**************************************/ extern _DRIVER_INFO _linux_gfx_driver_list[]; extern _DRIVER_INFO _linux_keyboard_driver_list[]; extern _DRIVER_INFO _linux_mouse_driver_list[]; extern _DRIVER_INFO _linux_timer_driver_list[]; /* _linux_joystick_driver_list is in aintunix.h */ /****************************************/ /************ Memory mapping ************/ /* (src/linux/lmemory.c) */ /****************************************/ /* struct MAPPED_MEMORY: Used to describe a block of memory mapped * into our address space (in particular, the video memory). */ struct MAPPED_MEMORY { unsigned int base, size; /* linear address and size of block */ int perms; /* PROT_READ | PROT_WRITE, etc */ void *data; /* pointer to block after mapping */ }; extern int __al_linux_have_ioperms; int __al_linux_init_memory (void); int __al_linux_shutdown_memory (void); int __al_linux_map_memory (struct MAPPED_MEMORY *info); int __al_linux_unmap_memory (struct MAPPED_MEMORY *info); /******************************************/ /************ Standard drivers ************/ /* (src/linux/lstddrv.c) */ /******************************************/ /* This "standard drivers" business is mostly a historical artifact. * It was highly over-engineered, now simplified. It has been mostly * superseded by the newer, shinier, better bg_man. But hey, at least * it didn't suffer the fate of its cousin lasyncio.c, now dead, * buried, and without a tombstone to show for it. --pw */ typedef struct STD_DRIVER { unsigned type; /* One of the below STD_ constants */ int (*update) (void); void (*resume) (void); void (*suspend) (void); int fd; /* Descriptor of the opened device */ } STD_DRIVER; #define STD_MOUSE 0 #define STD_KBD 1 #define N_STD_DRIVERS 2 /* List of standard drivers */ extern STD_DRIVER *__al_linux_std_drivers[]; /* Exported functions */ int __al_linux_add_standard_driver (STD_DRIVER *spec); int __al_linux_remove_standard_driver (STD_DRIVER *spec); void __al_linux_update_standard_drivers (int threaded); void __al_linux_suspend_standard_drivers (void); void __al_linux_resume_standard_drivers (void); /******************************************/ /************ Console routines ************/ /* (src/linux/lconsole.c) */ /******************************************/ #define N_CRTC_REGS 24 #define N_ATC_REGS 21 #define N_GC_REGS 9 #define N_SEQ_REGS 5 #define MISC_REG_R 0x03CC #define MISC_REG_W 0x03C2 #define ATC_REG_IW 0x03C0 #define ATC_REG_R 0x03C1 #define GC_REG_I 0x03CE #define GC_REG_RW 0x03CF #define SEQ_REG_I 0x03C4 #define SEQ_REG_RW 0x03C5 #define PEL_REG_IW 0x03C8 #define PEL_REG_IR 0x03C7 #define PEL_REG_D 0x03C9 #define _is1 0x03DA #define ATC_DELAY 10 /* microseconds - for usleep() */ #define VGA_MEMORY_BASE 0xA0000 #define VGA_MEMORY_SIZE 0x10000 #define VGA_FONT_SIZE 0x02000 /* This structure is also used for video state saving/restoring, therefore it * contains fields that are used only when saving/restoring the text mode. */ typedef struct MODE_REGISTERS { unsigned char crt[N_CRTC_REGS]; unsigned char seq[N_SEQ_REGS]; unsigned char atc[N_ATC_REGS]; unsigned char gc[N_GC_REGS]; unsigned char misc; unsigned char *ext; unsigned short ext_count; unsigned char *text_font1; unsigned char *text_font2; unsigned long flags; union { unsigned char vga[768]; PALETTE allegro; } palette; } MODE_REGISTERS; extern int __al_linux_vt; extern int __al_linux_console_fd; extern int __al_linux_prev_vt; extern int __al_linux_got_text_message; extern struct termios __al_linux_startup_termio; extern struct termios __al_linux_work_termio; int __al_linux_use_console (void); int __al_linux_leave_console (void); int __al_linux_console_graphics (void); int __al_linux_console_text (void); int __al_linux_wait_for_display (void); /*************************************/ /************ VGA helpers ************/ /* (src/linux/lvgahelp.c) */ /*************************************/ int __al_linux_init_vga_helpers (void); int __al_linux_shutdown_vga_helpers (void); void __al_linux_screen_off (void); void __al_linux_screen_on (void); void __al_linux_clear_vram (void); void __al_linux_set_vga_regs (MODE_REGISTERS *regs); void __al_linux_get_vga_regs (MODE_REGISTERS *regs); void __al_linux_save_gfx_mode (void); void __al_linux_restore_gfx_mode (void); void __al_linux_save_text_mode (void); void __al_linux_restore_text_mode (void); #define __just_a_moment() usleep(ATC_DELAY) /**************************************/ /************ VT switching ************/ /* (src/linux/vtswitch.c) */ /**************************************/ /* signals for VT switching */ #define SIGRELVT SIGUSR1 #define SIGACQVT SIGUSR2 int __al_linux_init_vtswitch (void); int __al_linux_done_vtswitch (void); void __al_linux_acquire_bitmap (BITMAP *bmp); void __al_linux_release_bitmap (BITMAP *bmp); int __al_linux_set_display_switch_mode (int mode); void __al_linux_display_switch_lock (int lock, int foreground); extern volatile int __al_linux_switching_blocked; /**************************************/ /************ Mode setting ************/ /* (src/linux/lgraph.c) */ /**************************************/ typedef struct GFX_MODE_INFO { int w,h,c; /* width, height, colour depth */ int id; /* ID code, for driver's reference */ void *data; /* data for driver's use in setting the mode */ } GFX_MODE_INFO; BITMAP *__al_linux_gfx_mode_set_helper ( int w, int h, int v_w, int v_h, int c, GFX_DRIVER *driver, GFX_MODE_INFO *mode, int (*set_video_mode) (GFX_MODE_INFO *mode), void (*set_width) (int w) ); /*******************************/ /************ Mouse ************/ /* (src/linux/lmouse.c) */ /*******************************/ typedef struct INTERNAL_MOUSE_DRIVER { int device; int (*process) (unsigned char *buf, int buf_size); int num_buttons; } INTERNAL_MOUSE_DRIVER; int __al_linux_mouse_init (INTERNAL_MOUSE_DRIVER *drv); void __al_linux_mouse_exit (void); void __al_linux_mouse_position (int x, int y); void __al_linux_mouse_set_range (int x1, int y_1, int x2, int y2); void __al_linux_mouse_set_speed (int xspeed, int yspeed); void __al_linux_mouse_get_mickeys (int *mickeyx, int *mickeyy); void __al_linux_mouse_handler (int x, int y, int z, int b); #ifdef __cplusplus } #endif /* VGA register access helpers */ /* This is conditional because configure may have disabled VGA support */ #ifdef ALLEGRO_LINUX_VGA #include "allegro/internal/aintern.h" #include "allegro/internal/aintvga.h" #endif /* Functions for querying the framebuffer, for the fbcon driver */ #if (defined ALLEGRO_LINUX_FBCON) && (!defined ALLEGRO_WITH_MODULES) extern int __al_linux_get_fb_color_depth(void); extern int __al_linux_get_fb_resolution(int *width, int *height); #endif #endif /* ifndef AINTLNX_H */ allegro-4.4.3.1/include/allegro/platform/alwin.h0000664000175000017500000001157313437077643020466 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows-specific header defines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_WINDOWS #error bad include #endif /*******************************************/ /********** magic main emulation ***********/ /*******************************************/ #ifdef __cplusplus extern "C" { #endif AL_FUNC(int, _WinMain, (void *_main, void *hInst, void *hPrev, char *Cmd, int nShow)); #ifdef __cplusplus } #endif #if (!defined ALLEGRO_NO_MAGIC_MAIN) && (!defined ALLEGRO_SRC) #define ALLEGRO_MAGIC_MAIN #define main _mangled_main #undef END_OF_MAIN /* disable strict pointer typing because of the vague prototype below */ #define NO_STRICT #ifdef __cplusplus extern "C" int __stdcall WinMain(void *hInst, void *hPrev, char *Cmd, int nShow); #endif #define END_OF_MAIN() \ \ int __stdcall WinMain(void *hInst, void *hPrev, char *Cmd, int nShow) \ { \ return _WinMain((void *)_mangled_main, hInst, hPrev, Cmd, nShow); \ } #endif /*******************************************/ /************* system drivers **************/ /*******************************************/ #define SYSTEM_DIRECTX AL_ID('D','X',' ',' ') AL_VAR(SYSTEM_DRIVER, system_directx); /*******************************************/ /************** timer drivers **************/ /*******************************************/ #define TIMER_WIN32_HIGH_PERF AL_ID('W','3','2','H') #define TIMER_WIN32_LOW_PERF AL_ID('W','3','2','L') /*******************************************/ /************ keyboard drivers *************/ /*******************************************/ #define KEYBOARD_DIRECTX AL_ID('D','X',' ',' ') /*******************************************/ /************* mouse drivers ***************/ /*******************************************/ #define MOUSE_DIRECTX AL_ID('D','X',' ',' ') /*******************************************/ /*************** gfx drivers ***************/ /*******************************************/ #define GFX_DIRECTX AL_ID('D','X','A','C') #define GFX_DIRECTX_ACCEL AL_ID('D','X','A','C') #define GFX_DIRECTX_SAFE AL_ID('D','X','S','A') #define GFX_DIRECTX_SOFT AL_ID('D','X','S','O') #define GFX_DIRECTX_WIN AL_ID('D','X','W','N') #define GFX_DIRECTX_OVL AL_ID('D','X','O','V') #define GFX_GDI AL_ID('G','D','I','B') AL_VAR(GFX_DRIVER, gfx_directx_accel); AL_VAR(GFX_DRIVER, gfx_directx_safe); AL_VAR(GFX_DRIVER, gfx_directx_soft); AL_VAR(GFX_DRIVER, gfx_directx_win); AL_VAR(GFX_DRIVER, gfx_directx_ovl); AL_VAR(GFX_DRIVER, gfx_gdi); #define GFX_DRIVER_DIRECTX \ { GFX_DIRECTX_ACCEL, &gfx_directx_accel, TRUE }, \ { GFX_DIRECTX_SOFT, &gfx_directx_soft, TRUE }, \ { GFX_DIRECTX_SAFE, &gfx_directx_safe, TRUE }, \ { GFX_DIRECTX_WIN, &gfx_directx_win, TRUE }, \ { GFX_DIRECTX_OVL, &gfx_directx_ovl, TRUE }, \ { GFX_GDI, &gfx_gdi, FALSE }, /********************************************/ /*************** sound drivers **************/ /********************************************/ #define DIGI_DIRECTX(n) AL_ID('D','X','A'+(n),' ') #define DIGI_DIRECTAMX(n) AL_ID('A','X','A'+(n),' ') #define DIGI_WAVOUTID(n) AL_ID('W','O','A'+(n),' ') #define MIDI_WIN32MAPPER AL_ID('W','3','2','M') #define MIDI_WIN32(n) AL_ID('W','3','2','A'+(n)) #define MIDI_WIN32_IN(n) AL_ID('W','3','2','A'+(n)) /*******************************************/ /************ joystick drivers *************/ /*******************************************/ #define JOY_TYPE_DIRECTX AL_ID('D','X',' ',' ') #define JOY_TYPE_WIN32 AL_ID('W','3','2',' ') AL_VAR(JOYSTICK_DRIVER, joystick_directx); AL_VAR(JOYSTICK_DRIVER, joystick_win32); #define JOYSTICK_DRIVER_DIRECTX \ { JOY_TYPE_DIRECTX, &joystick_directx, TRUE }, #define JOYSTICK_DRIVER_WIN32 \ { JOY_TYPE_WIN32, &joystick_win32, TRUE }, allegro-4.4.3.1/include/allegro/platform/aintqnx.h0000664000175000017500000000605613437077643021036 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Internal header for the QNX Allegro library. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #ifndef AINTQNX_H #define AINTQNX_H #include "allegro/platform/aintunix.h" #ifndef SCAN_DEPEND #include #include #include #endif #ifdef __cplusplus extern "C" { #endif /* from qphaccel.c */ AL_FUNC(void, enable_acceleration, (GFX_DRIVER * drv)); AL_FUNC(void, enable_triple_buffering, (GFX_DRIVER *drv)); /* from qphbmp.c */ typedef struct BMP_EXTRA_INFO { PdOffscreenContext_t *context; } BMP_EXTRA_INFO; #define BMP_EXTRA(bmp) ((BMP_EXTRA_INFO *)(bmp->extra)) AL_VAR(BITMAP *, ph_frontbuffer); AL_FUNC(uintptr_t, ph_write_line, (BITMAP *bmp, int lyne)); AL_FUNC(uintptr_t, ph_write_line_asm, (BITMAP *bmp, int lyne)); AL_FUNC(void, ph_unwrite_line, (BITMAP *bmp, int lyne)); AL_FUNC(void, ph_unwrite_line_asm, (BITMAP *bmp, int lyne)); AL_FUNC(void, ph_acquire, (BITMAP *bmp)); AL_FUNC(void, ph_release, (BITMAP *bmp)); AL_FUNC(BITMAP *, make_photon_bitmap, (PdOffscreenContext_t *context, int w, int h, int id)); AL_FUNC(void, destroy_photon_bitmap, (BITMAP *bmp)); AL_FUNC(void, qnx_ph_created_sub_bitmap, (BITMAP *bmp, BITMAP *parent)); AL_FUNC(BITMAP *, qnx_ph_create_video_bitmap, (int width, int height)); AL_FUNC(void, qnx_ph_destroy_video_bitmap, (BITMAP *bmp)); AL_FUNC(int, qnx_ph_show_video_bitmap, (BITMAP *bmp)); AL_FUNC(int, qnx_ph_request_video_bitmap, (BITMAP *bmp)); /* from qphoton.c */ #define PH_GFX_NONE 0 #define PH_GFX_WINDOW 1 #define PH_GFX_DIRECT 2 #define PH_GFX_OVERLAY 3 AL_VAR(int, ph_gfx_mode); AL_VAR(PgVideoModeInfo_t, ph_gfx_mode_info); AL_ARRAY(PgColor_t, ph_palette); AL_FUNC(void, setup_direct_shifts, (void)); AL_FUNC(void, setup_driver, (GFX_DRIVER *drv, int w, int h, int color_depth)); /* from qphwin.c */ AL_VAR(BITMAP *, pseudo_screen); AL_FUNCPTR(void, ph_update_window, (PhRect_t* rect)); /* from qsystem.c */ AL_VAR(PtWidget_t, *ph_window); AL_VAR(pthread_mutex_t, qnx_event_mutex); AL_VAR(pthread_mutex_t, qnx_gfx_mutex); /* from qkeydrv.c */ AL_FUNC(void, qnx_keyboard_handler, (int, int)); AL_FUNC(void, qnx_keyboard_focused, (int, int)); /* from qmouse.c */ AL_VAR(int, qnx_mouse_warped); AL_FUNC(void, qnx_mouse_handler, (int, int, int, int)); /* A very strange thing: PgWaitHWIdle() cannot be found in any system * header file, but it is explained in the QNX docs, and it actually * exists in the Photon library... So until QNX fixes the missing declaration, * we will declare it here. */ int PgWaitHWIdle(void); #ifdef __cplusplus } #endif #endif allegro-4.4.3.1/include/allegro/platform/aintmac.h0000664000175000017500000000552713437077643020772 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some definitions for internal use by the MacOs library code. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #ifndef AINTMAC_H #define AINTMAC_H #ifndef ALLEGRO_H #error must include allegro.h first #endif #ifndef ALLEGRO_MPW #error bad include #endif #include "macalleg.h" #include "allegro/aintern.h" #ifdef __cplusplus extern "C" { #endif /*macsbmp.c*/ extern void _mac_init_system_bitmap(void); extern BITMAP *_mac_create_system_bitmap(int w, int h); extern void _mac_destroy_system_bitmap(BITMAP *bmp); extern void _mac_sys_set_clip(struct BITMAP *dst); extern void _mac_sys_clear_to_color8(BITMAP *bmp, int color); extern void _mac_sys_blit8(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h); extern void _mac_sys_selfblit8(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h); extern int _mac_sys_triangle(struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color); extern void _mac_sys_rectfill8(struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color); extern void _mac_sys_hline8(struct BITMAP *bmp, int x1, int y, int x2, int color); extern void _mac_sys_vline8(struct BITMAP *bmp, int x, int y_1, int y2, int color); extern BITMAP *_CGrafPtr_to_system_bitmap(CGrafPtr cg); /*macdraw.c*/ extern GDHandle MainGDevice; extern CTabHandle MainCTable; extern short dspr_depth; extern volatile short _sync; extern const RGBColor ForeDef; extern const RGBColor BackDef; extern int _dspr_sys_init(); extern void _dspr_sys_exit(); enum{kRDDNull =0, kRDDStarted =1, kRDDReserved =2, kRDDFadeOut =4, kRDDActive =8, kRDDPaused =16, kRDDUnder =32, kRDDOver =64, kRDDouble =128, }; /*macsys.c*/ extern void _mac_get_executable_name(char *output, int size); extern void _mac_message(const char *msg); extern int _tm_sys_init(); extern void _tm_sys_exit(); /*macfile.c*/ extern int _al_open(const char *filename, int mode); extern int _mac_file_sys_init(); /*macallegro.c*/ extern QDGlobals qd; /*The our QuickDraw globals */ extern char *strdup(const char *p); extern void ptoc(StringPtr pstr, char *cstr); extern Boolean RTrapAvailable(short tNumber, TrapType tType); extern void MacEntry(); #ifdef __cplusplus } #endif #endif /* ifndef AINTMAC_H */ allegro-4.4.3.1/include/allegro/platform/macdef.h0000664000175000017500000000042613437077643020566 0ustar siegesiege#define rmac_message 128 /*message window ID*/ #define rerror_str 128 /*errors str*/ #define kprefsize 16384 /* kbytes */ #define kminsize 10000 #define kStackNeeded 2048*1024 /*unsual stack requeriment? but allegro need*/ #define kHeapNeeded 8192*1024 /*it's a game OK*/allegro-4.4.3.1/include/allegro/platform/albeos.h0000664000175000017500000000537313437077643020622 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS specific definitions header file. * * By Jason Wilkins. * * See readme.txt for copyright information. */ /* system driver */ #define SYSTEM_BEOS AL_ID('B','S','Y','S') AL_VAR(SYSTEM_DRIVER, system_beos); /* timer driver */ #define TIMER_BEOS AL_ID('B','T','I','M') AL_VAR(TIMER_DRIVER, timer_beos); /* keyboard driver */ #define KEYBOARD_BEOS AL_ID('B','K','E','Y') AL_VAR(KEYBOARD_DRIVER, keyboard_beos); /* mouse driver */ #define MOUSE_BEOS AL_ID('B','M','O','U') AL_VAR(MOUSE_DRIVER, mouse_beos); /* joystick driver */ #define JOYSTICK_BEOS AL_ID('B','J','O','Y') AL_VAR(JOYSTICK_DRIVER, joystick_beos); /* graphics drivers */ #define GFX_BWINDOWSCREEN_ACCEL AL_ID('B','W','S','A') #define GFX_BWINDOWSCREEN AL_ID('B','W','S',' ') AL_VAR(GFX_DRIVER, gfx_beos_bwindowscreen_accel); AL_VAR(GFX_DRIVER, gfx_beos_bwindowscreen); #define GFX_BDIRECTWINDOW AL_ID('B','D','W','N') #define GFX_BWINDOW AL_ID('B','W','N',' ') AL_VAR(GFX_DRIVER, gfx_beos_bdirectwindow); AL_VAR(GFX_DRIVER, gfx_beos_bwindow); #define GFX_BWINDOW_OVERLAY AL_ID('B','O','V','L') AL_VAR(GFX_DRIVER, gfx_beos_overlay); /* digi drivers */ #define DIGI_BEOS AL_ID('B','D','I','G') AL_VAR(DIGI_DRIVER, digi_beos); /* midi drivers */ #define MIDI_BEOS AL_ID('B','M','I','D') AL_VAR(MIDI_DRIVER, midi_beos); #define GFX_DRIVER_BEOS \ { GFX_BWINDOWSCREEN_ACCEL, &gfx_beos_bwindowscreen_accel, TRUE }, \ { GFX_BWINDOWSCREEN, &gfx_beos_bwindowscreen, TRUE }, \ { GFX_BDIRECTWINDOW, &gfx_beos_bdirectwindow, TRUE }, \ { GFX_BWINDOW, &gfx_beos_bwindow, TRUE }, \ { GFX_BWINDOW_OVERLAY, &gfx_beos_overlay, TRUE }, #define DIGI_DRIVER_BEOS \ { DIGI_BEOS, &digi_beos, TRUE }, #define MIDI_DRIVER_BEOS \ { MIDI_BEOS, &midi_beos, TRUE }, #define JOYSTICK_DRIVER_BEOS \ { JOYSTICK_BEOS, &joystick_beos, TRUE }, #if defined __HAIKU__ #define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') #endif allegro-4.4.3.1/include/allegro/platform/al386gcc.h0000664000175000017500000002333313437077643020663 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Inline functions (gcc style 386 asm). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #if (!defined ALLEGRO_GCC) || (!defined ALLEGRO_I386) #error bad include #endif #ifdef ALLEGRO_IMPORT_GFX_ASM /* _default_ds: * Return a copy of the current %ds selector. */ AL_INLINE(int, _default_ds, (void), { short result; __asm__ ( " movw %%ds, %0 " : "=r" (result) ); return result; }) /* bmp_write_line: * Bank switch function. */ AL_INLINE(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne), { uintptr_t result; __asm__ volatile ( " call *%3 " : "=a" (result) /* result in eax */ : "d" (bmp), /* bitmap in edx */ "0" (lyne), /* line number in eax */ "r" (bmp->write_bank) /* the bank switch routine */ ); return result; }) /* bmp_read_line: * Bank switch function. */ AL_INLINE(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne), { uintptr_t result; __asm__ volatile ( " call *%3 " : "=a" (result) /* result in eax */ : "d" (bmp), /* bitmap in edx */ "0" (lyne), /* line number in eax */ "r" (bmp->read_bank) /* the bank switch routine */ ); return result; }) /* bmp_unwrite_line: * Terminate bank switch function. */ AL_INLINE(void, bmp_unwrite_line, (BITMAP *bmp), { __asm__ volatile ( " call *%1 " : : "d" (bmp), /* bitmap in edx */ "r" (bmp->vtable->unwrite_bank) /* the bank switch routine */ ); }) #endif /* ALLEGRO_IMPORT_GFX_ASM */ #ifdef ALLEGRO_IMPORT_MATH_ASM /* Helper macro that makes the compiler reduce fixadd(), fixsub(), fixmul() and fixdiv() calls to a single constant if both operands are constant. Since this doesn't work unless we compile with optimization, it's better to skip the test then. */ #if (defined __OPTIMIZE__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95))) #define __PRECALCULATE_CONSTANTS(calc) \ if(__builtin_constant_p(x) && __builtin_constant_p(y)) { \ if((calc) > (double)0x7FFFFFFF) { \ *allegro_errno = ERANGE; \ return 0x7FFFFFFF; \ } \ else if(-(calc) > (double)0x7FFFFFFF) { \ *allegro_errno = ERANGE; \ return -0x7FFFFFFF; \ } \ else \ return (fixed)(calc); \ } \ else #else #define __PRECALCULATE_CONSTANTS(calc) #endif /* fixadd: * Fixed point (16.16) addition. */ AL_INLINE(fixed, fixadd, (fixed x, fixed y), { fixed result; __PRECALCULATE_CONSTANTS(x + (double)y) { __asm__ ( " addl %2, %0 ; " /* do the addition */ " jno 0f ; " /* check for overflow */ " movl %4, %0 ; " /* on overflow, set errno */ " movl %3, (%0) ; " " movl $0x7FFFFFFF, %0 ; " /* and return MAXINT */ " cmpl $0, %2 ; " " jg 0f ; " " negl %0 ; " " 0: " /* finished */ : "=r" (result) /* result in a register */ : "0" (x), /* x in the output register */ "rm" (y), /* y can go in register or memory */ "i" (ERANGE), "m" (allegro_errno) : "%cc", "memory" /* clobbers flags and errno */ ); return result; } }) /* fixsub: * Fixed point (16.16) subtraction. */ AL_INLINE(fixed, fixsub, (fixed x, fixed y), { fixed result; __PRECALCULATE_CONSTANTS(x - (double)y) { __asm__ ( " subl %2, %0 ; " /* do the subtraction */ " jno 0f ; " /* check for overflow */ " movl %4, %0 ; " /* on overflow, set errno */ " movl %3, (%0) ; " " movl $0x7FFFFFFF, %0 ; " /* and return MAXINT */ " cmpl $0, %2 ; " " jl 0f ; " " negl %0 ; " " 0: " /* finished */ : "=r" (result) /* result in a register */ : "0" (x), /* x in the output register */ "rm" (y), /* y can go in register or memory */ "i" (ERANGE), "m" (allegro_errno) : "%cc", "memory" /* clobbers flags and errno */ ); return result; } }) /* fixmul: * Fixed point (16.16) multiplication. */ AL_INLINE(fixed, fixmul, (fixed x, fixed y), { fixed edx __attribute__ ((__unused__)); fixed result; __PRECALCULATE_CONSTANTS(x / 65536.0 * y) { __asm__ ( " movl %2, %%eax ; " " imull %3 ; " /* do the multiply */ " shrdl $16, %%edx, %%eax ; " " sarl $15, %%edx ; " /* check for overflow */ " jz 0f ; " " cmpl $-1, %%edx ; " " je 0f ; " " movl %5, %%eax ; " /* on overflow, set errno */ " movl %4, (%%eax) ; " " movl $0x7FFFFFFF, %%eax ; " /* and return MAXINT */ " cmpl $0, %2 ; " " jge 1f ; " " negl %%eax ; " " 1: " " cmpl $0, %3 ; " " jge 0f ; " " negl %%eax ; " " .balign 4, 0x90 ; " " 0: " /* finished */ : "=&a" (result), /* the result has to go in eax */ "=&d" (edx) /* reliably reserve edx */ : "mr" (x), /* x and y can be regs or mem */ "mr" (y), "i" (ERANGE), "m" (allegro_errno) : "%cc", "memory" /* clobbers flags and errno */ ); return result; } }) /* fixdiv: * Fixed point (16.16) division. */ AL_INLINE(fixed, fixdiv, (fixed x, fixed y), { fixed edx __attribute__ ((__unused__)); fixed reg __attribute__ ((__unused__)); fixed result; __PRECALCULATE_CONSTANTS(x * 65536.0 / y) { __asm__ ( " testl %%eax, %%eax ; " /* test sign of x */ " js 3f ; " " testl %2, %2 ; " /* test sign of y */ " jns 4f ; " " negl %2 ; " " 0: " /* result will be negative */ " movl %%eax, %%edx ; " /* check the range is ok */ " shrl $16, %%edx ; " " shll $16, %%eax ; " " cmpl %2, %%edx ; " " jae 1f ; " " divl %2 ; " /* do the divide */ " testl %%eax, %%eax ; " " jns 2f ; " " 1: " " movl %6, %%eax ; " /* on overflow, set errno */ " movl %5, (%%eax) ; " " movl $0x7FFFFFFF, %%eax ; " /* and return MAXINT */ " 2: " " negl %%eax ; " /* fix up the sign of the result */ " jmp 6f ; " " .balign 4, 0x90 ; " " 3: " /* x is negative */ " negl %%eax ; " " testl %2, %2 ; " /* test sign of y */ " jns 0b ; " " negl %2 ; " " 4: " /* result will be positive */ " movl %%eax, %%edx ; " /* check the range is ok */ " shrl $16, %%edx ; " " shll $16, %%eax ; " " cmpl %2, %%edx ; " " jae 5f ; " " divl %2 ; " /* do the divide */ " testl %%eax, %%eax ; " " jns 6f ; " " 5: " " movl %6, %%eax ; " /* on overflow, set errno */ " movl %5, (%%eax) ; " " movl $0x7FFFFFFF, %%eax ; " /* and return MAXINT */ " 6: " /* finished */ : "=a" (result), /* the result has to go in eax */ "=&d" (edx), /* reliably reserve edx */ "=r" (reg) /* input operand will be clobbered */ : "0" (x), /* x in eax */ "2" (y), /* y in register */ "i" (ERANGE), "m" (allegro_errno) : "%cc", "memory" /* clobbers flags and memory */ ); return result; } }) /* fixfloor: * Fixed point version of floor(). * Note that it returns an integer result (not a fixed one) */ AL_INLINE(int, fixfloor, (fixed x), { int result; __asm__ ( " sarl $16, %0 " /* convert to int */ : "=r" (result) /* result in a register */ : "0" (x) /* x in the output register */ ); return result; }) /* fixceil: * Fixed point version of ceil(). * Note that it returns an integer result (not a fixed one) */ AL_INLINE(int, fixceil, (fixed x), { int result; __asm__ ( " addl $0xFFFF, %0 ;" /* ceil () */ " jns 0f ;" " jo 1f ;" "0:" " sarl $16, %0 ;" /* convert to int */ " jmp 2f ;" "1:" " movl %3, %0 ;" /* on overflow, set errno */ " movl %2, (%0) ;" " movl $0x7FFF, %0 ;" /* and return large int */ "2:" : "=r" (result) /* result in a register */ : "0" (x), /* x in the output register */ "i" (ERANGE), "m" (allegro_errno) : "%cc", "memory" /* clobbers flags and errno */ ); return result; }) #undef __PRECALCULATE_CONSTANTS #endif /* ALLEGRO_IMPORT_MATH_ASM */ allegro-4.4.3.1/include/allegro/platform/alpspcfg.h0000664000175000017500000000327113437077643021147 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with PSP. * * By diedel. * * See readme.txt for copyright information. */ #ifndef ALPSPCFG_H #define ALPSPCFG_H #ifndef SCAN_DEPEND #include #include #endif #ifndef ALLEGRO_NO_MAGIC_MAIN #define ALLEGRO_MAGIC_MAIN #define main _mangled_main #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address = (void *) _mangled_main; #else #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address; #endif /* Provide implementations of missing definitions */ #define dup(X) (fcntl(X, F_DUPFD, 0)) /* TODO: Use the configure script. */ /* A static auto config */ //#define ALLEGRO_HAVE_LIBPTHREAD 1 #define ALLEGRO_HAVE_DIRENT_H 1 #define ALLEGRO_HAVE_INTTYPES_H 1 #define ALLEGRO_HAVE_STDINT_H 1 #define ALLEGRO_HAVE_SYS_TIME_H 1 #define ALLEGRO_HAVE_SYS_STAT_H 1 /* Describe this platform */ #define ALLEGRO_PLATFORM_STR "PlayStation Portable" #define ALLEGRO_USE_CONSTRUCTOR #define ALLEGRO_LITTLE_ENDIAN /* Exclude ASM */ #ifndef ALLEGRO_NO_ASM #define ALLEGRO_NO_ASM #endif /* Arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alpsp.h" #endif allegro-4.4.3.1/include/allegro/platform/almac.h0000664000175000017500000000455313437077643020431 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mac-specific header defines. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ /*******************************************/ /************* system drivers **************/ /*******************************************/ #define SYSTEM_MACOS AL_ID('M','C','O','S') AL_VAR(SYSTEM_DRIVER, system_macos); /*******************************************/ /************** timer drivers **************/ /*******************************************/ #define TIMER_MACOS AL_ID('M','C','O','S') AL_VAR(TIMER_DRIVER, timer_macos); /*******************************************/ /************ keyboard drivers *************/ /*******************************************/ #define KEYBOARD_MACOS AL_ID('M','C','O','S') AL_VAR(KEYBOARD_DRIVER, keyboard_macos); #define KEYBOARD_ADB AL_ID('M','A','D','B') AL_VAR(KEYBOARD_DRIVER, keyboard_adb); /*******************************************/ /************* mouse drivers ***************/ /*******************************************/ #define MOUSE_MACOS AL_ID('M','C','O','S') AL_VAR(MOUSE_DRIVER, mouse_macos); #define MOUSE_ADB AL_ID('M','A','D','B') AL_VAR(MOUSE_DRIVER, mouse_adb); /*******************************************/ /*************** gfx drivers ***************/ /*******************************************/ #define GFX_DRAWSPROCKET AL_ID('D','S','P',' ') AL_VAR(GFX_DRIVER,gfx_drawsprocket); /********************************************/ /*************** sound drivers **************/ /********************************************/ #define DIGI_MACOS AL_ID('M','C','O','S') AL_VAR(DIGI_DRIVER, digi_macos); #define MIDI_QUICKTIME AL_ID('Q','T',' ',' ') AL_VAR(MIDI_DRIVER, midi_quicktime); /*******************************************/ /************ joystick drivers *************/ /*******************************************/ /*no yet */ allegro-4.4.3.1/include/allegro/platform/aldos.h0000664000175000017500000003237113437077643020455 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DOS-specific header defines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DOS #error bad include #endif /********************************************/ /************ Platform-specifics ************/ /********************************************/ #define SYSTEM_DOS AL_ID('D','O','S',' ') AL_VAR(SYSTEM_DRIVER, system_dos); AL_VAR(int, i_love_bill); #define KEYDRV_PCDOS AL_ID('P','C','K','B') AL_VAR(KEYBOARD_DRIVER, keydrv_pcdos); #define TIMEDRV_FIXED_RATE AL_ID('F','I','X','T') #define TIMEDRV_VARIABLE_RATE AL_ID('V','A','R','T') AL_VAR(TIMER_DRIVER, timedrv_fixed_rate); AL_VAR(TIMER_DRIVER, timedrv_variable_rate); #define MOUSEDRV_MICKEYS AL_ID('M','I','C','K') #define MOUSEDRV_INT33 AL_ID('I','3','3',' ') #define MOUSEDRV_POLLING AL_ID('P','O','L','L') #define MOUSEDRV_WINNT AL_ID('W','N','T',' ') #define MOUSEDRV_WIN2K AL_ID('W','2','K',' ') AL_VAR(MOUSE_DRIVER, mousedrv_mickeys); AL_VAR(MOUSE_DRIVER, mousedrv_int33); AL_VAR(MOUSE_DRIVER, mousedrv_polling); AL_VAR(MOUSE_DRIVER, mousedrv_winnt); AL_VAR(MOUSE_DRIVER, mousedrv_win2k); /*******************************************/ /************ Joystick routines ************/ /*******************************************/ #define JOY_TYPE_STANDARD AL_ID('S','T','D',' ') #define JOY_TYPE_2PADS AL_ID('2','P','A','D') #define JOY_TYPE_4BUTTON AL_ID('4','B','U','T') #define JOY_TYPE_6BUTTON AL_ID('6','B','U','T') #define JOY_TYPE_8BUTTON AL_ID('8','B','U','T') #define JOY_TYPE_FSPRO AL_ID('F','P','R','O') #define JOY_TYPE_WINGEX AL_ID('W','I','N','G') #define JOY_TYPE_SIDEWINDER AL_ID('S','W',' ',' ') #define JOY_TYPE_SIDEWINDER_AG AL_ID('S','W','A','G') #define JOY_TYPE_SIDEWINDER_PP AL_ID('S','W','P','P') #define JOY_TYPE_GAMEPAD_PRO AL_ID('G','P','R','O') #define JOY_TYPE_GRIP AL_ID('G','R','I','P') #define JOY_TYPE_GRIP4 AL_ID('G','R','I','4') #define JOY_TYPE_SNESPAD_LPT1 AL_ID('S','N','E','1') #define JOY_TYPE_SNESPAD_LPT2 AL_ID('S','N','E','2') #define JOY_TYPE_SNESPAD_LPT3 AL_ID('S','N','E','3') #define JOY_TYPE_PSXPAD_LPT1 AL_ID('P','S','X','1') #define JOY_TYPE_PSXPAD_LPT2 AL_ID('P','S','X','2') #define JOY_TYPE_PSXPAD_LPT3 AL_ID('P','S','X','3') #define JOY_TYPE_N64PAD_LPT1 AL_ID('N','6','4','1') #define JOY_TYPE_N64PAD_LPT2 AL_ID('N','6','4','2') #define JOY_TYPE_N64PAD_LPT3 AL_ID('N','6','4','3') #define JOY_TYPE_DB9_LPT1 AL_ID('D','B','9','1') #define JOY_TYPE_DB9_LPT2 AL_ID('D','B','9','2') #define JOY_TYPE_DB9_LPT3 AL_ID('D','B','9','3') #define JOY_TYPE_TURBOGRAFX_LPT1 AL_ID('T','G','X','1') #define JOY_TYPE_TURBOGRAFX_LPT2 AL_ID('T','G','X','2') #define JOY_TYPE_TURBOGRAFX_LPT3 AL_ID('T','G','X','3') #define JOY_TYPE_IFSEGA_ISA AL_ID('S','E','G','I') #define JOY_TYPE_IFSEGA_PCI AL_ID('S','E','G','P') #define JOY_TYPE_IFSEGA_PCI_FAST AL_ID('S','G','P','F') #define JOY_TYPE_WINGWARRIOR AL_ID('W','W','A','R') AL_VAR(JOYSTICK_DRIVER, joystick_standard); AL_VAR(JOYSTICK_DRIVER, joystick_2pads); AL_VAR(JOYSTICK_DRIVER, joystick_4button); AL_VAR(JOYSTICK_DRIVER, joystick_6button); AL_VAR(JOYSTICK_DRIVER, joystick_8button); AL_VAR(JOYSTICK_DRIVER, joystick_fspro); AL_VAR(JOYSTICK_DRIVER, joystick_wingex); AL_VAR(JOYSTICK_DRIVER, joystick_sw); AL_VAR(JOYSTICK_DRIVER, joystick_sw_ag); AL_VAR(JOYSTICK_DRIVER, joystick_sw_pp); AL_VAR(JOYSTICK_DRIVER, joystick_gpro); AL_VAR(JOYSTICK_DRIVER, joystick_grip); AL_VAR(JOYSTICK_DRIVER, joystick_grip4); AL_VAR(JOYSTICK_DRIVER, joystick_sp1); AL_VAR(JOYSTICK_DRIVER, joystick_sp2); AL_VAR(JOYSTICK_DRIVER, joystick_sp3); AL_VAR(JOYSTICK_DRIVER, joystick_psx1); AL_VAR(JOYSTICK_DRIVER, joystick_psx2); AL_VAR(JOYSTICK_DRIVER, joystick_psx3); AL_VAR(JOYSTICK_DRIVER, joystick_n641); AL_VAR(JOYSTICK_DRIVER, joystick_n642); AL_VAR(JOYSTICK_DRIVER, joystick_n643); AL_VAR(JOYSTICK_DRIVER, joystick_db91); AL_VAR(JOYSTICK_DRIVER, joystick_db92); AL_VAR(JOYSTICK_DRIVER, joystick_db93); AL_VAR(JOYSTICK_DRIVER, joystick_tgx1); AL_VAR(JOYSTICK_DRIVER, joystick_tgx2); AL_VAR(JOYSTICK_DRIVER, joystick_tgx3); AL_VAR(JOYSTICK_DRIVER, joystick_sg1); AL_VAR(JOYSTICK_DRIVER, joystick_sg2); AL_VAR(JOYSTICK_DRIVER, joystick_sg2f); AL_VAR(JOYSTICK_DRIVER, joystick_ww); #define JOYSTICK_DRIVER_STANDARD \ { JOY_TYPE_STANDARD, &joystick_standard, TRUE }, \ { JOY_TYPE_2PADS, &joystick_2pads, FALSE }, \ { JOY_TYPE_4BUTTON, &joystick_4button, FALSE }, \ { JOY_TYPE_6BUTTON, &joystick_6button, FALSE }, \ { JOY_TYPE_8BUTTON, &joystick_8button, FALSE }, \ { JOY_TYPE_FSPRO, &joystick_fspro, FALSE }, \ { JOY_TYPE_WINGEX, &joystick_wingex, FALSE }, #define JOYSTICK_DRIVER_SIDEWINDER \ { JOY_TYPE_SIDEWINDER, &joystick_sw, TRUE }, \ { JOY_TYPE_SIDEWINDER_AG, &joystick_sw_ag, TRUE }, \ { JOY_TYPE_SIDEWINDER_PP, &joystick_sw_pp, TRUE }, #define JOYSTICK_DRIVER_GAMEPAD_PRO \ { JOY_TYPE_GAMEPAD_PRO, &joystick_gpro, TRUE }, #define JOYSTICK_DRIVER_GRIP \ { JOY_TYPE_GRIP, &joystick_grip, TRUE }, \ { JOY_TYPE_GRIP4, &joystick_grip4, TRUE }, #define JOYSTICK_DRIVER_SNESPAD \ { JOY_TYPE_SNESPAD_LPT1, &joystick_sp1, FALSE }, \ { JOY_TYPE_SNESPAD_LPT2, &joystick_sp2, FALSE }, \ { JOY_TYPE_SNESPAD_LPT3, &joystick_sp3, FALSE }, #define JOYSTICK_DRIVER_PSXPAD \ { JOY_TYPE_PSXPAD_LPT1, &joystick_psx1, FALSE }, \ { JOY_TYPE_PSXPAD_LPT2, &joystick_psx2, FALSE }, \ { JOY_TYPE_PSXPAD_LPT3, &joystick_psx3, FALSE }, #define JOYSTICK_DRIVER_N64PAD \ { JOY_TYPE_N64PAD_LPT1, &joystick_n641, FALSE }, \ { JOY_TYPE_N64PAD_LPT2, &joystick_n642, FALSE }, \ { JOY_TYPE_N64PAD_LPT3, &joystick_n643, FALSE }, #define JOYSTICK_DRIVER_DB9 \ { JOY_TYPE_DB9_LPT1, &joystick_db91, FALSE }, \ { JOY_TYPE_DB9_LPT2, &joystick_db92, FALSE }, \ { JOY_TYPE_DB9_LPT3, &joystick_db93, FALSE }, #define JOYSTICK_DRIVER_TURBOGRAFX \ { JOY_TYPE_TURBOGRAFX_LPT1,&joystick_tgx1, FALSE }, \ { JOY_TYPE_TURBOGRAFX_LPT2,&joystick_tgx2, FALSE }, \ { JOY_TYPE_TURBOGRAFX_LPT3,&joystick_tgx3, FALSE }, #define JOYSTICK_DRIVER_IFSEGA_ISA \ { JOY_TYPE_IFSEGA_ISA, &joystick_sg1, FALSE }, #define JOYSTICK_DRIVER_IFSEGA_PCI \ { JOY_TYPE_IFSEGA_PCI, &joystick_sg2, FALSE }, #define JOYSTICK_DRIVER_IFSEGA_PCI_FAST \ { JOY_TYPE_IFSEGA_PCI_FAST,&joystick_sg2f, FALSE }, #define JOYSTICK_DRIVER_WINGWARRIOR \ { JOY_TYPE_WINGWARRIOR, &joystick_ww, TRUE }, #define joy_FSPRO_trigger joy_b1 #define joy_FSPRO_butleft joy_b2 #define joy_FSPRO_butright joy_b3 #define joy_FSPRO_butmiddle joy_b4 #define joy_WINGEX_trigger joy_b1 #define joy_WINGEX_buttop joy_b2 #define joy_WINGEX_butthumb joy_b3 #define joy_WINGEX_butmiddle joy_b4 AL_FUNC(int, calibrate_joystick_tl, (void)); AL_FUNC(int, calibrate_joystick_br, (void)); AL_FUNC(int, calibrate_joystick_throttle_min, (void)); AL_FUNC(int, calibrate_joystick_throttle_max, (void)); AL_FUNC(int, calibrate_joystick_hat, (int direction)); /*******************************************/ /************ Graphics routines ************/ /*******************************************/ #define ALLEGRO_GFX_HAS_VGA #define ALLEGRO_GFX_HAS_VBEAF #define GFX_VGA AL_ID('V','G','A',' ') #define GFX_MODEX AL_ID('M','O','D','X') #define GFX_VESA1 AL_ID('V','B','E','1') #define GFX_VESA2B AL_ID('V','B','2','B') #define GFX_VESA2L AL_ID('V','B','2','L') #define GFX_VESA3 AL_ID('V','B','E','3') #define GFX_VBEAF AL_ID('V','B','A','F') #define GFX_XTENDED AL_ID('X','T','N','D') AL_VAR(GFX_DRIVER, gfx_vga); AL_VAR(GFX_DRIVER, gfx_modex); AL_VAR(GFX_DRIVER, gfx_vesa_1); AL_VAR(GFX_DRIVER, gfx_vesa_2b); AL_VAR(GFX_DRIVER, gfx_vesa_2l); AL_VAR(GFX_DRIVER, gfx_vesa_3); AL_VAR(GFX_DRIVER, gfx_vbeaf); AL_VAR(GFX_DRIVER, gfx_xtended); #define GFX_DRIVER_VGA \ { GFX_VGA, &gfx_vga, TRUE }, #define GFX_DRIVER_MODEX \ { GFX_MODEX, &gfx_modex, TRUE }, #define GFX_DRIVER_VBEAF \ { GFX_VBEAF, &gfx_vbeaf, TRUE }, #define GFX_DRIVER_VESA3 \ { GFX_VESA3, &gfx_vesa_3, TRUE }, #define GFX_DRIVER_VESA2L \ { GFX_VESA2L, &gfx_vesa_2l, TRUE }, #define GFX_DRIVER_VESA2B \ { GFX_VESA2B, &gfx_vesa_2b, TRUE }, #define GFX_DRIVER_XTENDED \ { GFX_XTENDED, &gfx_xtended, FALSE }, #define GFX_DRIVER_VESA1 \ { GFX_VESA1, &gfx_vesa_1, TRUE }, AL_FUNC_DEPRECATED(void, split_modex_screen, (int lyne)); AL_INLINE(void, _set_color, (int index, AL_CONST RGB *p), { outportb(0x3C8, index); outportb(0x3C9, p->r); outportb(0x3C9, p->g); outportb(0x3C9, p->b); _current_palette[index] = *p; }) /****************************************/ /************ Sound routines ************/ /****************************************/ #define DIGI_SB10 AL_ID('S','B','1','0') #define DIGI_SB15 AL_ID('S','B','1','5') #define DIGI_SB20 AL_ID('S','B','2','0') #define DIGI_SBPRO AL_ID('S','B','P',' ') #define DIGI_SB16 AL_ID('S','B','1','6') #define DIGI_AUDIODRIVE AL_ID('E','S','S',' ') #define DIGI_SOUNDSCAPE AL_ID('E','S','C',' ') #define DIGI_WINSOUNDSYS AL_ID('W','S','S',' ') #define MIDI_OPL2 AL_ID('O','P','L','2') #define MIDI_2XOPL2 AL_ID('O','P','L','X') #define MIDI_OPL3 AL_ID('O','P','L','3') #define MIDI_SB_OUT AL_ID('S','B',' ',' ') #define MIDI_MPU AL_ID('M','P','U',' ') #define MIDI_AWE32 AL_ID('A','W','E',' ') AL_VAR(DIGI_DRIVER, digi_sb10); AL_VAR(DIGI_DRIVER, digi_sb15); AL_VAR(DIGI_DRIVER, digi_sb20); AL_VAR(DIGI_DRIVER, digi_sbpro); AL_VAR(DIGI_DRIVER, digi_sb16); AL_VAR(DIGI_DRIVER, digi_audiodrive); AL_VAR(DIGI_DRIVER, digi_soundscape); AL_VAR(DIGI_DRIVER, digi_wss); AL_VAR(MIDI_DRIVER, midi_opl2); AL_VAR(MIDI_DRIVER, midi_2xopl2); AL_VAR(MIDI_DRIVER, midi_opl3); AL_VAR(MIDI_DRIVER, midi_sb_out); AL_VAR(MIDI_DRIVER, midi_mpu401); AL_VAR(MIDI_DRIVER, midi_awe32); #define DIGI_DRIVER_WINSOUNDSYS \ { DIGI_WINSOUNDSYS, &digi_wss, FALSE }, #define DIGI_DRIVER_AUDIODRIVE \ { DIGI_AUDIODRIVE, &digi_audiodrive, TRUE }, #define DIGI_DRIVER_SOUNDSCAPE \ { DIGI_SOUNDSCAPE, &digi_soundscape, TRUE }, #define DIGI_DRIVER_SB \ { DIGI_SB16, &digi_sb16, TRUE }, \ { DIGI_SBPRO, &digi_sbpro, TRUE }, \ { DIGI_SB20, &digi_sb20, TRUE }, \ { DIGI_SB15, &digi_sb15, TRUE }, \ { DIGI_SB10, &digi_sb10, TRUE }, #define MIDI_DRIVER_AWE32 \ { MIDI_AWE32, &midi_awe32, TRUE }, #define MIDI_DRIVER_ADLIB \ { MIDI_OPL3, &midi_opl3, TRUE }, \ { MIDI_2XOPL2, &midi_2xopl2, TRUE }, \ { MIDI_OPL2, &midi_opl2, TRUE }, #define MIDI_DRIVER_SB_OUT \ { MIDI_SB_OUT, &midi_sb_out, FALSE }, #define MIDI_DRIVER_MPU \ { MIDI_MPU, &midi_mpu401, FALSE }, #ifdef __cplusplus extern "C" { #endif AL_FUNC(int, load_ibk, (AL_CONST char *filename, int drums)); #ifdef __cplusplus } #endif allegro-4.4.3.1/include/allegro/platform/alqnx.h0000664000175000017500000000412713437077643020474 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX specific driver definitions. * * By Angelo Mottola. * * See readme.txt for copyright information. */ /* magic to capture name of executable file */ extern int __crt0_argc; extern char **__crt0_argv; #ifndef ALLEGRO_NO_MAGIC_MAIN #define ALLEGRO_MAGIC_MAIN #define main _mangled_main #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address = (void*) _mangled_main; #else #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address; #endif /* System driver */ #define SYSTEM_QNX AL_ID('Q','S','Y','S') AL_VAR(SYSTEM_DRIVER, system_qnx); /* Timer driver */ #define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') AL_VAR(TIMER_DRIVER, timerdrv_unix_pthreads); /* Keyboard driver */ #define KEYBOARD_QNX AL_ID('Q','K','E','Y') AL_VAR(KEYBOARD_DRIVER, keyboard_qnx); /* Mouse driver */ #define MOUSE_QNX AL_ID('Q','M','S','E') AL_VAR(MOUSE_DRIVER, mouse_qnx); /* Graphics drivers */ #define GFX_PHOTON AL_ID('Q','P','A','C') #define GFX_PHOTON_ACCEL AL_ID('Q','P','A','C') #define GFX_PHOTON_SOFT AL_ID('Q','P','S','O') #define GFX_PHOTON_SAFE AL_ID('Q','P','S','A') #define GFX_PHOTON_WIN AL_ID('Q','P','W','N') AL_VAR(GFX_DRIVER, gfx_photon); AL_VAR(GFX_DRIVER, gfx_photon_accel); AL_VAR(GFX_DRIVER, gfx_photon_soft); AL_VAR(GFX_DRIVER, gfx_photon_safe); AL_VAR(GFX_DRIVER, gfx_photon_win); /* Sound driver */ #define DIGI_ALSA AL_ID('A','L','S','A') AL_VAR(DIGI_DRIVER, digi_alsa); /* MIDI driver */ #define MIDI_ALSA AL_ID('A','M','I','D') AL_VAR(MIDI_DRIVER, midi_alsa); allegro-4.4.3.1/include/allegro/platform/al386wat.h0000664000175000017500000001330413437077643020717 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Inline functions (Watcom style 386 asm). * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #if (!defined ALLEGRO_WATCOM) || (!defined ALLEGRO_I386) #error bad include #endif #ifdef ALLEGRO_IMPORT_GFX_ASM /* _default_ds: * Return a copy of the current %ds selector. */ int _default_ds(void); #pragma aux _default_ds = \ " mov eax, 0 " \ " mov ax, ds " \ \ value [eax]; /* _my_cs: * Return a copy of the current %cs selector. */ int _my_cs(void); #pragma aux _my_cs = \ " mov eax, 0 " \ " mov ax, cs " \ \ value [eax]; /* bmp_write_line/bmp_read_line: * Bank switch functions. */ uintptr_t _bmp_bank_switcher(BITMAP *bmp, int lyne, void *bank_switch); #pragma aux _bmp_bank_switcher = \ " call ecx " \ \ parm [edx] [eax] [ecx] \ value [eax]; #define bmp_write_line(bmp, lyne) _bmp_bank_switcher(bmp, lyne, (void *)bmp->write_bank) #define bmp_read_line(bmp, lyne) _bmp_bank_switcher(bmp, lyne, (void *)bmp->read_bank) /* bmp_unwrite_line: * Terminate bank switch function. */ void _bmp_unbank_switcher(BITMAP *bmp, void *bank_unswitcher); #pragma aux _bmp_unbank_switcher = \ " call ecx " \ \ parm [edx] [ecx]; #define bmp_unwrite_line(bmp) _bmp_unbank_switcher(bmp, (void *)bmp->vtable->unwrite_bank) #endif /* ALLEGRO_IMPORT_GFX_ASM */ #ifdef ALLEGRO_IMPORT_MATH_ASM /* _set_errno_erange: * Watcom's asm syntax doesn't provide any nice way to do this inline... */ AL_INLINE(void, _set_errno_erange, (void), { *allegro_errno = ERANGE; }) /* fixadd: * Fixed point (16.16) addition. */ fixed fixadd(fixed x, fixed y); #pragma aux fixadd = \ " add eax, edx " \ " jno Out1 " \ " call _set_errno_erange " \ " mov eax, 0x7FFFFFFF " \ " cmp edx, 0 " \ " jg Out1 " \ " neg eax " \ " Out1: " \ \ parm [eax] [edx] \ value [eax]; /* fixsub: * Fixed point (16.16) subtraction. */ fixed fixsub(fixed x, fixed y); #pragma aux fixsub = \ " sub eax, edx " \ " jno Out1 " \ " call _set_errno_erange " \ " mov eax, 0x7FFFFFFF " \ " cmp edx, 0 " \ " jl Out1 " \ " neg eax " \ " Out1: " \ \ parm [eax] [edx] \ value [eax]; /* fixmul: * Fixed point (16.16) multiplication. */ fixed fixmul(fixed x, fixed y); #pragma aux fixmul = \ " mov eax, ebx " \ " imul ecx " \ " shrd eax, edx, 16 " \ " sar edx, 15 " \ " jz Out2 " \ " cmp edx, -1 " \ " jz Out2 " \ " call _set_errno_erange " \ " mov eax, 0x7FFFFFFF " \ " cmp ebx, 0 " \ " jge Out1 " \ " neg eax " \ " Out1: " \ " cmp ecx, 0 " \ " jge Out2 " \ " neg eax " \ " Out2: " \ \ parm [ebx] [ecx] \ modify [edx] \ value [eax]; /* fixdiv: * Fixed point (16.16) division. */ fixed fixdiv(fixed x, fixed y); #pragma aux fixdiv = \ " xor ebx, ebx " \ " or eax, eax " \ " jns Out1 " \ " neg eax " \ " inc ebx " \ " Out1: " \ " or ecx, ecx " \ " jns Out2 " \ " neg ecx " \ " inc ebx " \ " Out2: " \ " mov edx, eax " \ " shr edx, 0x10 " \ " shl eax, 0x10 " \ " cmp edx, ecx " \ " jae Out3 " \ " div ecx " \ " or eax, eax " \ " jns Out4 " \ " Out3: " \ " call _set_errno_erange " \ " mov eax, 0x7FFFFFFF " \ " Out4: " \ " test ebx, 1 " \ " je Out5 " \ " neg eax " \ " Out5: " \ \ parm [eax] [ecx] \ modify [ebx edx] \ value [eax]; /* fixfloor : * Fixed point version of floor(). * Note that it returns an integer result (not a fixed one) */ int fixfloor(fixed x); #pragma aux fixfloor = \ " sar eax, 0x10 " \ \ parm [eax] \ value [eax]; /* fixceil : * Fixed point version of ceil(). * Note that it returns an integer result (not a fixed one) */ int fixceil(fixed x); #pragma aux fixceil = \ " add eax, 0xFFFF " \ " jns Out1 " \ " jo Out2 " \ " Out1: " \ " sar eax, 0x10 " \ " jmp Out3 " \ " Out2: " \ " call _set_errno_erange " \ " mov eax, 0x7FFF " \ " Out3: " \ \ parm [eax] \ value [eax]; #endif /* ALLEGRO_IMPORT_MATH_ASM */ allegro-4.4.3.1/include/allegro/platform/aintpsp.h0000664000175000017500000000402413437077643021023 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Internal header file for the PSP Allegro library port. * * By diedel. * * See readme.txt for copyright information. */ #ifndef AINTPSP_H #define AINTPSP_H /* For accelerated blitting support .*/ AL_FUNC(BITMAP *, psp_create_bitmap, (int color_depth, int width, int height)); AL_FUNC(int, psp_destroy_bitmap, (BITMAP *bitmap)); /* Extra bitmap info. */ #define BMP_EXTRA(bmp) ((BMP_EXTRA_INFO *)((bmp)->extra)) typedef struct BMP_EXTRA_INFO { int pitch; /* For video bitmaps. */ int size; uintptr_t hw_addr; } BMP_EXTRA_INFO; #define ALIGN_TO(v,n) ((v + n-1) & ~(n-1)) /* For 8 bpp support. */ AL_VAR(GFX_VTABLE, psp_vtable8); AL_FUNC(void, psp_do_stretch_blit8, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)); /* The video bitmap actually displayed on the PSP. */ BITMAP *displayed_video_bitmap; AL_FUNC(void, psp_draw_to_screen, (void)); /* Video memory manager stuff. */ #define VMM_NO_MEM ((uintptr_t)0) typedef struct VRAM_HOLE { uintptr_t h_base; unsigned int h_len; struct VRAM_HOLE *h_next; } VRAM_HOLE; AL_FUNC(void, vmm_init, (uintptr_t base, unsigned int available_vram)); AL_FUNC(uintptr_t, vmm_alloc_mem, (unsigned int size)); AL_FUNC(void, vmm_free_mem, (uintptr_t base, unsigned int size)); /* PSP controller stuff. */ #define SAMPLING_CYCLE 0 #define SAMPLING_MODE PSP_CTRL_MODE_DIGITAL AL_FUNC(void, _psp_init_controller, (int cycle, int mode)); #endif allegro-4.4.3.1/include/allegro/platform/almsvc.h0000664000175000017500000000541613437077643020640 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with MSVC. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #include #include #endif #pragma warning (disable: 4200 4244 4305) /* describe this platform */ #ifdef ALLEGRO_STATICLINK #define ALLEGRO_PLATFORM_STR "MSVC.s" #else #define ALLEGRO_PLATFORM_STR "MSVC" #endif #define ALLEGRO_WINDOWS #define ALLEGRO_I386 #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_GUESS_INTTYPES_OK #define ALLEGRO_MULTITHREADED #ifdef ALLEGRO_USE_CONSOLE #define ALLEGRO_CONSOLE_OK #define ALLEGRO_NO_MAGIC_MAIN #endif #ifdef ALLEGRO_AND_MFC #define ALLEGRO_NO_MAGIC_MAIN #endif /* describe how function prototypes look to MSVC */ #if defined ALLEGRO_STATICLINK #define _AL_DLL #elif defined ALLEGRO_SRC #define _AL_DLL __declspec(dllexport) #else #define _AL_DLL __declspec(dllimport) #endif #define AL_VAR(type, name) extern _AL_DLL type name #define AL_ARRAY(type, name) extern _AL_DLL type name[] #define AL_FUNC(type, name, args) _AL_DLL type __cdecl name args #define AL_METHOD(type, name, args) type (__cdecl *name) args #define AL_FUNCPTR(type, name, args) extern _AL_DLL type (__cdecl *name) args #ifdef AL_INLINE #define END_OF_INLINE(name) void *_force_instantiate_##name = name; #else #define END_OF_INLINE(name) #endif #undef AL_INLINE #define AL_INLINE(type, name, args, code) __inline _AL_DLL type __cdecl name args code END_OF_INLINE(name) #define INLINE __inline #define LONG_LONG __int64 #if (_MSC_VER >= 1600) #define ALLEGRO_HAVE_STDINT_H #else #define int64_t signed __int64 #define uint64_t unsigned __int64 #endif #define AL_CONST const /* describe the asm syntax for this platform */ #define ALLEGRO_ASM_PREFIX "_" /* life would be so easy if compilers would all use the same names! */ #if (!defined S_IRUSR) && (!defined SCAN_DEPEND) #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #endif /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" #define ALLEGRO_ASMCAPA_HEADER "obj/msvc/asmcapa.h" allegro-4.4.3.1/include/allegro/platform/al386vc.h0000664000175000017500000001025213437077643020533 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Inline functions (MSVC style 386 asm). * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #if (!defined ALLEGRO_MSVC) || (!defined ALLEGRO_I386) #error bad include #endif #pragma warning (disable: 4035) #ifdef ALLEGRO_IMPORT_GFX_ASM /* _default_ds: * Return a copy of the current %ds selector. */ INLINE _AL_DLL int _default_ds(void) { _asm { mov eax, 0 mov ax, ds } } END_OF_INLINE(_default_ds); /* bmp_write_line: * Bank switch function. */ INLINE _AL_DLL uintptr_t bmp_write_line(BITMAP *bmp, int lyne) { _asm { mov edx, bmp mov ecx, [edx]BITMAP.write_bank mov eax, lyne call ecx } } END_OF_INLINE(bmp_write_line); /* bmp_read_line: * Bank switch function. */ INLINE _AL_DLL uintptr_t bmp_read_line(BITMAP *bmp, int lyne) { _asm { mov edx, bmp mov ecx, [edx]BITMAP.read_bank mov eax, lyne call ecx } } END_OF_INLINE(bmp_read_line); /* bmp_unwrite_line: * Terminate bank switch function. */ INLINE _AL_DLL void bmp_unwrite_line(BITMAP *bmp) { _asm { mov edx, bmp mov ecx, [edx]BITMAP.vtable mov ecx, [ecx]GFX_VTABLE.unwrite_bank call ecx } } END_OF_INLINE(bmp_unwrite_line); #endif /* ALLEGRO_IMPORT_GFX_ASM */ #ifdef ALLEGRO_IMPORT_MATH_ASM /* _set_errno_erange: */ INLINE void _set_errno_erange(void) { *allegro_errno = ERANGE; } END_OF_INLINE(_set_errno_erange); /* fixadd: * Fixed point (16.16) addition. */ INLINE _AL_DLL fixed fixadd(fixed x, fixed y) { _asm { mov eax, x add eax, y jno Out1 call _set_errno_erange mov eax, 0x7FFFFFFF cmp y, 0 jg Out1 neg eax Out1: } } END_OF_INLINE(fixadd); /* fixsub: * Fixed point (16.16) subtraction. */ INLINE _AL_DLL fixed fixsub(fixed x, fixed y) { _asm { mov eax, x sub eax, y jno Out1 call _set_errno_erange mov eax, 0x7FFFFFFF cmp y, 0 jl Out1 neg eax Out1: } } END_OF_INLINE(fixsub); /* fixmul: * Fixed point (16.16) multiplication. */ INLINE _AL_DLL fixed fixmul(fixed x, fixed y) { _asm { mov eax, x imul y shrd eax, edx, 16 sar edx, 15 jz Out2 cmp edx, -1 jz Out2 call _set_errno_erange mov eax, 0x7FFFFFFF cmp x, 0 jge Out1 neg eax Out1: cmp y, 0 jge Out2 neg eax Out2: } } END_OF_INLINE(fixmul); /* fixdiv: * Fixed point (16.16) division. */ INLINE _AL_DLL fixed fixdiv(fixed x, fixed y) { _asm { mov ecx, y xor ebx, ebx mov eax, x or eax, eax jns Out1 neg eax inc ebx Out1: or ecx, ecx jns Out2 neg ecx inc ebx Out2: mov edx, eax shr edx, 0x10 shl eax, 0x10 cmp edx, ecx jae Out3 div ecx or eax, eax jns Out4 Out3: call _set_errno_erange mov eax, 0x7FFFFFFF Out4: test ebx, 1 je Out5 neg eax Out5: } } END_OF_INLINE(fixdiv); /* fixfloor : * Fixed point version of floor(). * Note that it returns an integer result (not a fixed one) */ INLINE _AL_DLL int fixfloor(fixed x) { _asm { mov eax, x sar eax, 0x10 } } END_OF_INLINE(fixfloor); /* fixceil: * Fixed point version of ceil(). * Note that it returns an integer result (not a fixed one) */ INLINE _AL_DLL int fixceil(fixed x) { _asm { mov eax, x add eax, 0xFFFF jns Out1 jo Out2 Out1: sar eax, 0x10 jmp Out3 Out2: call _set_errno_erange mov eax, 0x7FFF Out3: } } END_OF_INLINE(fixceil); #endif /* ALLEGRO_IMPORT_MATH_ASM */ #pragma warning (default: 4035) allegro-4.4.3.1/include/allegro/platform/alunix.h0000664000175000017500000001677313437077643020663 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Unix-specific header defines. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_UNIX #error bad include #endif /* magic to capture name of executable file */ extern int __crt0_argc; extern char **__crt0_argv; #ifdef ALLEGRO_WITH_MAGIC_MAIN #ifndef ALLEGRO_NO_MAGIC_MAIN #define ALLEGRO_MAGIC_MAIN #define main _mangled_main #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address = (void*) _mangled_main; #else #undef END_OF_MAIN #define END_OF_MAIN() void *_mangled_main_address; #endif #endif /**************************************/ /************ General Unix ************/ /**************************************/ #define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') #define TIMERDRV_UNIX_SIGALRM AL_ID('A','L','R','M') #ifdef ALLEGRO_HAVE_LIBPTHREAD AL_VAR(TIMER_DRIVER, timerdrv_unix_pthreads); #else AL_VAR(TIMER_DRIVER, timerdrv_unix_sigalrm); #endif /************************************/ /*********** Sound drivers **********/ /************************************/ #define DIGI_OSS AL_ID('O','S','S','D') #define MIDI_OSS AL_ID('O','S','S','M') #define DIGI_ESD AL_ID('E','S','D','D') #define DIGI_ARTS AL_ID('A','R','T','S') #define DIGI_SGIAL AL_ID('S','G','I','A') #define DIGI_ALSA AL_ID('A','L','S','A') #define MIDI_ALSA AL_ID('A','M','I','D') #define DIGI_JACK AL_ID('J','A','C','K') #ifdef ALLEGRO_WITH_OSSDIGI AL_VAR(DIGI_DRIVER, digi_oss); #define DIGI_DRIVER_OSS \ { DIGI_OSS, &digi_oss, TRUE }, #endif /* ALLEGRO_WITH_OSSDIGI */ #ifdef ALLEGRO_WITH_OSSMIDI AL_VAR(MIDI_DRIVER, midi_oss); #define MIDI_DRIVER_OSS \ { MIDI_OSS, &midi_oss, TRUE }, #endif /* ALLEGRO_WITH_OSSMIDI */ #ifndef ALLEGRO_WITH_MODULES #ifdef ALLEGRO_WITH_ESDDIGI AL_VAR(DIGI_DRIVER, digi_esd); #define DIGI_DRIVER_ESD \ { DIGI_ESD, &digi_esd, TRUE }, #endif /* ALLEGRO_WITH_ESDDIGI */ #ifdef ALLEGRO_WITH_ARTSDIGI AL_VAR(DIGI_DRIVER, digi_arts); #define DIGI_DRIVER_ARTS \ { DIGI_ARTS, &digi_arts, TRUE }, #endif /* ALLEGRO_WITH_ARTSDIGI */ #ifdef ALLEGRO_WITH_SGIALDIGI AL_VAR(DIGI_DRIVER, digi_sgial); #define DIGI_DRIVER_SGIAL \ { DIGI_SGIAL, &digi_sgial, TRUE }, #endif /* ALLEGRO_WITH_SGIALDIGI */ #ifdef ALLEGRO_WITH_ALSADIGI AL_VAR(DIGI_DRIVER, digi_alsa); #define DIGI_DRIVER_ALSA \ { DIGI_ALSA, &digi_alsa, TRUE }, #endif /* ALLEGRO_WITH_ALSADIGI */ #ifdef ALLEGRO_WITH_ALSAMIDI AL_VAR(MIDI_DRIVER, midi_alsa); #define MIDI_DRIVER_ALSA \ { MIDI_ALSA, &midi_alsa, TRUE }, #endif /* ALLEGRO_WITH_ALSAMIDI */ #ifdef ALLEGRO_WITH_JACKDIGI AL_VAR(DIGI_DRIVER, digi_jack); #define DIGI_DRIVER_JACK \ { DIGI_JACK, &digi_jack, TRUE }, #endif /* ALLEGRO_WITH_JACKDIGI */ #endif /************************************/ /************ X-specific ************/ /************************************/ #define SYSTEM_XWINDOWS AL_ID('X','W','I','N') #define KEYBOARD_XWINDOWS AL_ID('X','W','I','N') #define MOUSE_XWINDOWS AL_ID('X','W','I','N') #define GFX_XWINDOWS AL_ID('X','W','I','N') #define GFX_XWINDOWS_FULLSCREEN AL_ID('X','W','F','S') #define GFX_XDGA AL_ID('X','D','G','A') #define GFX_XDGA_FULLSCREEN AL_ID('X','D','F','S') #define GFX_XDGA2 AL_ID('D','G','A','2') #define GFX_XDGA2_SOFT AL_ID('D','G','A','S') #ifdef ALLEGRO_WITH_XWINDOWS AL_VAR(SYSTEM_DRIVER, system_xwin); #ifdef ALLEGRO_XWINDOWS_WITH_XF86DGA2 #ifndef ALLEGRO_WITH_MODULES AL_VAR(GFX_DRIVER, gfx_xdga2); AL_VAR(GFX_DRIVER, gfx_xdga2_soft); #endif #endif #endif /* ALLEGRO_WITH_XWINDOWS */ /****************************************/ /************ Linux-specific ************/ /****************************************/ #define SYSTEM_LINUX AL_ID('L','N','X','C') #define GFX_VGA AL_ID('V','G','A',' ') #define GFX_MODEX AL_ID('M','O','D','X') #define GFX_FBCON AL_ID('F','B',' ',' ') #define GFX_VBEAF AL_ID('V','B','A','F') #define GFX_SVGALIB AL_ID('S','V','G','A') #define KEYDRV_LINUX AL_ID('L','N','X','C') #define MOUSEDRV_LINUX_PS2 AL_ID('L','P','S','2') #define MOUSEDRV_LINUX_IPS2 AL_ID('L','I','P','S') #define MOUSEDRV_LINUX_GPMDATA AL_ID('G','P','M','D') #define MOUSEDRV_LINUX_MS AL_ID('M','S',' ',' ') #define MOUSEDRV_LINUX_IMS AL_ID('I','M','S',' ') #define MOUSEDRV_LINUX_EVDEV AL_ID('E','V',' ',' ') #define MOUSEDRV_LINUX_TSLIB AL_ID('T','S','L','I') #define JOY_TYPE_LINUX_ANALOGUE AL_ID('L','N','X','A') #ifdef ALLEGRO_LINUX AL_VAR(SYSTEM_DRIVER, system_linux); #ifdef ALLEGRO_LINUX_VGA AL_VAR(GFX_DRIVER, gfx_vga); AL_VAR(GFX_DRIVER, gfx_modex); #define ALLEGRO_GFX_HAS_VGA #endif #ifndef ALLEGRO_WITH_MODULES #ifdef ALLEGRO_LINUX_FBCON AL_VAR(GFX_DRIVER, gfx_fbcon); #endif #ifdef ALLEGRO_LINUX_SVGALIB AL_VAR(GFX_DRIVER, gfx_svgalib); #endif #endif #ifdef ALLEGRO_LINUX_VBEAF AL_VAR(GFX_DRIVER, gfx_vbeaf); #define ALLEGRO_GFX_HAS_VBEAF #endif AL_VAR(MOUSE_DRIVER, mousedrv_linux_ps2); AL_VAR(MOUSE_DRIVER, mousedrv_linux_ips2); AL_VAR(MOUSE_DRIVER, mousedrv_linux_gpmdata); AL_VAR(MOUSE_DRIVER, mousedrv_linux_ms); AL_VAR(MOUSE_DRIVER, mousedrv_linux_ims); AL_VAR(MOUSE_DRIVER, mousedrv_linux_evdev); AL_VAR(MOUSE_DRIVER, mousedrv_linux_tslib); AL_FUNC_DEPRECATED(void, split_modex_screen, (int lyne)); /* Port I/O functions -- maybe these should be internal */ #ifdef ALLEGRO_LINUX_VGA #ifdef __cplusplus extern "C" { #endif static INLINE void outportb(unsigned short port, unsigned char value) { __asm__ volatile ("outb %0, %1" : : "a" (value), "d" (port)); } static INLINE void outportw(unsigned short port, unsigned short value) { __asm__ volatile ("outw %0, %1" : : "a" (value), "d" (port)); } static INLINE void outportl(unsigned short port, unsigned long value) { __asm__ volatile ("outl %0, %1" : : "a" (value), "d" (port)); } static INLINE unsigned char inportb(unsigned short port) { unsigned char value; __asm__ volatile ("inb %1, %0" : "=a" (value) : "d" (port)); return value; } static INLINE unsigned short inportw(unsigned short port) { unsigned short value; __asm__ volatile ("inw %1, %0" : "=a" (value) : "d" (port)); return value; } static INLINE unsigned long inportl(unsigned short port) { unsigned long value; __asm__ volatile ("inl %1, %0" : "=a" (value) : "d" (port)); return value; } #ifdef __cplusplus } #endif #endif /* ALLEGRO_LINUX_VGA */ #endif /* ALLEGRO_LINUX */ allegro-4.4.3.1/include/allegro/platform/albcc32.h0000664000175000017500000000512013437077643020554 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with Borland C++Builder. * * By Greg Hackmann. * * See readme.txt for copyright information. */ #ifdef ALLEGRO_SRC #error Currently BCC32 cannot build the library #endif #ifndef SCAN_DEPEND #include #include #include #include #endif #pragma warn -8004 /* unused assigned value */ #pragma warn -8008 /* condition always met */ #pragma warn -8057 /* unused parameter */ #pragma warn -8066 /* unreachable code */ /* describe this platform */ #define ALLEGRO_PLATFORM_STR "BCC32" #define ALLEGRO_WINDOWS #define ALLEGRO_I386 #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_GUESS_INTTYPES_OK /* TODO: check if BCC has inttypes.h and/or stdint.h */ #define ALLEGRO_MULTITHREADED #ifdef ALLEGRO_USE_CONSOLE #define ALLEGRO_CONSOLE_OK #define ALLEGRO_NO_MAGIC_MAIN #endif /* describe how function prototypes look to BCC32 */ #if defined ALLEGRO_STATICLINK #define _AL_DLL #elif defined ALLEGRO_SRC #define _AL_DLL __declspec(dllexport) #else #define _AL_DLL __declspec(dllimport) #endif #define AL_VAR(type, name) extern _AL_DLL type name #define AL_ARRAY(type, name) extern _AL_DLL type name[] #define AL_FUNC(type, name, args) _AL_DLL type __cdecl name args #define AL_METHOD(type, name, args) type (__cdecl *name) args #define AL_FUNCPTR(type, name, args) extern _AL_DLL type (__cdecl *name) args #define END_OF_INLINE(name) #define AL_INLINE(type, name, args, code) extern __inline type __cdecl name args code END_OF_INLINE(name) #define INLINE __inline #define LONG_LONG __int64 #define int64_t signed __int64 #define uint64_t unsigned __int64 #define AL_CONST const /* windows specific defines */ #ifdef NONAMELESSUNION #undef NONAMELESSUNION #endif /* This fixes 99.999999% of Borland C++Builder's problems with structs. */ /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" allegro-4.4.3.1/include/allegro/platform/alucfg.h0000664000175000017500000000305713437077643020613 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use on Unix platforms. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include #include /* Describe this platform. */ #define ALLEGRO_PLATFORM_STR "Unix" #define ALLEGRO_CONSOLE_OK #define ALLEGRO_VRAM_SINGLE_SURFACE #define ALLEGRO_EXTRA_HEADER "allegro/platform/alunix.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintunix.h" /* These defines will be provided by configure script. */ #undef ALLEGRO_COLOR8 #undef ALLEGRO_COLOR16 #undef ALLEGRO_COLOR24 #undef ALLEGRO_COLOR32 /* Include configuration generated by configure script. */ #include "allegro/platform/alunixac.h" /* Enable multithreaded library */ #ifdef ALLEGRO_HAVE_LIBPTHREAD #define ALLEGRO_MULTITHREADED #endif /* Provide implementations of missing functions. */ #ifndef ALLEGRO_HAVE_STRICMP #define ALLEGRO_NO_STRICMP #endif #ifndef ALLEGRO_HAVE_STRLWR #define ALLEGRO_NO_STRLWR #endif #ifndef ALLEGRO_HAVE_STRUPR #define ALLEGRO_NO_STRUPR #endif #ifndef ALLEGRO_HAVE_MEMCMP #define ALLEGRO_NO_MEMCMP #endif allegro-4.4.3.1/include/allegro/platform/aintunix.h0000664000175000017500000001354713437077643021216 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some definitions for internal use by the Unix library code. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef AINTUNIX_H #define AINTUNIX_H #ifdef __cplusplus extern "C" { #endif #ifdef ALLEGRO_HAVE_LIBPTHREAD /* Synchronization routines using POSIX threads */ AL_FUNC(void *, _unix_create_mutex, (void)); AL_FUNC(void, _unix_destroy_mutex, (void *handle)); AL_FUNC(void, _unix_lock_mutex, (void *handle)); AL_FUNC(void, _unix_unlock_mutex, (void *handle)); #else /* Asynchronous event processing with SIGALRM */ AL_FUNC(void, _sigalrm_request_abort, (void)); AL_FUNCPTR(void, _sigalrm_timer_interrupt_handler, (unsigned long interval)); #endif /* Macros to enable and disable interrupts */ #define DISABLE() _unix_bg_man->disable_interrupts() #define ENABLE() _unix_bg_man->enable_interrupts() /* Helper for locating config files */ AL_FUNC(int, _unix_find_resource, (char *dest, AL_CONST char *resource, int size)); /* Generic system driver entry for finding the executable */ AL_FUNC(void, _unix_get_executable_name, (char *output, int size)); /* Helper for setting os_type */ AL_FUNC(void, _unix_read_os_type, (void)); /* Helper for yield CPU */ AL_FUNC(void, _unix_yield_timeslice, (void)); /* Unix rest function */ AL_FUNC(void, _unix_rest, (unsigned int, AL_METHOD(void, callback, (void)))); /* Module support */ AL_FUNC(void, _unix_load_modules, (int system_driver_id)); AL_FUNC(void, _unix_unload_modules, (void)); /* Dynamic driver lists, for modules */ AL_VAR(_DRIVER_INFO *, _unix_gfx_driver_list); AL_VAR(_DRIVER_INFO *, _unix_digi_driver_list); AL_VAR(_DRIVER_INFO *, _unix_midi_driver_list); AL_FUNC(void, _unix_driver_lists_init, (void)); AL_FUNC(void, _unix_driver_lists_shutdown, (void)); AL_FUNC(void, _unix_register_gfx_driver, (int id, GFX_DRIVER *driver, int autodetect, int priority)); AL_FUNC(void, _unix_register_digi_driver, (int id, DIGI_DRIVER *driver, int autodetect, int priority)); AL_FUNC(void, _unix_register_midi_driver, (int id, MIDI_DRIVER *driver, int autodetect, int priority)); /* Get size of a memory page in bytes */ AL_FUNC(size_t, _unix_get_page_size, (void)); #ifdef ALLEGRO_WITH_XWINDOWS AL_FUNCPTR(void, _xwin_keyboard_interrupt, (int pressed, int code)); AL_FUNCPTR(void, _xwin_keyboard_focused, (int focused, int state)); AL_FUNCPTR(void, _xwin_mouse_interrupt, (int x, int y, int z, int w, int buttons)); AL_FUNCPTR(void, _xwin_timer_interrupt, (unsigned long interval)); AL_ARRAY(_DRIVER_INFO, _xwin_gfx_driver_list); AL_ARRAY(_DRIVER_INFO, _xwin_keyboard_driver_list); AL_ARRAY(_DRIVER_INFO, _xwin_mouse_driver_list); AL_ARRAY(_DRIVER_INFO, _xwin_timer_driver_list); AL_FUNC(void, _xwin_handle_input, (void)); AL_FUNC(void, _xwin_private_handle_input, (void)); #ifndef ALLEGRO_MULTITHREADED AL_VAR(int, _xwin_missed_input); #define XLOCK() \ do { \ _xwin.lock_count++; \ } while (0) #define XUNLOCK() \ do { \ if (_xwin.lock_count == 1) { \ while(_xwin_missed_input) { \ if (_xwin_input_handler) \ _xwin_input_handler(); \ else \ _xwin_private_handle_input(); \ --_xwin_missed_input; \ } \ } \ _xwin.lock_count--; \ } while (0) #else #define XLOCK() \ do { \ if (_xwin.mutex) \ _unix_lock_mutex (_xwin.mutex); \ _xwin.lock_count++; \ } while (0) #define XUNLOCK() \ do { \ if (_xwin.mutex) \ _unix_unlock_mutex (_xwin.mutex); \ _xwin.lock_count--; \ } while (0) #endif #endif #ifdef ALLEGRO_WITH_OSSDIGI /* So the setup program can read what we detected */ AL_VAR(int, _oss_fragsize); AL_VAR(int, _oss_numfrags); #endif #ifdef __cplusplus } #endif #ifdef ALLEGRO_LINUX #include "aintlnx.h" #endif #ifdef __cplusplus extern "C" { #endif /* Typedef for background functions, called frequently in the background. * `threaded' is nonzero if the function is being called from a thread. */ typedef void (*bg_func) (int threaded); /* Background function manager -- responsible for calling background * functions. `int' methods return -1 on failure, 0 on success. */ struct bg_manager { int multi_threaded; int (*init) (void); void (*exit) (void); int (*register_func) (bg_func f); int (*unregister_func) (bg_func f); void (*enable_interrupts) (void); void (*disable_interrupts) (void); int (*interrupts_disabled) (void); }; extern struct bg_manager _bg_man_pthreads; extern struct bg_manager _bg_man_sigalrm; extern struct bg_manager *_unix_bg_man; extern _DRIVER_INFO _linux_joystick_driver_list[]; /* also in aintlnx.h */ #ifdef __cplusplus } #endif #endif /* ifndef AINTUNIX_H */ allegro-4.4.3.1/include/allegro/platform/aintbeos.h0000664000175000017500000001255713437077643021163 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Definitions for internal use by the BeOS configuration. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "bealleg.h" #ifdef __cplusplus extern status_t ignore_result; extern volatile int32 focus_count; #endif #ifdef __cplusplus extern "C" { #endif #define WND_TITLE_SIZE 128 AL_ARRAY(char, wnd_title); int be_key_init(void); void be_key_exit(void); void be_key_set_leds(int leds); void be_key_set_rate(int delay, int repeat); void be_key_wait_for_input(void); void be_key_stop_waiting_for_input(void); void be_key_suspend(void); void be_key_resume(void); int be_sys_init(void); void be_sys_exit(void); void _be_sys_get_executable_name(char *output, int size); void be_sys_get_executable_name(char *output, int size); int be_sys_find_resource(char *dest, AL_CONST char *resource, int size); void be_sys_set_window_title(AL_CONST char *name); int be_sys_set_close_button_callback(void (*proc)(void)); void be_sys_message(AL_CONST char *msg); int be_sys_set_display_switch_mode(int mode); int be_sys_desktop_color_depth(void); int be_sys_get_desktop_resolution(int *width, int *height); void be_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); void be_sys_yield_timeslice(void); void *be_sys_create_mutex(void); void be_sys_destroy_mutex(void *handle); void be_sys_lock_mutex(void *handle); void be_sys_unlock_mutex(void *handle); void be_sys_suspend(void); void be_sys_resume(void); void be_main_suspend(void); void be_main_resume(void); struct BITMAP *be_gfx_bwindowscreen_accel_init(int w, int h, int v_w, int v_h, int color_depth); struct BITMAP *be_gfx_bwindowscreen_init(int w, int h, int v_w, int v_h, int color_depth); void be_gfx_bwindowscreen_exit(struct BITMAP *b); void be_gfx_bwindowscreen_acquire(struct BITMAP *b); void be_gfx_bwindowscreen_release(struct BITMAP *b); void be_gfx_bwindowscreen_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); int be_gfx_bwindowscreen_scroll(int x, int y); int be_gfx_bwindowscreen_request_scroll(int x, int y); int be_gfx_bwindowscreen_poll_scroll(void); int be_gfx_bwindowscreen_request_video_bitmap(struct BITMAP *bitmap); void be_gfx_vsync(void); struct GFX_MODE_LIST *be_gfx_bwindowscreen_fetch_mode_list(void); void be_gfx_bwindowscreen_accelerate(int color_depth); #ifdef ALLEGRO_NO_ASM uintptr_t be_gfx_bwindowscreen_read_write_bank(BITMAP *bmp, int lyne); void be_gfx_bwindowscreen_unwrite_bank(BITMAP *bmp); #else uintptr_t _be_gfx_bwindowscreen_read_write_bank_asm(BITMAP *bmp, int lyne); void _be_gfx_bwindowscreen_unwrite_bank_asm(BITMAP *bmp); #endif struct BITMAP *be_gfx_bdirectwindow_init(int w, int h, int v_w, int v_h, int color_depth); void be_gfx_bdirectwindow_exit(struct BITMAP *b); void be_gfx_bdirectwindow_acquire(struct BITMAP *bmp); void be_gfx_bdirectwindow_release(struct BITMAP *bmp); void be_gfx_bdirectwindow_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); struct BITMAP *be_gfx_bwindow_init(int w, int h, int v_w, int v_h, int color_depth); void be_gfx_bwindow_exit(struct BITMAP *b); void be_gfx_bwindow_acquire(struct BITMAP *bmp); void be_gfx_bwindow_release(struct BITMAP *bmp); void be_gfx_bwindow_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); #ifdef ALLEGRO_NO_ASM void _be_gfx_bwindow_unwrite_bank(BITMAP *bmp); uintptr_t _be_gfx_bwindow_read_write_bank(BITMAP *bmp, int lyne); #else void _be_gfx_bwindow_unwrite_bank_asm(BITMAP *bmp); uintptr_t _be_gfx_bwindow_read_write_bank_asm(BITMAP *bmp, int lyne); #endif struct BITMAP *be_gfx_overlay_init(int w, int h, int v_w, int v_h, int color_depth); void be_gfx_overlay_exit(struct BITMAP *b); int be_time_init(void); void be_time_exit(void); void be_time_rest(unsigned int tyme, AL_METHOD(void, callback, (void))); void be_time_suspend(void); void be_time_resume(void); int be_mouse_init(void); void be_mouse_exit(void); void be_mouse_position(int x, int y); void be_mouse_set_range(int x1, int y_1, int x2, int y2); void be_mouse_set_speed(int xspeed, int yspeed); void be_mouse_get_mickeys(int *mickeyx, int *mickeyy); int be_joy_init(void); void be_joy_exit(void); int be_joy_poll(void); int be_sound_detect(int input); int be_sound_init(int input, int voices); void be_sound_exit(int input); void *be_sound_lock_voice(int voice, int start, int end); void be_sound_unlock_voice(int voice); int be_sound_buffer_size(void); int be_sound_set_mixer_volume(int volume); int be_sound_get_mixer_volume(void); void be_sound_suspend(void); void be_sound_resume(void); int be_midi_detect(int input); int be_midi_init(int input, int voices); void be_midi_exit(int input); int be_midi_set_mixer_volume(int volume); int be_midi_get_mixer_volume(void); void be_midi_key_on(int inst, int note, int bend, int vol, int pan); void be_midi_key_off(int voice); void be_midi_set_volume(int voice, int vol); void be_midi_set_pitch(int voice, int note, int bend); void be_midi_set_pan(int voice, int pan); #ifdef __cplusplus } #endif allegro-4.4.3.1/include/allegro/platform/alunixac.hin0000664000175000017500000001176613437077643021513 0ustar siegesiege/* * Note that this file is no longer generated by autoheader as it results in * too much namespace pollution. If you add define a new macro in * configure.in or aclocal.m4, you must add an entry to this file. */ /* Define if you want support for n bpp modes. */ #undef ALLEGRO_COLOR8 #undef ALLEGRO_COLOR16 #undef ALLEGRO_COLOR24 #undef ALLEGRO_COLOR32 /*---------------------------------------------------------------------------*/ /* Define to 1 if you have the corresponding header file. */ #undef ALLEGRO_HAVE_DIRENT_H #undef ALLEGRO_HAVE_INTTYPES_H #undef ALLEGRO_HAVE_LINUX_AWE_VOICE_H #undef ALLEGRO_HAVE_LINUX_INPUT_H #undef ALLEGRO_HAVE_LINUX_JOYSTICK_H #undef ALLEGRO_HAVE_LINUX_SOUNDCARD_H #undef ALLEGRO_HAVE_MACHINE_SOUNDCARD_H #undef ALLEGRO_HAVE_SOUNDCARD_H #undef ALLEGRO_HAVE_STDINT_H #undef ALLEGRO_HAVE_SV_PROCFS_H #undef ALLEGRO_HAVE_SYS_IO_H #undef ALLEGRO_HAVE_SYS_SOUNDCARD_H #undef ALLEGRO_HAVE_SYS_STAT_H #undef ALLEGRO_HAVE_SYS_TIME_H #undef ALLEGRO_HAVE_SYS_UTSNAME_H /* Define to 1 if the corresponding functions are available. */ #undef ALLEGRO_HAVE_GETEXECNAME #undef ALLEGRO_HAVE_MEMCMP #undef ALLEGRO_HAVE_MKSTEMP #undef ALLEGRO_HAVE_MMAP #undef ALLEGRO_HAVE_MPROTECT #undef ALLEGRO_HAVE_SCHED_YIELD #undef ALLEGRO_HAVE_STRICMP #undef ALLEGRO_HAVE_STRLWR #undef ALLEGRO_HAVE_STRUPR #undef ALLEGRO_HAVE_SYSCONF /* Define to 1 if procfs reveals argc and argv */ #undef ALLEGRO_HAVE_PROCFS_ARGCV /*---------------------------------------------------------------------------*/ /* Define if target machine is little endian. */ #undef ALLEGRO_LITTLE_ENDIAN /* Define if target machine is big endian. */ #undef ALLEGRO_BIG_ENDIAN /* Define for Unix platforms, to use C convention for bank switching. */ #undef ALLEGRO_NO_ASM /* Define if compiler prepends underscore to symbols. */ #undef ALLEGRO_ASM_PREFIX /* Define if assembler supports MMX. */ #undef ALLEGRO_MMX /* Define if assembler supports SSE. */ #undef ALLEGRO_SSE /* Define if target platform is Darwin. */ #undef ALLEGRO_DARWIN /* Define if you have the pthread library. */ #undef ALLEGRO_HAVE_LIBPTHREAD /* Define if constructor attribute is supported. */ #undef ALLEGRO_USE_CONSTRUCTOR /* Define if you need to use a magic main. */ #undef ALLEGRO_WITH_MAGIC_MAIN /* Define if dynamically loaded modules are supported. */ #undef ALLEGRO_WITH_MODULES /*---------------------------------------------------------------------------*/ /* Define if you need support for X-Windows. */ #undef ALLEGRO_WITH_XWINDOWS /* Define if MIT-SHM extension is supported. */ #undef ALLEGRO_XWINDOWS_WITH_SHM /* Define if XCursor ARGB extension is available. */ #undef ALLEGRO_XWINDOWS_WITH_XCURSOR /* Define if DGA version 2.0 or newer is supported */ #undef ALLEGRO_XWINDOWS_WITH_XF86DGA2 /* Define if XF86VidMode extension is supported. */ #undef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE /* Define if XIM extension is supported. */ #undef ALLEGRO_XWINDOWS_WITH_XIM /* Define if xpm bitmap support is available. */ #undef ALLEGRO_XWINDOWS_WITH_XPM /*---------------------------------------------------------------------------*/ /* Define if target platform is linux. */ #undef ALLEGRO_LINUX /* Define to enable Linux console fbcon driver. */ #undef ALLEGRO_LINUX_FBCON /* Define to enable Linux console SVGAlib driver. */ #undef ALLEGRO_LINUX_SVGALIB /* Define if SVGAlib driver can check vga_version. */ #undef ALLEGRO_LINUX_SVGALIB_HAVE_VGA_VERSION /* Define to enable Linux console VBE/AF driver. */ #undef ALLEGRO_LINUX_VBEAF /* Define to enable Linux console VGA driver. */ #undef ALLEGRO_LINUX_VGA /*---------------------------------------------------------------------------*/ /* Define to the installed ALSA version. */ #undef ALLEGRO_ALSA_VERSION /* Define if ALSA DIGI driver is supported. */ #undef ALLEGRO_WITH_ALSADIGI /* Define if ALSA MIDI driver is supported. */ #undef ALLEGRO_WITH_ALSAMIDI /* Define if aRts DIGI driver is supported. */ #undef ALLEGRO_WITH_ARTSDIGI /* Define if ESD DIGI driver is supported. */ #undef ALLEGRO_WITH_ESDDIGI /* Define if JACK DIGI driver is supported. */ #undef ALLEGRO_WITH_JACKDIGI /* Define if OSS DIGI driver is supported. */ #undef ALLEGRO_WITH_OSSDIGI /* Define if OSS MIDI driver is supported. */ #undef ALLEGRO_WITH_OSSMIDI /* Define if SGI AL DIGI driver is supported. */ #undef ALLEGRO_WITH_SGIALDIGI /*---------------------------------------------------------------------------*/ /* Define to (void *)-1, if MAP_FAILED is not defined. */ /* TODO: rename this */ #undef MAP_FAILED /* Define as the return type of signal handlers (`int' or `void'). */ /* TODO: rename this */ #undef RETSIGTYPE /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to `unsigned int' if does not define. */ #undef size_t /*---------------------------------------------------------------------------*/ /* vi:set ft=c: */ allegro-4.4.3.1/include/allegro/platform/almngw32.h0000664000175000017500000000516213437077643021003 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with Mingw32. * * By Michael Rickmann. * * Native build version by Henrik Stokseth. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #include #include #endif /* a static auto config */ /* older mingw's don't seem to have inttypes.h */ /* #define ALLEGRO_HAVE_INTTYPES_H */ #define ALLEGRO_HAVE_STDINT_H 1 /* describe this platform */ #ifdef ALLEGRO_STATICLINK #define ALLEGRO_PLATFORM_STR "MinGW32.s" #else #define ALLEGRO_PLATFORM_STR "MinGW32" #endif #define ALLEGRO_WINDOWS #define ALLEGRO_I386 #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_USE_CONSTRUCTOR #define ALLEGRO_MULTITHREADED #ifdef ALLEGRO_USE_CONSOLE #define ALLEGRO_CONSOLE_OK #define ALLEGRO_NO_MAGIC_MAIN #endif /* describe how function prototypes look to MINGW32 */ #if (defined ALLEGRO_STATICLINK) || (defined ALLEGRO_SRC) #define _AL_DLL #else #define _AL_DLL __declspec(dllimport) #endif #define AL_VAR(type, name) extern _AL_DLL type name #define AL_ARRAY(type, name) extern _AL_DLL type name[] #define AL_FUNC(type, name, args) extern type name args #define AL_METHOD(type, name, args) type (*name) args #define AL_FUNCPTR(type, name, args) extern _AL_DLL type (*name) args /* windows specific defines */ #if (defined ALLEGRO_SRC) /* pathches to handle DX7 headers on a win9x system */ /* should WINNT be defined on win9x systems? */ #ifdef WINNT #undef WINNT #endif /* defined in windef.h */ #ifndef HMONITOR_DECLARED #define HMONITOR_DECLARED 1 #endif #endif /* ALLEGRO_SRC */ /* another instance of missing constants in the mingw32 headers */ #ifndef ENUM_CURRENT_SETTINGS #define ENUM_CURRENT_SETTINGS ((DWORD)-1) #endif /* describe the asm syntax for this platform */ #define ALLEGRO_ASM_PREFIX "_" /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" #define ALLEGRO_ASMCAPA_HEADER "obj/mingw32/asmcapa.h" allegro-4.4.3.1/include/allegro/platform/albecfg.h0000664000175000017500000000307413437077643020734 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include #include /* provide implementations of missing functions */ #define ALLEGRO_NO_STRICMP #define ALLEGRO_NO_STRLWR #define ALLEGRO_NO_STRUPR /* a static auto config */ #define ALLEGRO_HAVE_DIRENT_H 1 #define ALLEGRO_HAVE_INTTYPES_H 1 /* TODO: check this */ #define ALLEGRO_HAVE_STDINT_H 1 /* TODO: check this */ #define ALLEGRO_HAVE_SYS_TIME_H 1 /* describe this platform */ #if defined __BEOS__ && !defined __HAIKU__ #define ALLEGRO_PLATFORM_STR "BeOS" #endif #if defined __HAIKU__ #define ALLEGRO_PLATFORM_STR "Haiku" #define ALLEGRO_HAVE_LIBPTHREAD 1 #endif #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_CONSOLE_OK #define ALLEGRO_USE_CONSTRUCTOR #define ALLEGRO_MULTITHREADED /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/albeos.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintbeos.h" #define ALLEGRO_ASMCAPA_HEADER "obj/beos/asmcapa.h" allegro-4.4.3.1/include/allegro/platform/alplatf.h.cmake0000664000175000017500000000065213437077643022052 0ustar siegesiege#cmakedefine ALLEGRO_BCC32 #cmakedefine ALLEGRO_BEOS #cmakedefine ALLEGRO_DJGPP #cmakedefine ALLEGRO_DMC #cmakedefine ALLEGRO_HAIKU #cmakedefine ALLEGRO_MACOSX #cmakedefine ALLEGRO_MINGW32 #cmakedefine ALLEGRO_MPW #cmakedefine ALLEGRO_MSVC #cmakedefine ALLEGRO_PSP #cmakedefine ALLEGRO_QNX #cmakedefine ALLEGRO_UNIX #cmakedefine ALLEGRO_WATCOM /* These are always defined now. */ #define ALLEGRO_NO_ASM #define ALLEGRO_USE_C allegro-4.4.3.1/include/allegro/platform/alpsp.h0000664000175000017500000000271113437077643020465 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PSP specific header defines. * * By diedel. * * See readme.txt for copyright information. */ #ifndef ALPSP_H #define ALPSP_H #ifndef ALLEGRO_PSP #error bad include #endif /* System driver */ #define SYSTEM_PSP AL_ID('P','S','P',' ') AL_VAR(SYSTEM_DRIVER, system_psp); /* Timer driver */ #define TIMER_PSP AL_ID('P','S','P','T') AL_VAR(TIMER_DRIVER, timer_psp); /* Keyboard driver */ #define KEYSIM_PSP AL_ID('P','S','P','K') AL_VAR(KEYBOARD_DRIVER, keybd_simulator_psp); /* Mouse drivers */ #define MOUSE_PSP AL_ID('P','S','P','M') AL_VAR(MOUSE_DRIVER, mouse_psp); /* Gfx driver */ #define GFX_PSP AL_ID('P','S','P','G') AL_VAR(GFX_DRIVER, gfx_psp); /* Digital sound driver */ #define DIGI_PSP AL_ID('P','S','P','S') AL_VAR(DIGI_DRIVER, digi_psp); /* Joystick drivers */ #define JOYSTICK_PSP AL_ID('P','S','P','J') AL_VAR(JOYSTICK_DRIVER, joystick_psp); #endif allegro-4.4.3.1/include/allegro/platform/aldjgpp.h0000664000175000017500000000577613437077643021005 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with djgpp. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #include #include #include #include #include #endif /* describe this platform */ #define ALLEGRO_PLATFORM_STR "djgpp" #define ALLEGRO_DOS #define ALLEGRO_I386 #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_GUESS_INTTYPES_OK /* inttypes.h and stdint.h not available in djgpp 2.02 */ #define ALLEGRO_CONSOLE_OK #define ALLEGRO_VRAM_SINGLE_SURFACE #define ALLEGRO_USE_CONSTRUCTOR #ifdef __cplusplus extern "C" { #endif /* memory locking macros */ void _unlock_dpmi_data(void *addr, int size); #define END_OF_FUNCTION(x) void x##_end(void) { } #define END_OF_STATIC_FUNCTION(x) static void x##_end(void) { } #define LOCK_DATA(d, s) _go32_dpmi_lock_data((void *)d, s) #define LOCK_CODE(c, s) _go32_dpmi_lock_code((void *)c, s) #define UNLOCK_DATA(d,s) _unlock_dpmi_data((void *)d, s) #define LOCK_VARIABLE(x) LOCK_DATA((void *)&x, sizeof(x)) #define LOCK_FUNCTION(x) LOCK_CODE((void *)x, (intptr_t)x##_end - (intptr_t)x) /* long filename status */ #ifdef _USE_LFN #define ALLEGRO_LFN _USE_LFN #else #define ALLEGRO_LFN 0 #endif /* selector for video memory bitmaps */ #define _video_ds() _dos_ds /* helpers for talking to video memory */ #define bmp_select(bmp) _farsetsel((bmp)->seg) #define bmp_write8(addr, c) _farnspokeb(addr, c) #define bmp_write15(addr, c) _farnspokew(addr, c) #define bmp_write16(addr, c) _farnspokew(addr, c) #define bmp_write24(addr, c) ({ _farnspokew(addr, c&0xFFFF); \ _farnspokeb(addr+2, c>>16); }) #define bmp_write32(addr, c) _farnspokel(addr, c) #define bmp_read8(addr) _farnspeekb(addr) #define bmp_read15(addr) _farnspeekw(addr) #define bmp_read16(addr) _farnspeekw(addr) #define bmp_read32(addr) _farnspeekl(addr) #define bmp_read24(addr) (_farnspeekl(addr) & 0xFFFFFF) #ifdef __cplusplus } #endif /* describe the asm syntax for this platform */ #define ALLEGRO_ASM_PREFIX "_" #define ALLEGRO_ASM_USE_FS /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/aldos.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintdos.h" #define ALLEGRO_ASMCAPA_HEADER "obj/djgpp/asmcapa.h" allegro-4.4.3.1/include/allegro/platform/alqnxcfg.h0000664000175000017500000000311313437077643021146 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with QNX. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #include #include #endif /* a static auto config */ #define ALLEGRO_HAVE_INTTYPES_H 1 #define ALLEGRO_HAVE_STDINT_H 1 #define ALLEGRO_HAVE_STRICMP 1 #define ALLEGRO_HAVE_STRLWR 1 #define ALLEGRO_HAVE_STRUPR 1 #define ALLEGRO_HAVE_MEMCMP 1 #define ALLEGRO_HAVE_MKSTEMP 1 #define ALLEGRO_HAVE_DIRENT_H 1 #define ALLEGRO_HAVE_SYS_UTSNAME_H 1 #define ALLEGRO_HAVE_SYS_TIME_H 1 #define ALLEGRO_HAVE_LIBPTHREAD 1 /* describe this platform */ #define ALLEGRO_PLATFORM_STR "QNX" #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_CONSOLE_OK #define ALLEGRO_HAVE_SCHED_YIELD #define ALLEGRO_USE_CONSTRUCTOR #undef ALLEGRO_MULTITHREADED /* FIXME */ /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alqnx.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintqnx.h" #define ALLEGRO_ASMCAPA_HEADER "obj/qnx/asmcapa.h" allegro-4.4.3.1/include/allegro/platform/almaccfg.h0000664000175000017500000000452413437077643021107 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with MPW. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #endif #define CALL_NOT_IN_CARBON 1 #include #ifndef ENOSYS #define ENOSYS ENOENT #endif /* describe this platform */ #define ALLEGRO_PLATFORM_STR "mpw" #define ALLEGRO_BIG_ENDIAN #undef ALLEGRO_CONSOLE_OK #define INLINE #define ZERO_SIZE_ARRAY(type, name) type name[64] #define AL_CONST const #define AL_VAR(type, name) extern type name #define AL_ARRAY(type, name) extern type name[] #define AL_FUNC(type, name, args) type name args #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) #define AL_METHOD(type, name, args) type (*name) args #define AL_FUNCPTR(type, name, args) extern type (*name) args #define END_OF_MAIN() void x##_end(void) { } #define END_OF_FUNCTION(x) void x##_end(void) { } #define END_OF_STATIC_FUNCTION(x) static void x##_end(void) { } #define LOCK_DATA(d, s) _mac_lock((void *)d, s) #define LOCK_CODE(c, s) _mac_lock((void *)c, s) #define UNLOCK_DATA(d,s) _mac_unlock((void *)d, s) #define LOCK_VARIABLE(x) LOCK_DATA((void *)&x, sizeof(x)) #define LOCK_FUNCTION(x) LOCK_CODE((void *)x, (intptr_t)x##_end - (intptr_t)x) /* long filename status */ #define ALLEGRO_LFN 0 #define ALLEGRO_NO_STRICMP 1 #define ALLEGRO_NO_STRUPR 1 //#define ALLEGRO_NO_STRDUP 1 #ifdef __cplusplus extern "C" #endif char *strdup(const char *); #ifndef AL_INLINE #define AL_INLINE(type, name, args, code) static type name args code #endif // gm_time has an strange return #define gmtime localtime #define ALLEGRO_EXTRA_HEADER "allegro/platform/almac.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintmac.h" allegro-4.4.3.1/include/allegro/platform/aintdos.h0000664000175000017500000001163213437077643021011 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some definitions for internal use by the DOS library code. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef AINTDOS_H #define AINTDOS_H #ifndef ALLEGRO_H #error must include allegro.h first #endif #ifndef ALLEGRO_DOS #error bad include #endif #ifdef __cplusplus extern "C" { #endif /* macros to enable and disable interrupts */ #if defined ALLEGRO_GCC #define DISABLE() asm volatile ("cli") #define ENABLE() asm volatile ("sti") #elif defined ALLEGRO_WATCOM void DISABLE(void); void ENABLE(void); #pragma aux DISABLE = "cli"; #pragma aux ENABLE = "sti"; #else #define DISABLE() asm { cli } #define ENABLE() asm { sti } #endif AL_INLINE(void, _enter_critical, (void), { /* check if windows is running */ if ((os_type == OSTYPE_WIN3) || (os_type == OSTYPE_WIN95) || (os_type == OSTYPE_WIN98) || (os_type == OSTYPE_WINME) || (os_type == OSTYPE_WINNT) || (os_type == OSTYPE_WIN2000)) { __dpmi_regs r; r.x.ax = 0x1681; __dpmi_int(0x2F, &r); } DISABLE(); }) AL_INLINE(void, _exit_critical, (void), { /* check if windows is running */ if ((os_type == OSTYPE_WIN3) || (os_type == OSTYPE_WIN95) || (os_type == OSTYPE_WIN98) || (os_type == OSTYPE_WINME) || (os_type == OSTYPE_WINNT) || (os_type == OSTYPE_WIN2000)) { __dpmi_regs r; r.x.ax = 0x1682; __dpmi_int(0x2F, &r); } ENABLE(); }) /* interrupt hander stuff */ AL_FUNC(void, _dos_irq_init, (void)); AL_FUNC(void, _dos_irq_exit, (void)); #define _map_irq(irq) (((irq)>7) ? ((irq)+104) : ((irq)+8)) AL_FUNC(int, _install_irq, (int num, AL_METHOD(int, handler, (void)))); AL_FUNC(void, _remove_irq, (int num)); AL_FUNC(void, _restore_irq, (int irq)); AL_FUNC(void, _enable_irq, (int irq)); AL_FUNC(void, _disable_irq, (int irq)); #define _eoi(irq) { outportb(0x20, 0x20); if ((irq)>7) outportb(0xA0, 0x20); } typedef struct _IRQ_HANDLER { AL_METHOD(int, handler, (void)); /* our C handler */ int number; /* irq number */ #ifdef ALLEGRO_DJGPP __dpmi_paddr old_vector; /* original protected mode vector */ #else void (__interrupt __far *old_vector)(); #endif } _IRQ_HANDLER; /* sound lib stuff */ AL_VAR(int, _fm_port); AL_VAR(int, _mpu_port); AL_VAR(int, _mpu_irq); /* DPMI memory mapping routines */ AL_FUNC(int, _create_physical_mapping, (unsigned long *linear, int *segment, unsigned long physaddr, int size)); AL_FUNC(void, _remove_physical_mapping, (unsigned long *linear, int *segment)); AL_FUNC(int, _create_linear_mapping, (unsigned long *linear, unsigned long physaddr, int size)); AL_FUNC(void, _remove_linear_mapping, (unsigned long *linear)); AL_FUNC(int, _create_selector, (int *segment, unsigned long linear, int size)); AL_FUNC(void, _remove_selector, (int *segment)); AL_FUNC(void, _unlock_dpmi_data, (void *addr, int size)); /* bank switching routines (these use a non-C calling convention on i386!) */ AL_FUNC(void, _vesa_window_1, (void)); AL_FUNC(void, _vesa_window_1_end, (void)); AL_FUNC(void, _vesa_window_2, (void)); AL_FUNC(void, _vesa_window_2_end, (void)); AL_FUNC(void, _vesa_pm_window_1, (void)); AL_FUNC(void, _vesa_pm_window_1_end, (void)); AL_FUNC(void, _vesa_pm_window_2, (void)); AL_FUNC(void, _vesa_pm_window_2_end, (void)); AL_FUNC(void, _vesa_pm_es_window_1, (void)); AL_FUNC(void, _vesa_pm_es_window_1_end, (void)); AL_FUNC(void, _vesa_pm_es_window_2, (void)); AL_FUNC(void, _vesa_pm_es_window_2_end, (void)); /* stuff for the VESA driver */ AL_VAR(__dpmi_regs, _dpmi_reg); AL_VAR(int, _window_2_offset); AL_VAR(int, _mmio_segment); AL_FUNCPTR(void, _pm_vesa_switcher, (void)); AL_FUNCPTR(void, _pm_vesa_scroller, (void)); AL_FUNCPTR(void, _pm_vesa_palette, (void)); AL_FUNC(int, _sb_read_dsp_version, (void)); AL_FUNC(int, _sb_reset_dsp, (int data)); AL_FUNC(void, _sb_voice, (int state)); AL_FUNC(int, _sb_set_mixer, (int digi_volume, int midi_volume)); AL_FUNC(void, _mpu_poll, (void)); AL_FUNC(int, _dma_allocate_mem, (int bytes, int *sel, unsigned long *phys)); AL_FUNC(void, _dma_start, (int channel, unsigned long addr, int size, int auto_init, int input)); AL_FUNC(void, _dma_stop, (int channel)); AL_FUNC(unsigned long, _dma_todo, (int channel)); AL_FUNC(void, _dma_lock_mem, (void)); #ifdef __cplusplus } #endif /* VGA register access helpers */ #include "allegro/internal/aintvga.h" #endif /* ifndef AINTDOS_H */ allegro-4.4.3.1/include/allegro/platform/aintwin.h0000664000175000017500000001451213437077643021021 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some definitions for internal use by the Windows library code. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #ifndef AINTWIN_H #define AINTWIN_H #ifndef ALLEGRO_H #error must include allegro.h first #endif #ifndef ALLEGRO_WINDOWS #error bad include #endif #include "winalleg.h" #ifndef SCAN_DEPEND /* workaround for buggy MinGW32 headers */ #ifdef ALLEGRO_MINGW32 #ifndef HMONITOR_DECLARED #define HMONITOR_DECLARED #endif #if (defined _HRESULT_DEFINED) && (defined WINNT) #undef WINNT #endif #endif #include /* for LPGUID */ #endif #ifdef __cplusplus extern "C" { #endif /* generals */ AL_VAR(HINSTANCE, allegro_inst); AL_VAR(HANDLE, allegro_thread); AL_VAR(CRITICAL_SECTION, allegro_critical_section); AL_VAR(int, _dx_ver); #define _enter_critical() EnterCriticalSection(&allegro_critical_section) #define _exit_critical() LeaveCriticalSection(&allegro_critical_section) AL_FUNC(int, init_directx_window, (void)); AL_FUNC(void, exit_directx_window, (void)); AL_FUNC(int, get_dx_ver, (void)); AL_FUNC(int, adjust_window, (int w, int h)); AL_FUNC(void, restore_window_style, (void)); AL_FUNC(void, save_window_pos, (void)); /* main window */ #define WND_TITLE_SIZE 128 AL_ARRAY(char, wnd_title); AL_VAR(int, wnd_x); AL_VAR(int, wnd_y); AL_VAR(int, wnd_width); AL_VAR(int, wnd_height); AL_VAR(int, wnd_sysmenu); AL_FUNCPTR(void, user_close_proc, (void)); /* gfx synchronization */ AL_VAR(CRITICAL_SECTION, gfx_crit_sect); AL_VAR(int, gfx_crit_sect_nesting); #define _enter_gfx_critical() EnterCriticalSection(&gfx_crit_sect); \ gfx_crit_sect_nesting++ #define _exit_gfx_critical() LeaveCriticalSection(&gfx_crit_sect); \ gfx_crit_sect_nesting-- #define GFX_CRITICAL_RELEASED (!gfx_crit_sect_nesting) /* switch routines */ AL_VAR(int, _win_app_foreground); AL_FUNC(void, sys_directx_display_switch_init, (void)); AL_FUNC(void, sys_directx_display_switch_exit, (void)); AL_FUNC(int, sys_directx_set_display_switch_mode, (int mode)); AL_FUNC(void, _win_switch_in, (void)); AL_FUNC(void, _win_switch_out, (void)); AL_FUNC(void, _win_reset_switch_mode, (void)); AL_FUNC(int, _win_thread_switch_out, (void)); /* main window routines */ AL_FUNC(int, wnd_call_proc, (int (*proc)(void))); AL_FUNC(void, wnd_schedule_proc, (int (*proc)(void))); /* input routines */ AL_VAR(int, _win_input_events); AL_ARRAY(HANDLE, _win_input_event_id); AL_FUNCPTRARRAY(void, _win_input_event_handler, (void)); AL_FUNC(void, _win_input_init, (int need_thread)); AL_FUNC(void, _win_input_exit, (void)); AL_FUNC(int, _win_input_register_event, (HANDLE event_id, void (*event_handler)(void))); AL_FUNC(void, _win_input_unregister_event, (HANDLE event_id)); /* keyboard routines */ AL_FUNC(int, key_dinput_acquire, (void)); AL_FUNC(int, key_dinput_unacquire, (void)); /* mouse routines */ AL_VAR(HCURSOR, _win_hcursor); AL_FUNC(int, mouse_dinput_acquire, (void)); AL_FUNC(int, mouse_dinput_unacquire, (void)); AL_FUNC(int, mouse_dinput_grab, (void)); AL_FUNC(int, mouse_set_syscursor, (void)); AL_FUNC(int, mouse_set_sysmenu, (int state)); /* joystick routines */ #define WINDOWS_MAX_AXES 6 #define WINDOWS_JOYSTICK_INFO_MEMBERS \ int caps; \ int num_axes; \ int axis[WINDOWS_MAX_AXES]; \ char *axis_name[WINDOWS_MAX_AXES]; \ int hat; \ char *hat_name; \ int num_buttons; \ int button[MAX_JOYSTICK_BUTTONS]; \ char *button_name[MAX_JOYSTICK_BUTTONS]; typedef struct WINDOWS_JOYSTICK_INFO { WINDOWS_JOYSTICK_INFO_MEMBERS } WINDOWS_JOYSTICK_INFO; AL_FUNC(int, win_add_joystick, (WINDOWS_JOYSTICK_INFO *win_joy)); AL_FUNC(void, win_remove_all_joysticks, (void)); AL_FUNC(int, win_update_joystick_status, (int n, WINDOWS_JOYSTICK_INFO *win_joy)); AL_FUNC(int, joystick_dinput_acquire, (void)); AL_FUNC(int, joystick_dinput_unacquire, (void)); /* thread routines */ AL_FUNC(void, _win_thread_init, (void)); AL_FUNC(void, _win_thread_exit, (void)); /* synchronization routines */ AL_FUNC(void *, sys_directx_create_mutex, (void)); AL_FUNC(void, sys_directx_destroy_mutex, (void *handle)); AL_FUNC(void, sys_directx_lock_mutex, (void *handle)); AL_FUNC(void, sys_directx_unlock_mutex, (void *handle)); /* sound routines */ AL_FUNC(_DRIVER_INFO *, _get_win_digi_driver_list, (void)); AL_FUNC(void, _free_win_digi_driver_list, (void)); AL_FUNC(DIGI_DRIVER *, _get_dsalmix_driver, (char *name, LPGUID guid, int num)); AL_FUNC(void, _free_win_dsalmix_name_list, (void)); AL_FUNC(DIGI_DRIVER *, _get_woalmix_driver, (int num)); AL_FUNC(int, digi_directsound_capture_init, (LPGUID guid)); AL_FUNC(void, digi_directsound_capture_exit, (void)); AL_FUNC(int, digi_directsound_capture_detect, (LPGUID guid)); AL_FUNC(int, digi_directsound_rec_cap_rate, (int bits, int stereo)); AL_FUNC(int, digi_directsound_rec_cap_param, (int rate, int bits, int stereo)); AL_FUNC(int, digi_directsound_rec_source, (int source)); AL_FUNC(int, digi_directsound_rec_start, (int rate, int bits, int stereo)); AL_FUNC(void, digi_directsound_rec_stop, (void)); AL_FUNC(int, digi_directsound_rec_read, (void *buf)); /* midi routines */ AL_FUNC(_DRIVER_INFO *, _get_win_midi_driver_list, (void)); AL_FUNC(void, _free_win_midi_driver_list, (void)); AL_FUNC(void, midi_switch_out, (void)); /* file routines */ AL_VAR(int, _al_win_unicode_filenames); /* error handling */ AL_FUNC(char* , win_err_str, (long err)); AL_FUNC(void, thread_safe_trace, (char *msg, ...)); #if DEBUGMODE >= 2 #define _TRACE thread_safe_trace #else #define _TRACE 1 ? (void) 0 : thread_safe_trace #endif #ifdef __cplusplus } #endif #endif /* !defined AINTWIN_H */ allegro-4.4.3.1/include/allegro/platform/alosxcfg.h0000664000175000017500000000326113437077643021155 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with MacOS X. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #ifndef ALOSXCFG_H #define ALOSXCFG_H /* Provide implementations of missing functions */ #define ALLEGRO_NO_STRICMP #define ALLEGRO_NO_STRLWR #define ALLEGRO_NO_STRUPR /* Override default definitions for this platform */ #define AL_RAND() ((rand() >> 16) & 0x7fff) /* A static auto config */ #define ALLEGRO_HAVE_LIBPTHREAD 1 #define ALLEGRO_HAVE_DIRENT_H 1 #define ALLEGRO_HAVE_INTTYPES_H 1 #define ALLEGRO_HAVE_STDINT_H 1 #define ALLEGRO_HAVE_SYS_TIME_H 1 #define ALLEGRO_HAVE_SYS_STAT_H 1 #define ALLEGRO_HAVE_MKSTEMP 1 /* Describe this platform */ #define ALLEGRO_PLATFORM_STR "MacOS X" #define ALLEGRO_CONSOLE_OK #define ALLEGRO_USE_CONSTRUCTOR #define ALLEGRO_MULTITHREADED /* Endianesse - different between Intel and PPC based Mac's */ #ifdef __LITTLE_ENDIAN__ #define ALLEGRO_LITTLE_ENDIAN #endif #ifdef __BIG_ENDIAN__ #define ALLEGRO_BIG_ENDIAN #endif /* Exclude ASM */ #ifndef ALLEGRO_NO_ASM #define ALLEGRO_NO_ASM #endif /* Arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alosx.h" #endif allegro-4.4.3.1/include/allegro/platform/aldmc.h0000664000175000017500000000506613437077643020434 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with Digital Mars C compiler. * * By Matthew Leverton. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #endif #include /* a static auto config */ #define ALLEGRO_HAVE_INTTYPES_H #define ALLEGRO_HAVE_STDINT_H #define LONG_LONG long long /* describe this platform */ #ifdef ALLEGRO_STATICLINK #define ALLEGRO_PLATFORM_STR "DMC.s" #else #define ALLEGRO_PLATFORM_STR "DMC" #endif #define ALLEGRO_WINDOWS #define ALLEGRO_I386 #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_MULTITHREADED #ifdef ALLEGRO_USE_CONSOLE #define ALLEGRO_CONSOLE_OK #define ALLEGRO_NO_MAGIC_MAIN #endif /* describe how function prototypes look to DMC */ #if defined ALLEGRO_STATICLINK #define _AL_DLL #elif defined ALLEGRO_SRC #define _AL_DLL __declspec(dllexport) #else #define _AL_DLL __declspec(dllimport) #endif #define AL_VAR(type, name) extern _AL_DLL type name #define AL_ARRAY(type, name) extern _AL_DLL type name[] #define AL_FUNC(type, name, args) extern type name args #define AL_METHOD(type, name, args) type (*name) args #define AL_FUNCPTR(type, name, args) extern _AL_DLL type (*name) args /* Windows specific defines */ #if (defined ALLEGRO_SRC) #if (!defined S_IRUSR) && (!defined SCAN_DEPEND) #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #endif typedef unsigned long _fsize_t; struct _wfinddata_t { unsigned attrib; time_t time_create; /* -1 for FAT file systems */ time_t time_access; /* -1 for FAT file systems */ time_t time_write; _fsize_t size; wchar_t name[260]; /* may include spaces. */ }; #endif /* ALLEGRO_SRC */ /* describe the asm syntax for this platform */ #define ALLEGRO_ASM_PREFIX "_" /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" #define ALLEGRO_ASMCAPA_HEADER "obj/dmc/asmcapa.h" allegro-4.4.3.1/include/allegro/platform/alunixac.h.cmake0000664000175000017500000001314213437077643022231 0ustar siegesiege/* * Note that this file is no longer generated by autoheader as it results in * too much namespace pollution. If you add define a new macro in * configure.in or aclocal.m4, you must add an entry to this file. */ /* Define if you want support for n bpp modes. */ #cmakedefine ALLEGRO_COLOR8 #cmakedefine ALLEGRO_COLOR16 #cmakedefine ALLEGRO_COLOR24 #cmakedefine ALLEGRO_COLOR32 /*---------------------------------------------------------------------------*/ /* Define to 1 if you have the corresponding header file. */ #cmakedefine ALLEGRO_HAVE_DIRENT_H #cmakedefine ALLEGRO_HAVE_INTTYPES_H #cmakedefine ALLEGRO_HAVE_LINUX_AWE_VOICE_H #cmakedefine ALLEGRO_HAVE_LINUX_INPUT_H #cmakedefine ALLEGRO_HAVE_LINUX_JOYSTICK_H #cmakedefine ALLEGRO_HAVE_LINUX_SOUNDCARD_H #cmakedefine ALLEGRO_HAVE_MACHINE_SOUNDCARD_H #cmakedefine ALLEGRO_HAVE_SOUNDCARD_H #cmakedefine ALLEGRO_HAVE_STDINT_H #cmakedefine ALLEGRO_HAVE_SV_PROCFS_H #cmakedefine ALLEGRO_HAVE_SYS_IO_H #cmakedefine ALLEGRO_HAVE_SYS_SOUNDCARD_H #cmakedefine ALLEGRO_HAVE_SYS_STAT_H #cmakedefine ALLEGRO_HAVE_SYS_TIME_H #cmakedefine ALLEGRO_HAVE_SYS_UTSNAME_H /* Define to 1 if the corresponding functions are available. */ #cmakedefine ALLEGRO_HAVE_GETEXECNAME #cmakedefine ALLEGRO_HAVE_MEMCMP #cmakedefine ALLEGRO_HAVE_MKSTEMP #cmakedefine ALLEGRO_HAVE_MMAP #cmakedefine ALLEGRO_HAVE_MPROTECT #cmakedefine ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK #cmakedefine ALLEGRO_HAVE_SCHED_YIELD #cmakedefine ALLEGRO_HAVE_STRICMP #cmakedefine ALLEGRO_HAVE_STRLWR #cmakedefine ALLEGRO_HAVE_STRUPR #cmakedefine ALLEGRO_HAVE_SYSCONF /* Define to 1 if procfs reveals argc and argv */ #cmakedefine ALLEGRO_HAVE_PROCFS_ARGCV /*---------------------------------------------------------------------------*/ /* Define if target machine is little endian. */ #cmakedefine ALLEGRO_LITTLE_ENDIAN /* Define if target machine is big endian. */ #cmakedefine ALLEGRO_BIG_ENDIAN /* Define for Unix platforms, to use C convention for bank switching. */ #cmakedefine ALLEGRO_NO_ASM /* Define if compiler prepends underscore to symbols. */ #cmakedefine ALLEGRO_ASM_PREFIX /* Define if assembler supports MMX. */ #cmakedefine ALLEGRO_MMX /* Define if assembler supports SSE. */ #cmakedefine ALLEGRO_SSE /* Define if target platform is Darwin. */ #cmakedefine ALLEGRO_DARWIN /* Define if you have the pthread library. */ #cmakedefine ALLEGRO_HAVE_LIBPTHREAD /* Define if constructor attribute is supported. */ #cmakedefine ALLEGRO_USE_CONSTRUCTOR /* Define if you need to use a magic main. */ #cmakedefine ALLEGRO_WITH_MAGIC_MAIN /* Define if dynamically loaded modules are supported. */ #cmakedefine ALLEGRO_WITH_MODULES /*---------------------------------------------------------------------------*/ /* Define if you need support for X-Windows. */ #cmakedefine ALLEGRO_WITH_XWINDOWS /* Define if MIT-SHM extension is supported. */ #cmakedefine ALLEGRO_XWINDOWS_WITH_SHM /* Define if XCursor ARGB extension is available. */ #cmakedefine ALLEGRO_XWINDOWS_WITH_XCURSOR /* Define if DGA version 2.0 or newer is supported */ #cmakedefine ALLEGRO_XWINDOWS_WITH_XF86DGA2 /* Define if XF86VidMode extension is supported. */ #cmakedefine ALLEGRO_XWINDOWS_WITH_XF86VIDMODE /* Define if XIM extension is supported. */ #cmakedefine ALLEGRO_XWINDOWS_WITH_XIM /* Define if xpm bitmap support is available. */ #cmakedefine ALLEGRO_XWINDOWS_WITH_XPM /*---------------------------------------------------------------------------*/ /* Define if target platform is linux. */ #cmakedefine ALLEGRO_LINUX /* Define to enable Linux console fbcon driver. */ #cmakedefine ALLEGRO_LINUX_FBCON /* Define to enable Linux console SVGAlib driver. */ #cmakedefine ALLEGRO_LINUX_SVGALIB /* Define if SVGAlib driver can check vga_version. */ #cmakedefine ALLEGRO_LINUX_SVGALIB_HAVE_VGA_VERSION /* Define to enable Linux console VBE/AF driver. */ #cmakedefine ALLEGRO_LINUX_VBEAF /* Define to enable Linux console VGA driver. */ #cmakedefine ALLEGRO_LINUX_VGA /* Define to enable Linux console tslib mouse driver. */ #cmakedefine ALLEGRO_LINUX_TSLIB /*---------------------------------------------------------------------------*/ /* Define to the installed ALSA version. */ #cmakedefine ALLEGRO_ALSA_VERSION @ALLEGRO_ALSA_VERSION@ /* Define if ALSA DIGI driver is supported. */ #cmakedefine ALLEGRO_WITH_ALSADIGI /* Define if ALSA MIDI driver is supported. */ #cmakedefine ALLEGRO_WITH_ALSAMIDI /* Define if aRts DIGI driver is supported. */ #cmakedefine ALLEGRO_WITH_ARTSDIGI /* Define if ESD DIGI driver is supported. */ #cmakedefine ALLEGRO_WITH_ESDDIGI /* Define if JACK DIGI driver is supported. */ #cmakedefine ALLEGRO_WITH_JACKDIGI /* Define if OSS DIGI driver is supported. */ #cmakedefine ALLEGRO_WITH_OSSDIGI /* Define if OSS MIDI driver is supported. */ #cmakedefine ALLEGRO_WITH_OSSMIDI /* Define if SGI AL DIGI driver is supported. */ #cmakedefine ALLEGRO_WITH_SGIALDIGI /*---------------------------------------------------------------------------*/ /* Define to (void *)-1, if MAP_FAILED is not defined. */ /* TODO: rename this */ #cmakedefine MAP_FAILED @MAP_FAILED@ /* Define as the return type of signal handlers (`int' or `void'). */ /* TODO: rename this */ /* XXX too lazy to configure this */ #define RETSIGTYPE void /* Define to empty if `const' does not conform to ANSI C. */ #cmakedefine const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #cmakedefine inline #endif /* Define to `unsigned int' if does not define. */ #cmakedefine size_t /*---------------------------------------------------------------------------*/ /* vi:set ft=c: */ allegro-4.4.3.1/include/allegro/platform/astdint.h0000664000175000017500000000310613437077643021013 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * A header file to get definitions of uint*_t and int*_t. * * By Peter Wang. * * See readme.txt for copyright information. */ #ifndef ASTDINT_H #define ASTDINT_H /* Please only include this file from include/allegro/internal/alconfig.h * and don't add more than inttypes.h/stdint.h emulation here. Thanks. */ #if defined ALLEGRO_HAVE_INTTYPES_H #include #elif defined ALLEGRO_HAVE_STDINT_H #include #elif defined ALLEGRO_I386 && defined ALLEGRO_LITTLE_ENDIAN #ifndef ALLEGRO_GUESS_INTTYPES_OK #warning Guessing the definitions of fixed-width integer types. #endif #define int8_t signed char #define uint8_t unsigned char #define int16_t signed short #define uint16_t unsigned short #define int32_t signed int #define uint32_t unsigned int #define intptr_t int32_t #define uintptr_t uint32_t #else #error I dunno how to get the definitions of fixed-width integer types on your platform. Please report this to your friendly Allegro developer. #endif #endif /* ifndef ASTDINT_H */ allegro-4.4.3.1/include/allegro/platform/alwatcom.h0000664000175000017500000001345413437077643021163 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines for use with Watcom. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #ifndef __SW_3S #error Allegro only supports stack based calling convention #endif #ifndef __SW_S #error Stack overflow checking must be disabled #endif #include #include #include #include #include #include #endif #pragma disable_message (120 201 202) /* these are available in OpenWatcom 1.3 (12.3) */ #if __WATCOMC__ >= 1230 #define ALLEGRO_HAVE_INTTYPES_H 1 #define ALLEGRO_HAVE_STDINT_H 1 #else #define ALLEGRO_GUESS_INTTYPES_OK #endif /* describe this platform */ #define ALLEGRO_PLATFORM_STR "Watcom" #define ALLEGRO_DOS #define ALLEGRO_I386 #define ALLEGRO_LITTLE_ENDIAN #define ALLEGRO_CONSOLE_OK #define ALLEGRO_VRAM_SINGLE_SURFACE #define ALLEGRO_LFN 0 #define LONG_LONG long long #ifdef ALLEGRO_GUESS_INTTYPES_OK #define int64_t signed long long #define uint64_t unsigned long long #endif #if __WATCOMC__ >= 1100 #define ALLEGRO_MMX #endif #if __WATCOMC__ >= 1200 /* Open Watcom 1.0 */ #define AL_CONST const #endif /* emulate some important djgpp routines */ #define inportb(port) inp(port) #define inportw(port) inpw(port) #define outportb(port, val) outp(port, val) #define outportw(port, val) outpw(port, val) #define ffblk find_t #define ff_name name #define ff_attrib attrib #define ff_fsize size #define ff_ftime wr_time #define ff_fdate wr_date #define findfirst(name, dta, attrib) _dos_findfirst(name, attrib, dta) #define findnext(dta) _dos_findnext(dta) #define random() rand() #define srandom(n) srand(n) #define _dos_ds _default_ds() #define dosmemget(offset, length, buffer) memcpy(buffer, (void *)(offset), length) #define dosmemput(buffer, length, offset) memcpy((void *)(offset), buffer, length) #define __djgpp_nearptr_enable() 1 #define __djgpp_nearptr_disable() #define __djgpp_base_address 0 #define __djgpp_conventional_base 0 #define _crt0_startup_flags 1 #define _CRT0_FLAG_NEARPTR 1 #ifdef __cplusplus extern "C" { #endif typedef union __dpmi_regs { struct { unsigned long edi, esi, ebp, res, ebx, edx, ecx, eax; } d; struct { unsigned short di, di_hi, si, si_hi, bp, bp_hi, res, res_hi; unsigned short bx, bx_hi, dx, dx_hi, cx, cx_hi, ax, ax_hi; unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss; } x; struct { unsigned char edi[4], esi[4], ebp[4], res[4]; unsigned char bl, bh, ebx_b2, ebx_b3, dl, dh, edx_b2, edx_b3; unsigned char cl, ch, ecx_b2, ecx_b3, al, ah, eax_b2, eax_b3; } h; } __dpmi_regs; typedef struct __dpmi_meminfo { unsigned long handle; unsigned long size; unsigned long address; } __dpmi_meminfo; typedef struct __dpmi_free_mem_info { unsigned long largest_available_free_block_in_bytes; unsigned long maximum_unlocked_page_allocation_in_pages; unsigned long maximum_locked_page_allocation_in_pages; unsigned long linear_address_space_size_in_pages; unsigned long total_number_of_unlocked_pages; unsigned long total_number_of_free_pages; unsigned long total_number_of_physical_pages; unsigned long free_linear_address_space_in_pages; unsigned long size_of_paging_file_partition_in_pages; unsigned long reserved[3]; } __dpmi_free_mem_info; extern unsigned long __tb; int __dpmi_int(int vector, __dpmi_regs *regs); int __dpmi_allocate_dos_memory(int paragraphs, int *ret); int __dpmi_free_dos_memory(int selector); int __dpmi_physical_address_mapping(__dpmi_meminfo *info); int __dpmi_free_physical_address_mapping(__dpmi_meminfo *info); int __dpmi_lock_linear_region(__dpmi_meminfo *info); int __dpmi_unlock_linear_region(__dpmi_meminfo *info); int __dpmi_allocate_ldt_descriptors(int count); int __dpmi_free_ldt_descriptor(int descriptor); int __dpmi_get_segment_base_address(int selector, unsigned long *addr); int __dpmi_set_segment_base_address(int selector, unsigned long address); int __dpmi_set_segment_limit(int selector, unsigned long limit); int __dpmi_get_free_memory_information(__dpmi_free_mem_info *info); int __dpmi_simulate_real_mode_interrupt(int vector, __dpmi_regs *regs); int __dpmi_simulate_real_mode_procedure_retf(__dpmi_regs *regs); int _go32_dpmi_lock_data(void *lockaddr, unsigned long locksize); int _go32_dpmi_lock_code(void *lockaddr, unsigned long locksize); long _allocate_real_mode_callback(void (*handler)(__dpmi_regs *r), __dpmi_regs *regs); /* memory locking macros */ void _unlock_dpmi_data(void *addr, int size); #ifdef __cplusplus } #endif #define END_OF_FUNCTION(x) void x##_end(void) { } #define END_OF_STATIC_FUNCTION(x) static void x##_end(void) { } #define LOCK_DATA(d, s) _go32_dpmi_lock_data(d, s) #define LOCK_CODE(c, s) _go32_dpmi_lock_code(c, s) #define UNLOCK_DATA(d,s) _unlock_dpmi_data(d, s) #define LOCK_VARIABLE(x) LOCK_DATA((void *)&x, sizeof(x)) #define LOCK_FUNCTION(x) LOCK_CODE((void *)FP_OFF(x), (long)FP_OFF(x##_end) - (long)FP_OFF(x)) /* arrange for other headers to be included later on */ #define ALLEGRO_EXTRA_HEADER "allegro/platform/aldos.h" #define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintdos.h" allegro-4.4.3.1/include/allegro/platform/aintosx.h0000664000175000017500000001217113437077643021034 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Internal header file for the MacOS X Allegro library port. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #ifndef AINTOSX_H #define AINTOSX_H #ifdef __OBJC__ #include "allegro/platform/aintunix.h" #include #include #include #include #include #include #ifndef NSAppKitVersionNumber10_1 #define NSAppKitVersionNumber10_1 620 #endif #ifndef NSAppKitVersionNumber10_2 #define NSAppKitVersionNumber10_2 663 #endif #define OSX_GFX_NONE 0 #define OSX_GFX_WINDOW 1 #define OSX_GFX_FULL 2 #define BMP_EXTRA(bmp) ((BMP_EXTRA_INFO *)((bmp)->extra)) #define HID_MAX_DEVICES MAX_JOYSTICKS #define HID_MOUSE 0 #define HID_JOYSTICK 1 #define HID_GAMEPAD 2 #define HID_MAX_DEVICE_ELEMENTS ((MAX_JOYSTICK_AXIS * MAX_JOYSTICK_STICKS) + MAX_JOYSTICK_BUTTONS) #define HID_ELEMENT_BUTTON 0 #define HID_ELEMENT_AXIS 1 #define HID_ELEMENT_AXIS_PRIMARY_X 2 #define HID_ELEMENT_AXIS_PRIMARY_Y 3 #define HID_ELEMENT_STANDALONE_AXIS 4 #define HID_ELEMENT_HAT 5 @interface AllegroAppDelegate : NSObject - (BOOL)application: (NSApplication *)theApplication openFile: (NSString *)filename; - (void)applicationDidFinishLaunching: (NSNotification *)aNotification; - (void)applicationDidChangeScreenParameters: (NSNotification *)aNotification; + (void)app_main: (id)arg; - (NSApplicationTerminateReply) applicationShouldTerminate: (id)sender; - (void) quitAction: (id) sender; @end @interface AllegroWindow : NSWindow - (void)display; - (void)miniaturize: (id)sender; @end @interface AllegroWindowDelegate : NSObject - (BOOL)windowShouldClose: (id)sender; - (void)windowDidDeminiaturize: (NSNotification *)aNotification; @end @interface AllegroView: NSQuickDrawView - (void)resetCursorRects; @end typedef void RETSIGTYPE; typedef struct BMP_EXTRA_INFO { GrafPtr port; } BMP_EXTRA_INFO; typedef struct HID_ELEMENT { int type; IOHIDElementCookie cookie; int max, min; int app; int col; int index; char *name; } HID_ELEMENT; typedef struct HID_DEVICE { int type; char *manufacturer; char *product; int num_elements; int capacity; HID_ELEMENT *element; IOHIDDeviceInterface **interface; int cur_app; } HID_DEVICE; typedef struct { int count; int capacity; HID_DEVICE* devices; } HID_DEVICE_COLLECTION; void osx_event_handler(void); int osx_bootstrap_ok(void); void setup_direct_shifts(void); void osx_init_fade_system(void); void osx_fade_screen(int fade_in, double seconds); void osx_qz_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); void osx_qz_created_sub_bitmap(BITMAP *bmp, BITMAP *parent); BITMAP *osx_qz_create_video_bitmap(int width, int height); BITMAP *osx_qz_create_system_bitmap(int width, int height); void osx_qz_destroy_video_bitmap(BITMAP *bmp); int osx_setup_colorconv_blitter(void); void osx_update_dirty_lines(void); uintptr_t osx_qz_write_line(BITMAP *bmp, int lyne); void osx_qz_unwrite_line(BITMAP *bmp); void osx_qz_acquire(BITMAP *bmp); void osx_qz_release(BITMAP *bmp); void osx_keyboard_handler(int pressed, NSEvent *event); void osx_keyboard_modifiers(unsigned int new_mods); void osx_keyboard_focused(int focused, int state); void osx_mouse_handler(int x, int y, int dx, int dy, int dz, int buttons); int osx_mouse_set_sprite(BITMAP *sprite, int x, int y); int osx_mouse_show(BITMAP *bmp, int x, int y); void osx_mouse_hide(void); void osx_mouse_move(int x, int y); HID_DEVICE_COLLECTION *osx_hid_scan(int type, HID_DEVICE_COLLECTION*); void osx_hid_free(HID_DEVICE_COLLECTION *); AL_VAR(NSBundle *, osx_bundle); AL_VAR(void *, osx_event_mutex); AL_VAR(void *, osx_window_mutex); AL_VAR(int, osx_gfx_mode); AL_VAR(int, osx_screen_used); AL_VAR(NSCursor *, osx_blank_cursor); AL_VAR(NSCursor *, osx_cursor); AL_VAR(AllegroWindow *, osx_window); AL_ARRAY(char, osx_window_title); AL_VAR(int, osx_window_first_expose); AL_VAR(int, osx_skip_events_processing); AL_VAR(void *, osx_skip_events_processing_mutex); AL_VAR(CGDirectPaletteRef, osx_palette); AL_VAR(int, osx_palette_dirty); AL_VAR(int, osx_mouse_warped); AL_VAR(int, osx_skip_mouse_move); AL_VAR(int, osx_emulate_mouse_buttons); AL_VAR(NSTrackingRectTag, osx_mouse_tracking_rect); extern AL_METHOD(void, osx_window_close_hook, (void)); #endif #endif /* Local variables: */ /* mode: objc */ /* c-basic-offset: 3 */ /* indent-tabs-mode: nil */ /* End: */ allegro-4.4.3.1/include/allegro/3d.h0000664000175000017500000000772513437077643016042 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 3D polygon drawing routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_3D_H #define ALLEGRO_3D_H #include "base.h" #include "fixed.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; typedef struct V3D /* a 3d point (fixed point version) */ { fixed x, y, z; /* position */ fixed u, v; /* texture map coordinates */ int c; /* color */ } V3D; typedef struct V3D_f /* a 3d point (floating point version) */ { float x, y, z; /* position */ float u, v; /* texture map coordinates */ int c; /* color */ } V3D_f; #define POLYTYPE_FLAT 0 #define POLYTYPE_GCOL 1 #define POLYTYPE_GRGB 2 #define POLYTYPE_ATEX 3 #define POLYTYPE_PTEX 4 #define POLYTYPE_ATEX_MASK 5 #define POLYTYPE_PTEX_MASK 6 #define POLYTYPE_ATEX_LIT 7 #define POLYTYPE_PTEX_LIT 8 #define POLYTYPE_ATEX_MASK_LIT 9 #define POLYTYPE_PTEX_MASK_LIT 10 #define POLYTYPE_ATEX_TRANS 11 #define POLYTYPE_PTEX_TRANS 12 #define POLYTYPE_ATEX_MASK_TRANS 13 #define POLYTYPE_PTEX_MASK_TRANS 14 #define POLYTYPE_MAX 15 #define POLYTYPE_ZBUF 16 AL_VAR(float, scene_gap); AL_FUNC(void, _soft_polygon3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[])); AL_FUNC(void, _soft_polygon3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[])); AL_FUNC(void, _soft_triangle3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)); AL_FUNC(void, _soft_triangle3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)); AL_FUNC(void, _soft_quad3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)); AL_FUNC(void, _soft_quad3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)); AL_FUNC(int, clip3d, (int type, fixed min_z, fixed max_z, int vc, AL_CONST V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[])); AL_FUNC(int, clip3d_f, (int type, float min_z, float max_z, int vc, AL_CONST V3D_f *vtx[], V3D_f *vout[], V3D_f *vtmp[], int out[])); AL_FUNC(fixed, polygon_z_normal, (AL_CONST V3D *v1, AL_CONST V3D *v2, AL_CONST V3D *v3)); AL_FUNC(float, polygon_z_normal_f, (AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, AL_CONST V3D_f *v3)); /* Note: You are not supposed to mix ZBUFFER with BITMAP even though it is * currently possible. This is just the internal representation, and it may * change in the future. */ typedef struct BITMAP ZBUFFER; AL_FUNC(ZBUFFER *, create_zbuffer, (struct BITMAP *bmp)); AL_FUNC(ZBUFFER *, create_sub_zbuffer, (ZBUFFER *parent, int x, int y, int width, int height)); AL_FUNC(void, set_zbuffer, (ZBUFFER *zbuf)); AL_FUNC(void, clear_zbuffer, (ZBUFFER *zbuf, float z)); AL_FUNC(void, destroy_zbuffer, (ZBUFFER *zbuf)); AL_FUNC(int, create_scene, (int nedge, int npoly)); AL_FUNC(void, clear_scene, (struct BITMAP* bmp)); AL_FUNC(void, destroy_scene, (void)); AL_FUNC(int, scene_polygon3d, (int type, struct BITMAP *texture, int vx, V3D *vtx[])); AL_FUNC(int, scene_polygon3d_f, (int type, struct BITMAP *texture, int vx, V3D_f *vtx[])); AL_FUNC(void, render_scene, (void)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_3D_H */ allegro-4.4.3.1/include/allegro/unicode.h0000664000175000017500000001164113437077643017152 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Unicode support routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_UNICODE__H #define ALLEGRO_UNICODE__H #include "base.h" #ifdef __cplusplus extern "C" { #endif #define U_ASCII AL_ID('A','S','C','8') #define U_ASCII_CP AL_ID('A','S','C','P') #define U_UNICODE AL_ID('U','N','I','C') #define U_UTF8 AL_ID('U','T','F','8') #define U_CURRENT AL_ID('c','u','r','.') AL_FUNC(void, set_uformat, (int type)); AL_FUNC(int, get_uformat, (void)); AL_FUNC(void, register_uformat, (int type, AL_METHOD(int, u_getc, (AL_CONST char *s)), AL_METHOD(int, u_getx, (char **s)), AL_METHOD(int, u_setc, (char *s, int c)), AL_METHOD(int, u_width, (AL_CONST char *s)), AL_METHOD(int, u_cwidth, (int c)), AL_METHOD(int, u_isok, (int c)), int u_width_max)); AL_FUNC(void, set_ucodepage, (AL_CONST unsigned short *table, AL_CONST unsigned short *extras)); AL_FUNC(int, need_uconvert, (AL_CONST char *s, int type, int newtype)); AL_FUNC(int, uconvert_size, (AL_CONST char *s, int type, int newtype)); AL_FUNC(void, do_uconvert, (AL_CONST char *s, int type, char *buf, int newtype, int size)); AL_FUNC(char *, uconvert, (AL_CONST char *s, int type, char *buf, int newtype, int size)); AL_FUNC(int, uwidth_max, (int type)); #define uconvert_ascii(s, buf) uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)) #define uconvert_toascii(s, buf) uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)) #define EMPTY_STRING "\0\0\0" AL_ARRAY(char, empty_string); AL_FUNCPTR(int, ugetc, (AL_CONST char *s)); AL_FUNCPTR(int, ugetx, (char **s)); AL_FUNCPTR(int, ugetxc, (AL_CONST char **s)); AL_FUNCPTR(int, usetc, (char *s, int c)); AL_FUNCPTR(int, uwidth, (AL_CONST char *s)); AL_FUNCPTR(int, ucwidth, (int c)); AL_FUNCPTR(int, uisok, (int c)); AL_FUNC(int, uoffset, (AL_CONST char *s, int idx)); AL_FUNC(int, ugetat, (AL_CONST char *s, int idx)); AL_FUNC(int, usetat, (char *s, int idx, int c)); AL_FUNC(int, uinsert, (char *s, int idx, int c)); AL_FUNC(int, uremove, (char *s, int idx)); AL_FUNC(int, utolower, (int c)); AL_FUNC(int, utoupper, (int c)); AL_FUNC(int, uisspace, (int c)); AL_FUNC(int, uisdigit, (int c)); AL_FUNC(int, ustrsize, (AL_CONST char *s)); AL_FUNC(int, ustrsizez, (AL_CONST char *s)); AL_FUNC(char *, _ustrdup, (AL_CONST char *src, AL_METHOD(void *, malloc_func, (size_t)))); AL_FUNC(char *, ustrzcpy, (char *dest, int size, AL_CONST char *src)); AL_FUNC(char *, ustrzcat, (char *dest, int size, AL_CONST char *src)); AL_FUNC(int, ustrlen, (AL_CONST char *s)); AL_FUNC(int, ustrcmp, (AL_CONST char *s1, AL_CONST char *s2)); AL_FUNC(char *, ustrzncpy, (char *dest, int size, AL_CONST char *src, int n)); AL_FUNC(char *, ustrzncat, (char *dest, int size, AL_CONST char *src, int n)); AL_FUNC(int, ustrncmp, (AL_CONST char *s1, AL_CONST char *s2, int n)); AL_FUNC(int, ustricmp, (AL_CONST char *s1, AL_CONST char *s2)); AL_FUNC(int, ustrnicmp, (AL_CONST char *s1, AL_CONST char *s2, int n)); AL_FUNC(char *, ustrlwr, (char *s)); AL_FUNC(char *, ustrupr, (char *s)); AL_FUNC(char *, ustrchr, (AL_CONST char *s, int c)); AL_FUNC(char *, ustrrchr, (AL_CONST char *s, int c)); AL_FUNC(char *, ustrstr, (AL_CONST char *s1, AL_CONST char *s2)); AL_FUNC(char *, ustrpbrk, (AL_CONST char *s, AL_CONST char *set)); AL_FUNC(char *, ustrtok, (char *s, AL_CONST char *set)); AL_FUNC(char *, ustrtok_r, (char *s, AL_CONST char *set, char **last)); AL_FUNC(double, uatof, (AL_CONST char *s)); AL_FUNC(long, ustrtol, (AL_CONST char *s, char **endp, int base)); AL_FUNC(double, ustrtod, (AL_CONST char *s, char **endp)); AL_FUNC(AL_CONST char *, ustrerror, (int err)); AL_PRINTFUNC(int, uszprintf, (char *buf, int size, AL_CONST char *format, ...), 3, 4); AL_FUNC(int, uvszprintf, (char *buf, int size, AL_CONST char *format, va_list args)); AL_PRINTFUNC(int, usprintf, (char *buf, AL_CONST char *format, ...), 2, 3); #ifndef ustrdup #ifdef FORTIFY #define ustrdup(src) _ustrdup(src, Fortify_malloc) #else #define ustrdup(src) _ustrdup(src, malloc) #endif #endif #define ustrcpy(dest, src) ustrzcpy(dest, INT_MAX, src) #define ustrcat(dest, src) ustrzcat(dest, INT_MAX, src) #define ustrncpy(dest, src, n) ustrzncpy(dest, INT_MAX, src, n) #define ustrncat(dest, src, n) ustrzncat(dest, INT_MAX, src, n) #define uvsprintf(buf, format, args) uvszprintf(buf, INT_MAX, format, args) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_UNICODE__H */ allegro-4.4.3.1/include/allegro/quat.h0000664000175000017500000000324213437077643016474 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Quaternion routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_QUAT_H #define ALLEGRO_QUAT_H #include "base.h" #ifdef __cplusplus extern "C" { #endif typedef struct QUAT { float w, x, y, z; } QUAT; AL_VAR(QUAT, identity_quat); AL_FUNC(void, quat_mul, (AL_CONST QUAT *p, AL_CONST QUAT *q, QUAT *out)); AL_FUNC(void, get_x_rotate_quat, (QUAT *q, float r)); AL_FUNC(void, get_y_rotate_quat, (QUAT *q, float r)); AL_FUNC(void, get_z_rotate_quat, (QUAT *q, float r)); AL_FUNC(void, get_rotation_quat, (QUAT *q, float x, float y, float z)); AL_FUNC(void, get_vector_rotation_quat, (QUAT *q, float x, float y, float z, float a)); AL_FUNC(void, apply_quat, (AL_CONST QUAT *q, float x, float y, float z, float *xout, float *yout, float *zout)); AL_FUNC(void, quat_slerp, (AL_CONST QUAT *from, AL_CONST QUAT *to, float t, QUAT *out, int how)); #define QUAT_SHORT 0 #define QUAT_LONG 1 #define QUAT_CW 2 #define QUAT_CCW 3 #define QUAT_USER 4 #define quat_interpolate(from, to, t, out) quat_slerp((from), (to), (t), (out), QUAT_SHORT) #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_QUAT_H */ allegro-4.4.3.1/include/allegro/timer.h0000664000175000017500000000512113437077643016640 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Timer routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_TIMER_H #define ALLEGRO_TIMER_H #include "base.h" #ifdef __cplusplus extern "C" { #endif #define TIMERS_PER_SECOND 1193181L #define SECS_TO_TIMER(x) ((long)(x) * TIMERS_PER_SECOND) #define MSEC_TO_TIMER(x) ((long)(x) * (TIMERS_PER_SECOND / 1000)) #define BPS_TO_TIMER(x) (TIMERS_PER_SECOND / (long)(x)) #define BPM_TO_TIMER(x) ((60 * TIMERS_PER_SECOND) / (long)(x)) typedef struct TIMER_DRIVER { int id; AL_CONST char *name; AL_CONST char *desc; AL_CONST char *ascii_name; AL_METHOD(int, init, (void)); AL_METHOD(void, exit, (void)); AL_METHOD(int, install_int, (AL_METHOD(void, proc, (void)), long speed)); AL_METHOD(void, remove_int, (AL_METHOD(void, proc, (void)))); AL_METHOD(int, install_param_int, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); AL_METHOD(void, remove_param_int, (AL_METHOD(void, proc, (void *param)), void *param)); AL_METHOD(int, can_simulate_retrace, (void)); AL_METHOD(void, simulate_retrace, (int enable)); AL_METHOD(void, rest, (unsigned int tyme, AL_METHOD(void, callback, (void)))); } TIMER_DRIVER; AL_VAR(TIMER_DRIVER *, timer_driver); AL_ARRAY(_DRIVER_INFO, _timer_driver_list); AL_FUNC(int, install_timer, (void)); AL_FUNC(void, remove_timer, (void)); AL_FUNC(int, install_int_ex, (AL_METHOD(void, proc, (void)), long speed)); AL_FUNC(int, install_int, (AL_METHOD(void, proc, (void)), long speed)); AL_FUNC(void, remove_int, (AL_METHOD(void, proc, (void)))); AL_FUNC(int, install_param_int_ex, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); AL_FUNC(int, install_param_int, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); AL_FUNC(void, remove_param_int, (AL_METHOD(void, proc, (void *param)), void *param)); AL_VAR(volatile int, retrace_count); AL_FUNC(void, rest, (unsigned int tyme)); AL_FUNC(void, rest_callback, (unsigned int tyme, AL_METHOD(void, callback, (void)))); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_TIMER_H */ allegro-4.4.3.1/include/allegro/datafile.h0000664000175000017500000001136413437077643017277 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Datafile access routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DATAFILE_H #define ALLEGRO_DATAFILE_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; struct PACKFILE; struct RGB; #define DAT_ID(a,b,c,d) AL_ID(a,b,c,d) #define DAT_MAGIC DAT_ID('A','L','L','.') #define DAT_FILE DAT_ID('F','I','L','E') #define DAT_DATA DAT_ID('D','A','T','A') #define DAT_FONT DAT_ID('F','O','N','T') #define DAT_SAMPLE DAT_ID('S','A','M','P') #define DAT_MIDI DAT_ID('M','I','D','I') #define DAT_PATCH DAT_ID('P','A','T',' ') #define DAT_FLI DAT_ID('F','L','I','C') #define DAT_BITMAP DAT_ID('B','M','P',' ') #define DAT_RLE_SPRITE DAT_ID('R','L','E',' ') #define DAT_C_SPRITE DAT_ID('C','M','P',' ') #define DAT_XC_SPRITE DAT_ID('X','C','M','P') #define DAT_PALETTE DAT_ID('P','A','L',' ') #define DAT_PROPERTY DAT_ID('p','r','o','p') #define DAT_NAME DAT_ID('N','A','M','E') #define DAT_END -1 typedef struct DATAFILE_PROPERTY { char *dat; /* pointer to the data */ int type; /* property type */ } DATAFILE_PROPERTY; typedef struct DATAFILE { void *dat; /* pointer to the data */ int type; /* object type */ long size; /* size of the object */ DATAFILE_PROPERTY *prop; /* object properties */ } DATAFILE; typedef struct DATAFILE_INDEX { char *filename; /* datafile name (path) */ long *offset; /* list of offsets */ } DATAFILE_INDEX; AL_FUNC(DATAFILE *, load_datafile, (AL_CONST char *filename)); AL_FUNC(DATAFILE *, load_datafile_callback, (AL_CONST char *filename, AL_METHOD(void, callback, (DATAFILE *)))); AL_FUNC(DATAFILE_INDEX *, create_datafile_index, (AL_CONST char *filename)); AL_FUNC(void, unload_datafile, (DATAFILE *dat)); AL_FUNC(void, destroy_datafile_index, (DATAFILE_INDEX *index)); AL_FUNC(DATAFILE *, load_datafile_object, (AL_CONST char *filename, AL_CONST char *objectname)); AL_FUNC(DATAFILE *, load_datafile_object_indexed, (AL_CONST DATAFILE_INDEX *index, int item)); AL_FUNC(void, unload_datafile_object, (DATAFILE *dat)); AL_FUNC(DATAFILE *, find_datafile_object, (AL_CONST DATAFILE *dat, AL_CONST char *objectname)); AL_FUNC(AL_CONST char *, get_datafile_property, (AL_CONST DATAFILE *dat, int type)); AL_FUNC(void, register_datafile_object, (int id_, AL_METHOD(void *, load, (struct PACKFILE *f, long size)), AL_METHOD(void, destroy, (void *data)))); AL_FUNC(void, fixup_datafile, (DATAFILE *data)); AL_FUNC(struct BITMAP *, load_bitmap, (AL_CONST char *filename, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_bmp, (AL_CONST char *filename, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_bmp_pf, (PACKFILE *f, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_lbm, (AL_CONST char *filename, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_pcx, (AL_CONST char *filename, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_pcx_pf, (PACKFILE *f, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_tga, (AL_CONST char *filename, struct RGB *pal)); AL_FUNC(struct BITMAP *, load_tga_pf, (PACKFILE *f, struct RGB *pal)); AL_FUNC(int, save_bitmap, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(int, save_bmp, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(int, save_bmp_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(int, save_pcx, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(int, save_pcx_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(int, save_tga, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(int, save_tga_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); AL_FUNC(void, register_bitmap_file_type, (AL_CONST char *ext, AL_METHOD(struct BITMAP *, load, (AL_CONST char *filename, struct RGB *pal)), AL_METHOD(int, save, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)))); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_DATAFILE_H */ allegro-4.4.3.1/include/allegro/internal/0000775000175000017500000000000013437077643017164 5ustar siegesiegeallegro-4.4.3.1/include/allegro/internal/aintvga.h0000664000175000017500000000570213437077643020772 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helpers for accessing the VGA hardware registers. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef AINTVGA_H #define AINTVGA_H #ifndef ALLEGRO_H #error must include allegro.h first #endif #ifdef ALLEGRO_GFX_HAS_VGA #ifdef __cplusplus extern "C" { #endif AL_VAR(int, _crtc); AL_FUNC(void, _vga_regs_init, (void)); AL_FUNC(void, _vga_vsync, (void)); AL_FUNC(void, _vga_set_palette_range, (AL_CONST PALETTE p, int from, int to, int do_sync)); AL_FUNC(void, _set_vga_virtual_width, (int old_width, int new_width)); AL_FUNC(uintptr_t, _set_vga_mode, (int modenum)); AL_FUNC(void, _unset_vga_mode, (void)); AL_FUNC(void, _save_vga_mode, (void)); AL_FUNC(void, _restore_vga_mode, (void)); /* reads the current value of a VGA hardware register */ AL_INLINE(int, _read_vga_register, (int port, int idx), { if (port==0x3C0) inportb(_crtc+6); outportb(port, idx); return inportb(port+1); }) /* writes to a VGA hardware register */ AL_INLINE(void, _write_vga_register, (int port, int idx, int v), { if (port==0x3C0) { inportb(_crtc+6); outportb(port, idx); outportb(port, v); } else { outportb(port, idx); outportb(port+1, v); } }) /* alters specific bits of a VGA hardware register */ AL_INLINE(void, _alter_vga_register, (int port, int idx, int mask, int v), { int temp; temp = _read_vga_register(port, idx); temp &= (~mask); temp |= (v & mask); _write_vga_register(port, idx, temp); }) /* waits until the VGA isn't in a horizontal blank */ AL_INLINE(void, _vsync_out_h, (void), { do { } while (inportb(0x3DA) & 1); }) /* waits until the VGA isn't in a vertical blank */ AL_INLINE(void, _vsync_out_v, (void), { do { } while (inportb(0x3DA) & 8); }) /* waits until the VGA is in a vertical blank */ AL_INLINE(void, _vsync_in, (void), { if (_timer_use_retrace) { int t = retrace_count; do { } while (t == retrace_count); } else { do { } while (!(inportb(0x3DA) & 8)); } }) /* modifies the VGA pelpan register */ AL_INLINE(void, _write_hpp, (int value), { if (_timer_use_retrace) { _retrace_hpp_value = value; do { } while (_retrace_hpp_value == value); } else { do { } while (!(inportb(0x3DA) & 8)); _write_vga_register(0x3C0, 0x33, value); } }) #ifdef __cplusplus } #endif #endif /* ifdef ALLEGRO_GFX_HAS_VGA */ #endif /* ifndef AINTVGA_H */ allegro-4.4.3.1/include/allegro/internal/aintern.h0000664000175000017500000016671213437077643021012 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some definitions for internal use by the library code. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef AINTERN_H #define AINTERN_H #ifndef ALLEGRO_H #error must include allegro.h first #endif #ifdef __cplusplus extern "C" { #endif /* length in bytes of the cpu_vendor string */ #define _AL_CPU_VENDOR_SIZE 32 /* flag for how many times we have been initialised */ AL_VAR(int, _allegro_count); /* flag to know whether we are being called by the exit mechanism */ AL_VAR(int, _allegro_in_exit); /* flag to decide whether to disable the screensaver */ enum { NEVER_DISABLED, FULLSCREEN_DISABLED, ALWAYS_DISABLED }; AL_VAR(int, _screensaver_policy); AL_FUNCPTR(int, _al_trace_handler, (AL_CONST char *msg)); /* malloc wrappers */ /* The 4.3 branch uses the following macro names to allow the user to customise * the memory management routines. We don't have that feature in 4.2, but we * use the same macros names in order to reduce divergence of the codebases. */ #define _AL_MALLOC(SIZE) (_al_malloc(SIZE)) #define _AL_MALLOC_ATOMIC(SIZE) (_al_malloc(SIZE)) #define _AL_FREE(PTR) (_al_free(PTR)) #define _AL_REALLOC(PTR, SIZE) (_al_realloc(PTR, SIZE)) AL_FUNC(void *, _al_malloc, (size_t size)); AL_FUNC(void, _al_free, (void *mem)); AL_FUNC(void *, _al_realloc, (void *mem, size_t size)); AL_FUNC(char *, _al_strdup, (AL_CONST char *string)); AL_FUNC(char *, _al_ustrdup, (AL_CONST char *string)); /* some Allegro functions need a block of scratch memory */ AL_VAR(void *, _scratch_mem); AL_VAR(int, _scratch_mem_size); AL_INLINE(void, _grow_scratch_mem, (int size), { if (size > _scratch_mem_size) { size = (size+1023) & 0xFFFFFC00; _scratch_mem = _AL_REALLOC(_scratch_mem, size); _scratch_mem_size = size; } }) /* list of functions to call at program cleanup */ AL_FUNC(void, _add_exit_func, (AL_METHOD(void, func, (void)), AL_CONST char *desc)); AL_FUNC(void, _remove_exit_func, (AL_METHOD(void, func, (void)))); /* helper structure for talking to Unicode strings */ typedef struct UTYPE_INFO { int id; AL_METHOD(int, u_getc, (AL_CONST char *s)); AL_METHOD(int, u_getx, (char **s)); AL_METHOD(int, u_setc, (char *s, int c)); AL_METHOD(int, u_width, (AL_CONST char *s)); AL_METHOD(int, u_cwidth, (int c)); AL_METHOD(int, u_isok, (int c)); int u_width_max; } UTYPE_INFO; AL_FUNC(UTYPE_INFO *, _find_utype, (int type)); /* message stuff */ #define ALLEGRO_MESSAGE_SIZE 4096 /* wrappers for implementing disk I/O on different platforms */ AL_FUNC(int, _al_file_isok, (AL_CONST char *filename)); AL_FUNC(uint64_t, _al_file_size_ex, (AL_CONST char *filename)); AL_FUNC(time_t, _al_file_time, (AL_CONST char *filename)); AL_FUNC(int, _al_drive_exists, (int drive)); AL_FUNC(int, _al_getdrive, (void)); AL_FUNC(void, _al_getdcwd, (int drive, char *buf, int size)); AL_FUNC(void, _al_detect_filename_encoding, (void)); /* obsolete; only exists for binary compatibility with 4.2.0 */ AL_FUNC(long, _al_file_size, (AL_CONST char *filename)); /* packfile stuff */ AL_VAR(int, _packfile_filesize); AL_VAR(int, _packfile_datasize); AL_VAR(int, _packfile_type); AL_FUNC(PACKFILE *, _pack_fdopen, (int fd, AL_CONST char *mode)); AL_FUNC(int, _al_lzss_incomplete_state, (AL_CONST LZSS_UNPACK_DATA *dat)); /* config stuff */ void _reload_config(void); /* various bits of mouse stuff */ AL_FUNC(void, _handle_mouse_input, (void)); AL_VAR(int, _mouse_x); AL_VAR(int, _mouse_y); AL_VAR(int, _mouse_z); AL_VAR(int, _mouse_w); AL_VAR(int, _mouse_b); AL_VAR(int, _mouse_on); AL_VAR(int, _mouse_installed); AL_VAR(int, _mouse_type); AL_VAR(BITMAP *, _mouse_screen); AL_VAR(BITMAP *, _mouse_pointer); /* various bits of timer stuff */ AL_FUNC(long, _handle_timer_tick, (int interval)); #define MAX_TIMERS 16 /* list of active timer handlers */ typedef struct TIMER_QUEUE { AL_METHOD(void, proc, (void)); /* timer handler functions */ AL_METHOD(void, param_proc, (void *param)); void *param; /* param for param_proc if used */ long speed; /* timer speed */ long counter; /* counts down to zero=blastoff */ } TIMER_QUEUE; AL_ARRAY(TIMER_QUEUE, _timer_queue); AL_VAR(int, _timer_installed); AL_VAR(int, _timer_use_retrace); AL_VAR(volatile int, _retrace_hpp_value); AL_VAR(long, _vsync_speed); /* various bits of keyboard stuff */ AL_FUNC(void, _handle_key_press, (int keycode, int scancode)); AL_FUNC(void, _handle_key_release, (int scancode)); AL_VAR(int, _keyboard_installed); AL_ARRAY(AL_CONST char *, _keyboard_common_names); AL_ARRAY(volatile char, _key); AL_VAR(volatile int, _key_shifts); #if (defined ALLEGRO_DOS) || (defined ALLEGRO_DJGPP) || (defined ALLEGRO_WATCOM) || \ (defined ALLEGRO_QNX) || (defined ALLEGRO_BEOS) || (defined ALLEGRO_HAIKU) AL_ARRAY(char *, _pckeys_names); AL_FUNC(void, _pckeys_init, (void)); AL_FUNC(void, _handle_pckey, (int code)); AL_FUNC(int, _pckey_scancode_to_ascii, (int scancode)); AL_FUNC(AL_CONST char *, _pckey_scancode_to_name, (int scancode)); AL_VAR(unsigned short *, _key_ascii_table); AL_VAR(unsigned short *, _key_capslock_table); AL_VAR(unsigned short *, _key_shift_table); AL_VAR(unsigned short *, _key_control_table); AL_VAR(unsigned short *, _key_altgr_lower_table); AL_VAR(unsigned short *, _key_altgr_upper_table); AL_VAR(unsigned short *, _key_accent1_lower_table); AL_VAR(unsigned short *, _key_accent1_upper_table); AL_VAR(unsigned short *, _key_accent2_lower_table); AL_VAR(unsigned short *, _key_accent2_upper_table); AL_VAR(unsigned short *, _key_accent3_lower_table); AL_VAR(unsigned short *, _key_accent3_upper_table); AL_VAR(unsigned short *, _key_accent4_lower_table); AL_VAR(unsigned short *, _key_accent4_upper_table); AL_VAR(int, _key_accent1); AL_VAR(int, _key_accent2); AL_VAR(int, _key_accent3); AL_VAR(int, _key_accent4); AL_VAR(int, _key_accent1_flag); AL_VAR(int, _key_accent2_flag); AL_VAR(int, _key_accent3_flag); AL_VAR(int, _key_accent4_flag); AL_VAR(int, _key_standard_kb); AL_VAR(char *, _keyboard_layout); #endif #if (defined ALLEGRO_WINDOWS) AL_FUNC(int, _al_win_open, (const char *filename, int mode, int perm)); AL_FUNC(int, _al_win_unlink, (const char *filename)); #define _al_open(filename, mode, perm) _al_win_open(filename, mode, perm) #define _al_unlink(filename) _al_win_unlink(filename) #else #define _al_open(filename, mode, perm) open(filename, mode, perm) #define _al_unlink(filename) unlink(filename) #endif /* various bits of joystick stuff */ AL_VAR(int, _joy_type); AL_VAR(int, _joystick_installed); /* some GUI innards that other people need to use */ AL_FUNC(int, _gui_shadow_box_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, _gui_ctext_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, _gui_button_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, _gui_edit_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, _gui_list_proc, (int msg, DIALOG *d, int c)); AL_FUNC(int, _gui_text_list_proc, (int msg, DIALOG *d, int c)); AL_FUNC(void, _handle_scrollable_scroll_click, (DIALOG *d, int listsize, int *offset, int height)); AL_FUNC(void, _handle_scrollable_scroll, (DIALOG *d, int listsize, int *idx, int *offset)); AL_FUNC(void, _handle_listbox_click, (DIALOG *d)); AL_FUNC(void, _draw_scrollable_frame, (DIALOG *d, int listsize, int offset, int height, int fg_color, int bg)); AL_FUNC(void, _draw_listbox, (DIALOG *d)); AL_FUNC(void, _draw_textbox, (char *thetext, int *listsize, int draw, int offset, int wword, int tabsize, int x, int y, int w, int h, int disabled, int fore, int deselect, int disable)); /* text- and font-related stuff */ typedef struct FONT_VTABLE { AL_METHOD(int, font_height, (AL_CONST FONT *f)); AL_METHOD(int, char_length, (AL_CONST FONT *f, int ch)); AL_METHOD(int, text_length, (AL_CONST FONT *f, AL_CONST char *text)); AL_METHOD(int, render_char, (AL_CONST FONT *f, int ch, int fg, int bg, BITMAP *bmp, int x, int y)); AL_METHOD(void, render, (AL_CONST FONT *f, AL_CONST char *text, int fg, int bg, BITMAP *bmp, int x, int y)); AL_METHOD(void, destroy, (FONT *f)); AL_METHOD(int, get_font_ranges, (FONT *f)); AL_METHOD(int, get_font_range_begin, (FONT *f, int range)); AL_METHOD(int, get_font_range_end, (FONT *f, int range)); AL_METHOD(FONT *, extract_font_range, (FONT *f, int begin, int end)); AL_METHOD(FONT *, merge_fonts, (FONT *f1, FONT *f2)); AL_METHOD(int, transpose_font, (FONT *f, int drange)); } FONT_VTABLE; AL_VAR(FONT_VTABLE, _font_vtable_mono); AL_VAR(FONT_VTABLE *, font_vtable_mono); AL_VAR(FONT_VTABLE, _font_vtable_color); AL_VAR(FONT_VTABLE *, font_vtable_color); AL_VAR(FONT_VTABLE, _font_vtable_trans); AL_VAR(FONT_VTABLE *, font_vtable_trans); AL_FUNC(FONT_GLYPH *, _mono_find_glyph, (AL_CONST FONT *f, int ch)); AL_FUNC(BITMAP *, _color_find_glyph, (AL_CONST FONT *f, int ch)); typedef struct FONT_MONO_DATA { int begin, end; /* first char and one-past-the-end char */ FONT_GLYPH **glyphs; /* our glyphs */ struct FONT_MONO_DATA *next; /* linked list structure */ } FONT_MONO_DATA; typedef struct FONT_COLOR_DATA { int begin, end; /* first char and one-past-the-end char */ BITMAP **bitmaps; /* our glyphs */ struct FONT_COLOR_DATA *next; /* linked list structure */ } FONT_COLOR_DATA; /* caches and tables for svga bank switching */ AL_VAR(int, _last_bank_1); AL_VAR(int, _last_bank_2); AL_VAR(int *, _gfx_bank); /* bank switching routines (these use a non-C calling convention on i386!) */ AL_FUNC(uintptr_t, _stub_bank_switch, (BITMAP *bmp, int lyne)); AL_FUNC(void, _stub_unbank_switch, (BITMAP *bmp)); AL_FUNC(void, _stub_bank_switch_end, (void)); #ifdef ALLEGRO_GFX_HAS_VGA AL_FUNC(uintptr_t, _x_bank_switch, (BITMAP *bmp, int lyne)); AL_FUNC(void, _x_unbank_switch, (BITMAP *bmp)); AL_FUNC(void, _x_bank_switch_end, (void)); #endif #ifdef ALLEGRO_GFX_HAS_VBEAF AL_FUNC(void, _accel_bank_stub, (void)); AL_FUNC(void, _accel_bank_stub_end, (void)); AL_FUNC(void, _accel_bank_switch, (void)); AL_FUNC(void, _accel_bank_switch_end, (void)); AL_VAR(void *, _accel_driver); AL_VAR(int, _accel_active); AL_VAR(void *, _accel_set_bank); AL_VAR(void *, _accel_idle); AL_FUNC(void, _fill_vbeaf_libc_exports, (void *ptr)); AL_FUNC(void, _fill_vbeaf_pmode_exports, (void *ptr)); #endif /* stuff for setting up bitmaps */ AL_FUNC(BITMAP *, _make_bitmap, (int w, int h, uintptr_t addr, GFX_DRIVER *driver, int color_depth, int bpl)); AL_FUNC(void, _sort_out_virtual_width, (int *width, GFX_DRIVER *driver)); AL_FUNC(GFX_VTABLE *, _get_vtable, (int color_depth)); AL_VAR(GFX_VTABLE, _screen_vtable); AL_VAR(int, _gfx_mode_set_count); AL_VAR(int, _refresh_rate_request); AL_FUNC(void, _set_current_refresh_rate, (int rate)); AL_VAR(int, _wait_for_vsync); AL_VAR(int, _sub_bitmap_id_count); AL_VAR(int, _screen_split_position); AL_VAR(int, _safe_gfx_mode_change); #ifdef ALLEGRO_I386 #define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) #else #ifdef ALLEGRO_MPW /* in Mac 24 bit is a unsigned long */ #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ : (((bpp) <= 16) ? 2 \ : 4)) #else #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ : (((bpp) <= 16) ? 2 \ : (((bpp) <= 24) ? 3 : 4))) #endif #endif AL_FUNC(int, _color_load_depth, (int depth, int hasalpha)); AL_VAR(int, _color_conv); AL_FUNC(BITMAP *, _fixup_loaded_bitmap, (BITMAP *bmp, PALETTE pal, int bpp)); AL_FUNC(int, _bitmap_has_alpha, (BITMAP *bmp)); /* default truecolor pixel format */ #define DEFAULT_RGB_R_SHIFT_15 0 #define DEFAULT_RGB_G_SHIFT_15 5 #define DEFAULT_RGB_B_SHIFT_15 10 #define DEFAULT_RGB_R_SHIFT_16 0 #define DEFAULT_RGB_G_SHIFT_16 5 #define DEFAULT_RGB_B_SHIFT_16 11 #define DEFAULT_RGB_R_SHIFT_24 0 #define DEFAULT_RGB_G_SHIFT_24 8 #define DEFAULT_RGB_B_SHIFT_24 16 #define DEFAULT_RGB_R_SHIFT_32 0 #define DEFAULT_RGB_G_SHIFT_32 8 #define DEFAULT_RGB_B_SHIFT_32 16 #define DEFAULT_RGB_A_SHIFT_32 24 /* display switching support */ AL_FUNC(void, _switch_in, (void)); AL_FUNC(void, _switch_out, (void)); AL_FUNC(void, _register_switch_bitmap, (BITMAP *bmp, BITMAP *parent)); AL_FUNC(void, _unregister_switch_bitmap, (BITMAP *bmp)); AL_FUNC(void, _save_switch_state, (int switch_mode)); AL_FUNC(void, _restore_switch_state, (void)); AL_VAR(int, _dispsw_status); /* current drawing mode */ AL_VAR(int, _drawing_mode); AL_VAR(BITMAP *, _drawing_pattern); AL_VAR(int, _drawing_x_anchor); AL_VAR(int, _drawing_y_anchor); AL_VAR(unsigned int, _drawing_x_mask); AL_VAR(unsigned int, _drawing_y_mask); AL_FUNCPTR(int *, _palette_expansion_table, (int bpp)); AL_VAR(int, _color_depth); AL_VAR(int, _current_palette_changed); AL_VAR(PALETTE, _prev_current_palette); AL_VAR(int, _got_prev_current_palette); AL_ARRAY(int, _palette_color8); AL_ARRAY(int, _palette_color15); AL_ARRAY(int, _palette_color16); AL_ARRAY(int, _palette_color24); AL_ARRAY(int, _palette_color32); /* truecolor blending functions */ AL_VAR(BLENDER_FUNC, _blender_func15); AL_VAR(BLENDER_FUNC, _blender_func16); AL_VAR(BLENDER_FUNC, _blender_func24); AL_VAR(BLENDER_FUNC, _blender_func32); AL_VAR(BLENDER_FUNC, _blender_func15x); AL_VAR(BLENDER_FUNC, _blender_func16x); AL_VAR(BLENDER_FUNC, _blender_func24x); AL_VAR(int, _blender_col_15); AL_VAR(int, _blender_col_16); AL_VAR(int, _blender_col_24); AL_VAR(int, _blender_col_32); AL_VAR(int, _blender_alpha); AL_FUNC(unsigned long, _blender_black, (unsigned long x, unsigned long y, unsigned long n)); #ifdef ALLEGRO_COLOR16 AL_FUNC(unsigned long, _blender_trans15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_add15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_burn15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_color15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_difference15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_dissolve15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_dodge15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_hue15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_invert15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_luminance15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_multiply15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_saturation15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_screen15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_trans16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_add16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_burn16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_color16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_difference16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_dissolve16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_dodge16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_hue16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_invert16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_luminance16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_multiply16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_saturation16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_screen16, (unsigned long x, unsigned long y, unsigned long n)); #endif #if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) AL_FUNC(unsigned long, _blender_trans24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_add24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_burn24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_color24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_difference24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_dissolve24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_dodge24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_hue24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_invert24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_luminance24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_multiply24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_saturation24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_screen24, (unsigned long x, unsigned long y, unsigned long n)); #endif AL_FUNC(unsigned long, _blender_alpha15, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_alpha16, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_alpha24, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_alpha32, (unsigned long x, unsigned long y, unsigned long n)); AL_FUNC(unsigned long, _blender_write_alpha, (unsigned long x, unsigned long y, unsigned long n)); /* graphics drawing routines */ AL_FUNC(void, _normal_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_FUNC(void, _fast_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); AL_FUNC(void, _normal_rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); #ifdef ALLEGRO_COLOR8 AL_FUNC(int, _linear_getpixel8, (BITMAP *bmp, int x, int y)); AL_FUNC(void, _linear_putpixel8, (BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, _linear_vline8, (BITMAP *bmp, int x, int y_1, int y2, int color)); AL_FUNC(void, _linear_hline8, (BITMAP *bmp, int x1, int y, int x2, int color)); AL_FUNC(void, _linear_draw_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_ex8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); AL_FUNC(void, _linear_draw_sprite_v_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_h_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_vh_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_character8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); AL_FUNC(void, _linear_draw_glyph8, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); AL_FUNC(void, _linear_blit8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_blit_backward8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_masked_blit8, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_clear_to_color8, (BITMAP *bitmap, int color)); #endif #ifdef ALLEGRO_COLOR16 AL_FUNC(void, _linear_putpixel15, (BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, _linear_vline15, (BITMAP *bmp, int x, int y_1, int y2, int color)); AL_FUNC(void, _linear_hline15, (BITMAP *bmp, int x1, int y, int x2, int color)); AL_FUNC(void, _linear_draw_trans_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rgba_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_FUNC(int, _linear_getpixel16, (BITMAP *bmp, int x, int y)); AL_FUNC(void, _linear_putpixel16, (BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, _linear_vline16, (BITMAP *bmp, int x, int y_1, int y2, int color)); AL_FUNC(void, _linear_hline16, (BITMAP *bmp, int x1, int y, int x2, int color)); AL_FUNC(void, _linear_draw_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_ex16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); AL_FUNC(void, _linear_draw_256_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_v_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_h_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_vh_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rgba_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_character16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); AL_FUNC(void, _linear_draw_glyph16, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); AL_FUNC(void, _linear_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_blit_backward16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_masked_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_clear_to_color16, (BITMAP *bitmap, int color)); #endif #ifdef ALLEGRO_COLOR24 AL_FUNC(int, _linear_getpixel24, (BITMAP *bmp, int x, int y)); AL_FUNC(void, _linear_putpixel24, (BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, _linear_vline24, (BITMAP *bmp, int x, int y_1, int y2, int color)); AL_FUNC(void, _linear_hline24, (BITMAP *bmp, int x1, int y, int x2, int color)); AL_FUNC(void, _linear_draw_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_ex24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); AL_FUNC(void, _linear_draw_256_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_v_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_h_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_vh_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rgba_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_character24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); AL_FUNC(void, _linear_draw_glyph24, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); AL_FUNC(void, _linear_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_blit_backward24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_masked_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_clear_to_color24, (BITMAP *bitmap, int color)); #endif #ifdef ALLEGRO_COLOR32 AL_FUNC(int, _linear_getpixel32, (BITMAP *bmp, int x, int y)); AL_FUNC(void, _linear_putpixel32, (BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, _linear_vline32, (BITMAP *bmp, int x, int y_1, int y2, int color)); AL_FUNC(void, _linear_hline32, (BITMAP *bmp, int x1, int y, int x2, int color)); AL_FUNC(void, _linear_draw_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_ex32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)); AL_FUNC(void, _linear_draw_256_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_v_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_h_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_sprite_vh_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_trans_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _linear_draw_lit_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_FUNC(void, _linear_draw_character32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); AL_FUNC(void, _linear_draw_glyph32, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); AL_FUNC(void, _linear_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_blit_backward32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_masked_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _linear_clear_to_color32, (BITMAP *bitmap, int color)); #endif #ifdef ALLEGRO_GFX_HAS_VGA AL_FUNC(int, _x_getpixel, (BITMAP *bmp, int x, int y)); AL_FUNC(void, _x_putpixel, (BITMAP *bmp, int x, int y, int color)); AL_FUNC(void, _x_vline, (BITMAP *bmp, int x, int y_1, int y2, int color)); AL_FUNC(void, _x_hline, (BITMAP *bmp, int x1, int y, int x2, int color)); AL_FUNC(void, _x_draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _x_draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _x_draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _x_draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _x_draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); AL_FUNC(void, _x_draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); AL_FUNC(void, _x_draw_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _x_draw_trans_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); AL_FUNC(void, _x_draw_lit_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); AL_FUNC(void, _x_draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); AL_FUNC(void, _x_draw_glyph, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); AL_FUNC(void, _x_blit_from_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _x_blit_to_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _x_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _x_blit_forward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _x_blit_backward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _x_masked_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); AL_FUNC(void, _x_clear_to_color, (BITMAP *bitmap, int color)); #endif /* color conversion routines */ typedef struct GRAPHICS_RECT { int width; int height; int pitch; void *data; } GRAPHICS_RECT; typedef void (COLORCONV_BLITTER_FUNC)(GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect); AL_FUNC(COLORCONV_BLITTER_FUNC *, _get_colorconv_blitter, (int from_depth, int to_depth)); AL_FUNC(void, _release_colorconv_blitter, (COLORCONV_BLITTER_FUNC *blitter)); AL_FUNC(void, _set_colorconv_palette, (AL_CONST struct RGB *p, int from, int to)); AL_FUNC(unsigned char *, _get_colorconv_map, (void)); #ifdef ALLEGRO_COLOR8 AL_FUNC(void, _colorconv_blit_8_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_8_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_8_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_8_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_8_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif #ifdef ALLEGRO_COLOR16 AL_FUNC(void, _colorconv_blit_15_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_15_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_15_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_15_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_16_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_16_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_16_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_16_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif #ifdef ALLEGRO_COLOR24 AL_FUNC(void, _colorconv_blit_24_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_24_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_24_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_24_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif #ifdef ALLEGRO_COLOR32 AL_FUNC(void, _colorconv_blit_32_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_32_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_32_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorconv_blit_32_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif /* color copy routines */ #ifndef ALLEGRO_NO_COLORCOPY #ifdef ALLEGRO_COLOR16 AL_FUNC(void, _colorcopy_blit_15_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); AL_FUNC(void, _colorcopy_blit_16_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif #ifdef ALLEGRO_COLOR24 AL_FUNC(void, _colorcopy_blit_24_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif #ifdef ALLEGRO_COLOR32 AL_FUNC(void, _colorcopy_blit_32_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); #endif #endif /* generic color conversion blitter */ AL_FUNC(void, _blit_between_formats, (BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)); /* asm helper for stretch_blit() */ #ifndef SCAN_EXPORT AL_FUNC(void, _do_stretch, (BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth)); #endif /* lower level functions for rotation */ AL_FUNC(void, _parallelogram_map, (BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy), int sub_pixel_accuracy)); AL_FUNC(void, _parallelogram_map_standard, (BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4])); AL_FUNC(void, _rotate_scale_flip_coordinates, (fixed w, fixed h, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale_x, fixed scale_y, int h_flip, int v_flip, fixed xs[4], fixed ys[4])); AL_FUNC(void, _pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); /* number of fractional bits used by the polygon rasteriser */ #define POLYGON_FIX_SHIFT 18 /* bitfield specifying which polygon attributes need interpolating */ #define INTERP_FLAT 1 /* no interpolation */ #define INTERP_1COL 2 /* gcol or alpha */ #define INTERP_3COL 4 /* grgb */ #define INTERP_FIX_UV 8 /* atex */ #define INTERP_Z 16 /* always in scene3d */ #define INTERP_FLOAT_UV 32 /* ptex */ #define OPT_FLOAT_UV_TO_FIX 64 /* translate ptex to atex */ #define COLOR_TO_RGB 128 /* grgb to gcol for truecolor */ #define INTERP_ZBUF 256 /* z-buffered */ #define INTERP_THRU 512 /* any kind of transparent */ #define INTERP_NOSOLID 1024 /* non-solid modes for 8-bit flat */ #define INTERP_BLEND 2048 /* lit for truecolor */ #define INTERP_TRANS 4096 /* trans for truecolor */ /* information for polygon scanline fillers */ typedef struct POLYGON_SEGMENT { fixed u, v, du, dv; /* fixed point u/v coordinates */ fixed c, dc; /* single color gouraud shade values */ fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ float z, dz; /* polygon depth (1/z) */ float fu, fv, dfu, dfv; /* floating point u/v coordinates */ unsigned char *texture; /* the texture map */ int umask, vmask, vshift; /* texture map size information */ int seg; /* destination bitmap selector */ uintptr_t zbuf_addr; /* Z-buffer address */ uintptr_t read_addr; /* reading address for transparency modes */ } POLYGON_SEGMENT; /* prototype for the scanline filler functions */ typedef AL_METHOD(void, SCANLINE_FILLER, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); /* an active polygon edge */ typedef struct POLYGON_EDGE { int top; /* top y position */ int bottom; /* bottom y position */ fixed x, dx; /* fixed point x position and gradient */ fixed w; /* width of line segment */ POLYGON_SEGMENT dat; /* texture/gouraud information */ struct POLYGON_EDGE *prev; /* doubly linked list */ struct POLYGON_EDGE *next; struct POLYGON_INFO *poly; /* father polygon */ } POLYGON_EDGE; typedef struct POLYGON_INFO /* a polygon waiting rendering */ { struct POLYGON_INFO *next, *prev;/* double linked list */ int inside; /* flag for "scanlining" */ int flags; /* INTERP_* flags */ int color; /* vtx[0]->c */ float a, b, c; /* plane's coefficients -a/d, -b/d, -c/d */ int dmode; /* drawing mode */ BITMAP *dpat; /* drawing pattern */ int xanchor, yanchor; /* for dpat */ int alpha; /* blender alpha */ int b15, b16, b24, b32; /* blender colors */ COLOR_MAP *cmap; /* trans color map */ SCANLINE_FILLER drawer; /* scanline drawing functions */ SCANLINE_FILLER alt_drawer; POLYGON_EDGE *left_edge; /* true edges used in interpolation */ POLYGON_EDGE *right_edge; POLYGON_SEGMENT info; /* base information for scanline functions */ } POLYGON_INFO; /* global variable for z-buffer */ AL_VAR(BITMAP *, _zbuffer); /* polygon helper functions */ AL_VAR(SCANLINE_FILLER, _optim_alternative_drawer); AL_FUNC(POLYGON_EDGE *, _add_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x)); AL_FUNC(POLYGON_EDGE *, _remove_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge)); AL_FUNC(int, _fill_3d_edge_structure, (POLYGON_EDGE *edge, AL_CONST V3D *v1, AL_CONST V3D *v2, int flags, BITMAP *bmp)); AL_FUNC(int, _fill_3d_edge_structure_f, (POLYGON_EDGE *edge, AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, int flags, BITMAP *bmp)); AL_FUNC(SCANLINE_FILLER, _get_scanline_filler, (int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp)); AL_FUNC(void, _clip_polygon_segment, (POLYGON_SEGMENT *info, fixed gap, int flags)); AL_FUNC(void, _clip_polygon_segment_f, (POLYGON_SEGMENT *info, int gap, int flags)); /* polygon scanline filler functions */ AL_FUNC(void, _poly_scanline_dummy, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #ifdef ALLEGRO_COLOR8 AL_FUNC(void, _poly_scanline_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #ifndef SCAN_EXPORT AL_FUNC(void, _poly_scanline_grgb8x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif AL_FUNC(void, _poly_zbuf_flat8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif #ifdef ALLEGRO_COLOR16 AL_FUNC(void, _poly_scanline_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #ifndef SCAN_EXPORT AL_FUNC(void, _poly_scanline_grgb15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif AL_FUNC(void, _poly_zbuf_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #ifndef SCAN_EXPORT AL_FUNC(void, _poly_scanline_grgb16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif AL_FUNC(void, _poly_zbuf_flat16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif #ifdef ALLEGRO_COLOR24 AL_FUNC(void, _poly_scanline_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #ifndef SCAN_EXPORT AL_FUNC(void, _poly_scanline_grgb24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif AL_FUNC(void, _poly_zbuf_flat24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif #ifdef ALLEGRO_COLOR32 AL_FUNC(void, _poly_scanline_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #ifndef SCAN_EXPORT AL_FUNC(void, _poly_scanline_grgb32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_atex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_scanline_ptex_mask_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif AL_FUNC(void, _poly_zbuf_flat32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); AL_FUNC(void, _poly_zbuf_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); #endif /* sound lib stuff */ AL_VAR(MIDI_DRIVER, _midi_none); AL_VAR(int, _digi_volume); AL_VAR(int, _midi_volume); AL_VAR(int, _sound_flip_pan); AL_VAR(int, _sound_hq); AL_VAR(int, _sound_stereo); AL_VAR(int, _sound_bits); AL_VAR(int, _sound_freq); AL_VAR(int, _sound_port); AL_VAR(int, _sound_dma); AL_VAR(int, _sound_irq); AL_VAR(int, _sound_installed); AL_VAR(int, _sound_input_installed); AL_FUNC(int, _midi_allocate_voice, (int min, int max)); AL_VAR(volatile long, _midi_tick); AL_FUNC(int, _digmid_find_patches, (char *dir, int dir_size, char *file, int size_of_file)); #define VIRTUAL_VOICES 256 typedef struct /* a virtual (as seen by the user) soundcard voice */ { AL_CONST SAMPLE *sample; /* which sample are we playing? (NULL = free) */ int num; /* physical voice number (-1 = been killed off) */ int autokill; /* set to free the voice when the sample finishes */ long time; /* when we were started (for voice allocation) */ int priority; /* how important are we? */ } VOICE; typedef struct /* a physical (as used by hardware) soundcard voice */ { int num; /* the virtual voice currently using me (-1 = free) */ int playmode; /* are we looping? */ int vol; /* current volume (fixed point .12) */ int dvol; /* volume delta, for ramping */ int target_vol; /* target volume, for ramping */ int pan; /* current pan (fixed point .12) */ int dpan; /* pan delta, for sweeps */ int target_pan; /* target pan, for sweeps */ int freq; /* current frequency (fixed point .12) */ int dfreq; /* frequency delta, for sweeps */ int target_freq; /* target frequency, for sweeps */ } PHYS_VOICE; AL_ARRAY(PHYS_VOICE, _phys_voice); #define MIXER_DEF_SFX 8 #define MIXER_MAX_SFX 64 AL_FUNC(int, _mixer_init, (int bufsize, int freq, int stereo, int is16bit, int *voices)); AL_FUNC(void, _mixer_exit, (void)); AL_FUNC(void, _mix_some_samples, (uintptr_t buf, unsigned short seg, int issigned)); AL_FUNC(void, _mixer_init_voice, (int voice, AL_CONST SAMPLE *sample)); AL_FUNC(void, _mixer_release_voice, (int voice)); AL_FUNC(void, _mixer_start_voice, (int voice)); AL_FUNC(void, _mixer_stop_voice, (int voice)); AL_FUNC(void, _mixer_loop_voice, (int voice, int loopmode)); AL_FUNC(int, _mixer_get_position, (int voice)); AL_FUNC(void, _mixer_set_position, (int voice, int position)); AL_FUNC(int, _mixer_get_volume, (int voice)); AL_FUNC(void, _mixer_set_volume, (int voice, int volume)); AL_FUNC(void, _mixer_ramp_volume, (int voice, int tyme, int endvol)); AL_FUNC(void, _mixer_stop_volume_ramp, (int voice)); AL_FUNC(int, _mixer_get_frequency, (int voice)); AL_FUNC(void, _mixer_set_frequency, (int voice, int frequency)); AL_FUNC(void, _mixer_sweep_frequency, (int voice, int tyme, int endfreq)); AL_FUNC(void, _mixer_stop_frequency_sweep, (int voice)); AL_FUNC(int, _mixer_get_pan, (int voice)); AL_FUNC(void, _mixer_set_pan, (int voice, int pan)); AL_FUNC(void, _mixer_sweep_pan, (int voice, int tyme, int endpan)); AL_FUNC(void, _mixer_stop_pan_sweep, (int voice)); AL_FUNC(void, _mixer_set_echo, (int voice, int strength, int delay)); AL_FUNC(void, _mixer_set_tremolo, (int voice, int rate, int depth)); AL_FUNC(void, _mixer_set_vibrato, (int voice, int rate, int depth)); AL_FUNC(void, _dummy_noop1, (int p)); AL_FUNC(void, _dummy_noop2, (int p1, int p2)); AL_FUNC(void, _dummy_noop3, (int p1, int p2, int p3)); AL_FUNC(int, _dummy_load_patches, (AL_CONST char *patches, AL_CONST char *drums)); AL_FUNC(void, _dummy_adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); AL_FUNC(void, _dummy_key_on, (int inst, int note, int bend, int vol, int pan)); /* datafile ID's for compatibility with the old datafile format */ #define V1_DAT_MAGIC 0x616C6C2EL #define V1_DAT_DATA 0 #define V1_DAT_FONT 1 #define V1_DAT_BITMAP_16 2 #define V1_DAT_BITMAP_256 3 #define V1_DAT_SPRITE_16 4 #define V1_DAT_SPRITE_256 5 #define V1_DAT_PALETTE_16 6 #define V1_DAT_PALETTE_256 7 #define V1_DAT_FONT_8x8 8 #define V1_DAT_FONT_PROP 9 #define V1_DAT_BITMAP 10 #define V1_DAT_PALETTE 11 #define V1_DAT_SAMPLE 12 #define V1_DAT_MIDI 13 #define V1_DAT_RLE_SPRITE 14 #define V1_DAT_FLI 15 #define V1_DAT_C_SPRITE 16 #define V1_DAT_XC_SPRITE 17 #define OLD_FONT_SIZE 95 #define LESS_OLD_FONT_SIZE 224 /* datafile object loading functions */ AL_FUNC(void, _unload_datafile_object, (DATAFILE *dat)); /* information about a datafile object */ typedef struct DATAFILE_TYPE { int type; AL_METHOD(void *, load, (PACKFILE *f, long size)); AL_METHOD(void, destroy, (void *)); } DATAFILE_TYPE; #define MAX_DATAFILE_TYPES 32 AL_ARRAY(DATAFILE_TYPE, _datafile_type); AL_VAR(int, _compile_sprites); AL_FUNC(void, _construct_datafile, (DATAFILE *data)); /* for readbmp.c */ AL_FUNC(void, _register_bitmap_file_type_init, (void)); /* for readsmp.c */ AL_FUNC(void, _register_sample_file_type_init, (void)); /* for readfont.c */ AL_FUNC(void, _register_font_file_type_init, (void)); /* for module linking system; see comment in allegro.c */ struct _AL_LINKER_MIDI { AL_METHOD(int, init, (void)); AL_METHOD(void, exit, (void)); }; AL_VAR(struct _AL_LINKER_MIDI *, _al_linker_midi); struct _AL_LINKER_MOUSE { AL_METHOD(void, set_mouse_etc, (void)); AL_METHOD(void, show_mouse, (BITMAP *)); BITMAP **mouse_screen_ptr; }; AL_VAR(struct _AL_LINKER_MOUSE *, _al_linker_mouse); /* dynamic driver lists */ AL_FUNC(_DRIVER_INFO *, _create_driver_list, (void)); AL_FUNC(void, _destroy_driver_list, (_DRIVER_INFO *drvlist)); AL_FUNC(void, _driver_list_append_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); AL_FUNC(void, _driver_list_prepend_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); AL_FUNC(void, _driver_list_append_list, (_DRIVER_INFO **drvlist, _DRIVER_INFO *srclist)); /* various libc stuff */ AL_FUNC(void *, _al_sane_realloc, (void *ptr, size_t size)); AL_FUNC(char *, _al_sane_strncpy, (char *dest, const char *src, size_t n)); #define _AL_RAND_MAX 0xFFFF AL_FUNC(void, _al_srand, (int seed)); AL_FUNC(int, _al_rand, (void)); #ifdef __cplusplus } #endif #endif /* ifndef AINTERN_H */ allegro-4.4.3.1/include/allegro/internal/alconfig.h0000664000175000017500000003057213437077643021126 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration defines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ /* which color depths to include? */ #define ALLEGRO_COLOR8 #define ALLEGRO_COLOR16 #define ALLEGRO_COLOR24 #define ALLEGRO_COLOR32 /* for backward compatibility */ #ifdef USE_CONSOLE #define ALLEGRO_NO_MAGIC_MAIN #define ALLEGRO_USE_CONSOLE #endif /* include platform-specific stuff */ #ifndef SCAN_EXPORT #ifndef SCAN_DEPEND #include "allegro/platform/alplatf.h" #endif #if defined ALLEGRO_DJGPP #include "allegro/platform/aldjgpp.h" #elif defined ALLEGRO_WATCOM #include "allegro/platform/alwatcom.h" #elif defined ALLEGRO_MINGW32 #include "allegro/platform/almngw32.h" #elif defined ALLEGRO_DMC #include "allegro/platform/aldmc.h" #elif defined ALLEGRO_BCC32 #include "allegro/platform/albcc32.h" #elif defined ALLEGRO_MSVC #include "allegro/platform/almsvc.h" #elif defined ALLEGRO_HAIKU #include "allegro/platform/albecfg.h" #elif defined ALLEGRO_BEOS #include "allegro/platform/albecfg.h" #elif defined ALLEGRO_MPW #include "allegro/platform/almaccfg.h" #elif defined ALLEGRO_MACOSX #include "allegro/platform/alosxcfg.h" #elif defined ALLEGRO_QNX #include "allegro/platform/alqnxcfg.h" #elif defined ALLEGRO_UNIX #include "allegro/platform/alucfg.h" #elif defined ALLEGRO_PSP #include "allegro/platform/alpspcfg.h" #else #error platform not supported #endif #ifndef SCAN_DEPEND #include "allegro/platform/astdint.h" #endif #endif /* special definitions for the GCC compiler */ #ifdef __GNUC__ #define ALLEGRO_GCC #ifndef AL_INLINE #ifdef __cplusplus #define AL_INLINE(type, name, args, code) \ static inline type name args; \ static inline type name args code /* Needed if this header is included by C99 user code, as * "extern __inline__" is defined differently in C99 (it exports * a new global function symbol). */ #elif __GNUC_STDC_INLINE__ #define AL_INLINE(type, name, args, code) \ extern __inline__ __attribute__((__gnu_inline__)) type name args; \ extern __inline__ __attribute__((__gnu_inline__)) type name args code #else #define AL_INLINE(type, name, args, code) \ extern __inline__ type name args; \ extern __inline__ type name args code #endif #endif #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) __attribute__ ((format (printf, a, b))) #ifndef INLINE #define INLINE __inline__ #endif #if __GNUC__ >= 3 /* SET: According to gcc volatile is ignored for a return type. * I think the code should just ensure that inportb is declared as an * __asm__ __volatile__ macro. If that's the case the extra volatile * doesn't have any sense. */ #define RET_VOLATILE #else #define RET_VOLATILE volatile #endif #ifndef ZERO_SIZE_ARRAY #if __GNUC__ < 3 #define ZERO_SIZE_ARRAY(type, name) __extension__ type name[0] #else #define ZERO_SIZE_ARRAY(type, name) type name[] /* ISO C99 flexible array members */ #endif #endif #ifndef LONG_LONG #define LONG_LONG long long #ifdef ALLEGRO_GUESS_INTTYPES_OK #define int64_t signed long long #define uint64_t unsigned long long #endif #endif #ifdef __i386__ #define ALLEGRO_I386 #ifndef ALLEGRO_NO_ASM #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) #endif #endif #ifdef __amd64__ #define ALLEGRO_AMD64 #ifndef ALLEGRO_NO_ASM #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) #endif #endif #ifdef __arm__ #define ALLEGRO_ARM #endif #ifndef AL_CONST #define AL_CONST const #endif #ifndef AL_FUNC_DEPRECATED #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) #define AL_FUNC_DEPRECATED(type, name, args) AL_FUNC(__attribute__ ((deprecated)) type, name, args) #define AL_PRINTFUNC_DEPRECATED(type, name, args, a, b) AL_PRINTFUNC(__attribute__ ((deprecated)) type, name, args, a, b) #define AL_INLINE_DEPRECATED(type, name, args, code) AL_INLINE(__attribute__ ((deprecated)) type, name, args, code) #endif #endif #ifndef AL_ALIAS #define AL_ALIAS(DECL, CALL) \ static __attribute__((unused)) __inline__ DECL \ { \ return CALL; \ } #endif #ifndef AL_ALIAS_VOID_RET #define AL_ALIAS_VOID_RET(DECL, CALL) \ static __attribute__((unused)) __inline__ void DECL \ { \ CALL; \ } #endif #endif /* use constructor functions, if supported */ #ifdef ALLEGRO_USE_CONSTRUCTOR #define CONSTRUCTOR_FUNCTION(func) func __attribute__ ((constructor)) #define DESTRUCTOR_FUNCTION(func) func __attribute__ ((destructor)) #endif /* the rest of this file fills in some default definitions of language * features and helper functions, which are conditionalised so they will * only be included if none of the above headers defined custom versions. */ #ifndef _AL_SINCOS #define _AL_SINCOS(x, s, c) do { (c) = cos(x); (s) = sin(x); } while (0) #endif #ifndef INLINE #define INLINE #endif #ifndef RET_VOLATILE #define RET_VOLATILE volatile #endif #ifndef ZERO_SIZE_ARRAY #define ZERO_SIZE_ARRAY(type, name) type name[] #endif #ifndef AL_CONST #define AL_CONST #endif #ifndef AL_VAR #define AL_VAR(type, name) extern type name #endif #ifndef AL_ARRAY #define AL_ARRAY(type, name) extern type name[] #endif #ifndef AL_FUNC #define AL_FUNC(type, name, args) type name args #endif #ifndef AL_PRINTFUNC #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) #endif #ifndef AL_METHOD #define AL_METHOD(type, name, args) type (*name) args #endif #ifndef AL_FUNCPTR #define AL_FUNCPTR(type, name, args) extern type (*name) args #endif #ifndef AL_FUNCPTRARRAY #define AL_FUNCPTRARRAY(type, name, args) extern type (*name[]) args #endif #ifndef AL_INLINE #define AL_INLINE(type, name, args, code) type name args; #endif #ifndef AL_FUNC_DEPRECATED #define AL_FUNC_DEPRECATED(type, name, args) AL_FUNC(type, name, args) #define AL_PRINTFUNC_DEPRECATED(type, name, args, a, b) AL_PRINTFUNC(type, name, args, a, b) #define AL_INLINE_DEPRECATED(type, name, args, code) AL_INLINE(type, name, args, code) #endif #ifndef AL_ALIAS #define AL_ALIAS(DECL, CALL) \ static INLINE DECL \ { \ return CALL; \ } #endif #ifndef AL_ALIAS_VOID_RET #define AL_ALIAS_VOID_RET(DECL, CALL) \ static INLINE void DECL \ { \ CALL; \ } #endif #ifndef END_OF_MAIN #define END_OF_MAIN() #endif /* fill in default memory locking macros */ #ifndef END_OF_FUNCTION #define END_OF_FUNCTION(x) #define END_OF_STATIC_FUNCTION(x) #define LOCK_DATA(d, s) #define LOCK_CODE(c, s) #define UNLOCK_DATA(d, s) #define LOCK_VARIABLE(x) #define LOCK_FUNCTION(x) #endif /* fill in default filename behaviour */ #ifndef ALLEGRO_LFN #define ALLEGRO_LFN 1 #endif #if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) #define OTHER_PATH_SEPARATOR '\\' #define DEVICE_SEPARATOR ':' #else #define OTHER_PATH_SEPARATOR '/' #define DEVICE_SEPARATOR '\0' #endif /* emulate the FA_* flags for platforms that don't already have them */ #ifndef FA_RDONLY #define FA_RDONLY 1 #define FA_HIDDEN 2 #define FA_SYSTEM 4 #define FA_LABEL 8 #define FA_DIREC 16 #define FA_ARCH 32 #endif #define FA_NONE 0 #define FA_ALL (~FA_NONE) #ifdef __cplusplus extern "C" { #endif /* emulate missing library functions */ #ifdef ALLEGRO_NO_STRICMP AL_FUNC(int, _alemu_stricmp, (AL_CONST char *s1, AL_CONST char *s2)); #define stricmp _alemu_stricmp #endif #ifdef ALLEGRO_NO_STRLWR AL_FUNC(char *, _alemu_strlwr, (char *string)); #define strlwr _alemu_strlwr #endif #ifdef ALLEGRO_NO_STRUPR AL_FUNC(char *, _alemu_strupr, (char *string)); #define strupr _alemu_strupr #endif #ifdef ALLEGRO_NO_MEMCMP AL_FUNC(int, _alemu_memcmp, (AL_CONST void *s1, AL_CONST void *s2, size_t num)); #define memcmp _alemu_memcmp #endif /* if nobody put them elsewhere, video bitmaps go in regular memory */ #ifndef _video_ds #define _video_ds() _default_ds() #endif /* not many places actually use these, but still worth emulating */ #ifndef ALLEGRO_DJGPP #define _farsetsel(seg) #define _farnspokeb(addr, val) (*((uint8_t *)(addr)) = (val)) #define _farnspokew(addr, val) (*((uint16_t *)(addr)) = (val)) #define _farnspokel(addr, val) (*((uint32_t *)(addr)) = (val)) #define _farnspeekb(addr) (*((uint8_t *)(addr))) #define _farnspeekw(addr) (*((uint16_t *)(addr))) #define _farnspeekl(addr) (*((uint32_t *)(addr))) #endif /* endian-independent 3-byte accessor macros */ #ifdef ALLEGRO_LITTLE_ENDIAN #define READ3BYTES(p) ((*(unsigned char *)(p)) \ | (*((unsigned char *)(p) + 1) << 8) \ | (*((unsigned char *)(p) + 2) << 16)) #define WRITE3BYTES(p,c) ((*(unsigned char *)(p) = (c)), \ (*((unsigned char *)(p) + 1) = (c) >> 8), \ (*((unsigned char *)(p) + 2) = (c) >> 16)) #elif defined ALLEGRO_BIG_ENDIAN #define READ3BYTES(p) ((*(unsigned char *)(p) << 16) \ | (*((unsigned char *)(p) + 1) << 8) \ | (*((unsigned char *)(p) + 2))) #define WRITE3BYTES(p,c) ((*(unsigned char *)(p) = (c) >> 16), \ (*((unsigned char *)(p) + 1) = (c) >> 8), \ (*((unsigned char *)(p) + 2) = (c))) #elif defined SCAN_DEPEND #define READ3BYTES(p) #define WRITE3BYTES(p,c) #else #error endianess not defined #endif /* generic versions of the video memory access helpers */ #ifndef bmp_select #define bmp_select(bmp) #endif #ifndef bmp_write8 #define bmp_write8(addr, c) (*((uint8_t *)(addr)) = (c)) #define bmp_write15(addr, c) (*((uint16_t *)(addr)) = (c)) #define bmp_write16(addr, c) (*((uint16_t *)(addr)) = (c)) #define bmp_write32(addr, c) (*((uint32_t *)(addr)) = (c)) #define bmp_read8(addr) (*((uint8_t *)(addr))) #define bmp_read15(addr) (*((uint16_t *)(addr))) #define bmp_read16(addr) (*((uint16_t *)(addr))) #define bmp_read32(addr) (*((uint32_t *)(addr))) AL_INLINE(int, bmp_read24, (uintptr_t addr), { unsigned char *p = (unsigned char *)addr; int c; c = READ3BYTES(p); return c; }) AL_INLINE(void, bmp_write24, (uintptr_t addr, int c), { unsigned char *p = (unsigned char *)addr; WRITE3BYTES(p, c); }) #endif /* default random function definition */ #ifndef AL_RAND #define AL_RAND() (rand()) #endif #ifdef __cplusplus } #endif /* parameters for the color conversion code */ #if (defined ALLEGRO_WINDOWS) || (defined ALLEGRO_QNX) #define ALLEGRO_COLORCONV_ALIGNED_WIDTH #define ALLEGRO_NO_COLORCOPY #endif allegro-4.4.3.1/include/allegro/alcompat.h0000664000175000017500000001750613437077643017332 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Backward compatibility stuff. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_COMPAT_H #define ALLEGRO_COMPAT_H #ifdef __cplusplus extern "C" { #endif #ifndef ALLEGRO_SRC #ifndef ALLEGRO_NO_CLEAR_BITMAP_ALIAS #if (defined ALLEGRO_GCC) static __attribute__((unused)) __inline__ void clear(BITMAP *bmp) { clear_bitmap(bmp); } #else static INLINE void clear(BITMAP *bmp) { clear_bitmap(bmp); } #endif #endif #endif /* !defined ALLEGRO_SRC */ #define KB_NORMAL 1 #define KB_EXTENDED 2 #define SEND_MESSAGE object_message #define cpu_fpu (cpu_capabilities & CPU_FPU) #define cpu_mmx (cpu_capabilities & CPU_MMX) #define cpu_3dnow (cpu_capabilities & CPU_3DNOW) #define cpu_cpuid (cpu_capabilities & CPU_ID) #define joy_x (joy[0].stick[0].axis[0].pos) #define joy_y (joy[0].stick[0].axis[1].pos) #define joy_left (joy[0].stick[0].axis[0].d1) #define joy_right (joy[0].stick[0].axis[0].d2) #define joy_up (joy[0].stick[0].axis[1].d1) #define joy_down (joy[0].stick[0].axis[1].d2) #define joy_b1 (joy[0].button[0].b) #define joy_b2 (joy[0].button[1].b) #define joy_b3 (joy[0].button[2].b) #define joy_b4 (joy[0].button[3].b) #define joy_b5 (joy[0].button[4].b) #define joy_b6 (joy[0].button[5].b) #define joy_b7 (joy[0].button[6].b) #define joy_b8 (joy[0].button[7].b) #define joy2_x (joy[1].stick[0].axis[0].pos) #define joy2_y (joy[1].stick[0].axis[1].pos) #define joy2_left (joy[1].stick[0].axis[0].d1) #define joy2_right (joy[1].stick[0].axis[0].d2) #define joy2_up (joy[1].stick[0].axis[1].d1) #define joy2_down (joy[1].stick[0].axis[1].d2) #define joy2_b1 (joy[1].button[0].b) #define joy2_b2 (joy[1].button[1].b) #define joy_throttle (joy[0].stick[2].axis[0].pos) #define joy_hat ((joy[0].stick[1].axis[0].d1) ? 1 : \ ((joy[0].stick[1].axis[0].d2) ? 3 : \ ((joy[0].stick[1].axis[1].d1) ? 4 : \ ((joy[0].stick[1].axis[1].d2) ? 2 : \ 0)))) #define JOY_HAT_CENTRE 0 #define JOY_HAT_CENTER 0 #define JOY_HAT_LEFT 1 #define JOY_HAT_DOWN 2 #define JOY_HAT_RIGHT 3 #define JOY_HAT_UP 4 AL_FUNC_DEPRECATED(int, initialise_joystick, (void)); /* in case you want to spell 'palette' as 'pallete' */ #define PALLETE PALETTE #define black_pallete black_palette #define desktop_pallete desktop_palette #define set_pallete set_palette #define get_pallete get_palette #define set_pallete_range set_palette_range #define get_pallete_range get_palette_range #define fli_pallete fli_palette #define pallete_color palette_color #define DAT_PALLETE DAT_PALETTE #define select_pallete select_palette #define unselect_pallete unselect_palette #define generate_332_pallete generate_332_palette #define generate_optimised_pallete generate_optimised_palette /* a pretty vague name */ #define fix_filename_path canonicalize_filename /* the good old file selector */ #define OLD_FILESEL_WIDTH -1 #define OLD_FILESEL_HEIGHT -1 AL_INLINE_DEPRECATED(int, file_select, (AL_CONST char *message, char *path, AL_CONST char *ext), { return file_select_ex(message, path, ext, 1024, OLD_FILESEL_WIDTH, OLD_FILESEL_HEIGHT); }) /* the old (and broken!) file enumeration function */ AL_FUNC_DEPRECATED(int, for_each_file, (AL_CONST char *name, int attrib, AL_METHOD(void, callback, (AL_CONST char *filename, int attrib, int param)), int param)); /* long is 32-bit only on some systems, and we want to list DVDs! */ AL_FUNC_DEPRECATED(long, file_size, (AL_CONST char *filename)); /* the old state-based textout functions */ AL_VAR(int, _textmode); AL_FUNC_DEPRECATED(int, text_mode, (int mode)); AL_INLINE_DEPRECATED(void, textout, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color), { textout_ex(bmp, f, str, x, y, color, _textmode); }) AL_INLINE_DEPRECATED(void, textout_centre, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color), { textout_centre_ex(bmp, f, str, x, y, color, _textmode); }) AL_INLINE_DEPRECATED(void, textout_right, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color), { textout_right_ex(bmp, f, str, x, y, color, _textmode); }) AL_INLINE_DEPRECATED(void, textout_justify, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x1, int x2, int y, int diff, int color), { textout_justify_ex(bmp, f, str, x1, x2, y, diff, color, _textmode); }) AL_PRINTFUNC_DEPRECATED(void, textprintf, (struct BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...), 6, 7); AL_PRINTFUNC_DEPRECATED(void, textprintf_centre, (struct BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...), 6, 7); AL_PRINTFUNC_DEPRECATED(void, textprintf_right, (struct BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...), 6, 7); AL_PRINTFUNC_DEPRECATED(void, textprintf_justify, (struct BITMAP *bmp, AL_CONST FONT *f, int x1, int x2, int y, int diff, int color, AL_CONST char *format, ...), 8, 9); AL_INLINE_DEPRECATED(void, draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color), { draw_character_ex(bmp, sprite, x, y, color, _textmode); }) AL_INLINE_DEPRECATED(int, gui_textout, (struct BITMAP *bmp, AL_CONST char *s, int x, int y, int color, int centre), { return gui_textout_ex(bmp, s, x, y, color, _textmode, centre); }) /* the old close button functions */ AL_INLINE_DEPRECATED(int, set_window_close_button, (int enable), { (void)enable; return 0; }) AL_INLINE_DEPRECATED(void, set_window_close_hook, (void (*proc)(void)), { set_close_button_callback(proc); }) /* the weird old clipping API */ AL_FUNC_DEPRECATED(void, set_clip, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); /* unnecessary, can use rest(0) */ AL_INLINE_DEPRECATED(void, yield_timeslice, (void), { ASSERT(system_driver); if (system_driver->yield_timeslice) system_driver->yield_timeslice(); }) /* DOS-ish monitor retrace ideas that don't work elsewhere */ AL_FUNCPTR(void, retrace_proc, (void)); /* Those were never documented, but we need to keep them for DLL compatibility, * and to be on the safe side also let's keep them work regardless. */ AL_INLINE_DEPRECATED(void, set_file_encoding, (int encoding), { set_filename_encoding(encoding); }) AL_INLINE_DEPRECATED(int, get_file_encoding, (void), { return get_filename_encoding(); }) #ifdef ALLEGRO_SRC AL_FUNC(int, timer_can_simulate_retrace, (void)); AL_FUNC(void, timer_simulate_retrace, (int enable)); #else AL_FUNC_DEPRECATED(int, timer_can_simulate_retrace, (void)); AL_FUNC_DEPRECATED(void, timer_simulate_retrace, (int enable)); #endif AL_FUNC_DEPRECATED(int, timer_is_using_retrace, (void)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_COMPAT_H */ allegro-4.4.3.1/include/allegro/rle.h0000664000175000017500000000237513437077643016312 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * RLE sprites. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_RLE_H #define ALLEGRO_RLE_H #include "base.h" #include "gfx.h" #ifdef __cplusplus extern "C" { #endif typedef struct RLE_SPRITE /* a RLE compressed sprite */ { int w, h; /* width and height in pixels */ int color_depth; /* color depth of the image */ int size; /* size of sprite data in bytes */ ZERO_SIZE_ARRAY(signed char, dat); } RLE_SPRITE; AL_FUNC(RLE_SPRITE *, get_rle_sprite, (struct BITMAP *bitmap)); AL_FUNC(void, destroy_rle_sprite, (RLE_SPRITE *sprite)); #ifdef __cplusplus } #endif #include "inline/rle.inl" #endif /* ifndef ALLEGRO_RLE_H */ allegro-4.4.3.1/include/allegro/fixed.h0000664000175000017500000000157213437077643016625 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fixed point type. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_FIXED_H #define ALLEGRO_FIXED_H #include "base.h" #ifdef __cplusplus extern "C" { #endif typedef int32_t fixed; AL_VAR(AL_CONST fixed, fixtorad_r); AL_VAR(AL_CONST fixed, radtofix_r); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_FIXED_H */ allegro-4.4.3.1/include/allegro/text.h0000664000175000017500000000433213437077643016507 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Text output routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_TEXT_H #define ALLEGRO_TEXT_H #include "base.h" #ifdef __cplusplus extern "C" { #endif struct BITMAP; struct FONT_VTABLE; struct FONT; AL_VAR(struct FONT *, font); AL_VAR(int, allegro_404_char); AL_FUNC(void, textout_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x, int y, int color, int bg)); AL_FUNC(void, textout_centre_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x, int y, int color, int bg)); AL_FUNC(void, textout_right_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x, int y, int color, int bg)); AL_FUNC(void, textout_justify_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x1, int x2, int y, int diff, int color, int bg)); AL_PRINTFUNC(void, textprintf_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...), 7, 8); AL_PRINTFUNC(void, textprintf_centre_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...), 7, 8); AL_PRINTFUNC(void, textprintf_right_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...), 7, 8); AL_PRINTFUNC(void, textprintf_justify_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x1, int x2, int y, int diff, int color, int bg, AL_CONST char *format, ...), 9, 10); AL_FUNC(int, text_length, (AL_CONST struct FONT *f, AL_CONST char *str)); AL_FUNC(int, text_height, (AL_CONST struct FONT *f)); AL_FUNC(void, destroy_font, (struct FONT *f)); #ifdef __cplusplus } #endif #endif /* ifndef ALLEGRO_TEXT_H */ allegro-4.4.3.1/include/xalleg.h0000664000175000017500000000770513437077643015361 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * X header file for the Allegro library. * * This prototypes some things which might be useful to * the calling application, but you don't need it. */ #ifndef X_ALLEGRO_H #define X_ALLEGRO_H #ifndef ALLEGRO_H #error Please include allegro.h before xalleg.h! #endif #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #include #include #include #include #ifdef ALLEGRO_XWINDOWS_WITH_SHM #include #include #include #endif #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE #include #endif #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR #include #endif #ifdef __cplusplus extern "C" { #endif /* X-Windows resources used by the library. */ extern struct _xwin_type { Display *display; volatile int lock_count; int screen; Window window; GC gc; Visual *visual; Colormap colormap; XImage *ximage; #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR XcursorImage *xcursor_image; XcursorBool support_argb_cursor; #endif Cursor cursor; int cursor_shape; int hw_cursor_ok; void (*screen_to_buffer)(int sx, int sy, int sw, int sh); void (*set_colors)(AL_CONST PALETTE p, int from, int to); unsigned char *screen_data; unsigned char **screen_line; unsigned char **buffer_line; int scroll_x; int scroll_y; int window_width; int window_height; int window_depth; int screen_width; int screen_height; int screen_depth; int virtual_width; int virtual_height; int mouse_warped; int keycode_to_scancode[256]; int matching_formats; int fast_visual_depth; int visual_is_truecolor; int rsize; int gsize; int bsize; int rshift; int gshift; int bshift; unsigned long cmap[0x1000]; unsigned long rmap[0x100]; unsigned long gmap[0x100]; unsigned long bmap[0x100]; #ifdef ALLEGRO_XWINDOWS_WITH_SHM XShmSegmentInfo shminfo; #endif int use_shm; int in_dga_mode; /* 0=no, 2=DGA2 */ int keyboard_grabbed; int mouse_grabbed; #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE XF86VidModeModeInfo **modesinfo; int num_modes; int mode_switched; /* only kept around and set for ABI compat */ int override_redirected; /* no longer used, kept for ABI compat */ #endif char window_title[1024]; char application_name[1024]; char application_class[1024]; int drawing_mode_ok; #ifdef ALLEGRO_MULTITHREADED void *mutex; #endif void (*close_button_callback)(void); /* These are at the end of the struct to maintain ABI compatibility with * allegro-4.2.0 (if and only if compiled with the same configuration). * Notice that IMHO apps really should not be using _xwin, but we export it, * so its fair game. */ #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE XF86VidModeModeInfo *orig_modeinfo; #endif /* Separate fullscreen and managed window id's, see * _xwin_private_create_windo* in src/x/xwin.c for more details. */ Window fs_window; Window wm_window; } _xwin; AL_FUNCPTR (int, _xwin_window_creator, (void)); AL_FUNCPTR (void, _xwin_window_defaultor, (void)); AL_FUNCPTR (void, _xwin_window_redrawer, (int, int, int, int)); AL_FUNCPTR (void, _xwin_input_handler, (void)); AL_FUNCPTR (void, _xwin_keyboard_callback, (int, int)); AL_FUNC(void, xwin_set_window_name, (AL_CONST char *name, AL_CONST char *group)); #ifdef __cplusplus } #endif #endif allegro-4.4.3.1/include/winalleg.h0000664000175000017500000000733613437077643015707 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows header file for the Allegro library. * * It must be included by Allegro programs that need to use * direct Win32 API calls and by Win32 programs that need to * interface with Allegro. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef WIN_ALLEGRO_H #define WIN_ALLEGRO_H #ifndef ALLEGRO_H #error Please include allegro.h before winalleg.h! #endif #ifdef ALLEGRO_SRC #define WIN32_LEAN_AND_MEAN /* to save compilation time */ #endif /* bodges to avoid conflicts between Allegro and Windows */ #define BITMAP WINDOWS_BITMAP #if (!defined SCAN_EXPORT) && (!defined SCAN_DEPEND) #ifdef ALLEGRO_AND_MFC #ifdef DEBUGMODE #define AL_ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } #define AL_TRACE al_trace #else #define AL_ASSERT(condition) #define AL_TRACE 1 ? (void) 0 : al_trace #endif #undef TRACE #undef ASSERT #include #else #include #endif #endif #define WINDOWS_RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) #undef BITMAP #undef RGB /* Allegro's Win32 specific interface */ #ifdef __cplusplus extern "C" { #endif /* external graphics driver support */ typedef struct WIN_GFX_DRIVER { int has_backing_store; AL_METHOD(void, switch_in, (void)); AL_METHOD(void, switch_out, (void)); AL_METHOD(void, enter_sysmode, (void)); AL_METHOD(void, exit_sysmode, (void)); AL_METHOD(void, move, (int x, int y, int w, int h)); AL_METHOD(void, iconify, (void)); AL_METHOD(void, paint, (RECT *rect)); } WIN_GFX_DRIVER; AL_VAR(WIN_GFX_DRIVER *, win_gfx_driver); AL_FUNC(void, win_grab_input, (void)); /* external window support */ AL_FUNC(HWND, win_get_window, (void)); AL_FUNC(void, win_set_window, (HWND wnd)); AL_FUNC(void, win_set_wnd_create_proc, (AL_METHOD(HWND, proc, (WNDPROC)))); AL_FUNC(void, win_set_msg_pre_proc, (AL_METHOD(int, proc, (HWND, UINT, WPARAM, LPARAM, int *)))); /* GDI to DirectDraw routines */ AL_FUNC(HDC, win_get_dc, (BITMAP *bmp)); AL_FUNC(void, win_release_dc, (BITMAP *bmp, HDC dc)); /* GDI routines */ AL_FUNC(void, set_gdi_color_format, (void)); AL_FUNC(void, set_palette_to_hdc, (HDC dc, PALETTE pal)); AL_FUNC(HPALETTE, convert_palette_to_hpalette, (PALETTE pal)); AL_FUNC(void, convert_hpalette_to_palette, (HPALETTE hpal, PALETTE pal)); AL_FUNC(HBITMAP, convert_bitmap_to_hbitmap, (BITMAP *bitmap)); AL_FUNC(BITMAP *, convert_hbitmap_to_bitmap, (HBITMAP bitmap)); AL_FUNC(void, draw_to_hdc, (HDC dc, BITMAP *bitmap, int x, int y)); AL_FUNC(void, blit_to_hdc, (BITMAP *bitmap, HDC dc, int src_x, int src_y, int dest_x, int dest_y, int w, int h)); AL_FUNC(void, stretch_blit_to_hdc, (BITMAP *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)); AL_FUNC(void, blit_from_hdc, (HDC dc, BITMAP *bitmap, int src_x, int src_y, int dest_x, int dest_y, int w, int h)); AL_FUNC(void, stretch_blit_from_hdc, (HDC hdc, BITMAP *bitmap, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)); #ifdef __cplusplus } #endif #endif /* ifndef WIN_ALLEGRO_H */ allegro-4.4.3.1/include/allegro.h0000664000175000017500000000356313437077643015530 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main header file for the entire Allegro library. * (separate modules can be included from the allegro/ directory) * * By Shawn Hargreaves. * * Vincent Penquerc'h split the original allegro.h into separate headers. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_H #define ALLEGRO_H #include "allegro/base.h" #include "allegro/system.h" #include "allegro/debug.h" #include "allegro/unicode.h" #include "allegro/mouse.h" #include "allegro/timer.h" #include "allegro/keyboard.h" #include "allegro/joystick.h" #include "allegro/palette.h" #include "allegro/gfx.h" #include "allegro/color.h" #include "allegro/draw.h" #include "allegro/rle.h" #include "allegro/compiled.h" #include "allegro/text.h" #include "allegro/font.h" #include "allegro/fli.h" #include "allegro/config.h" #include "allegro/gui.h" #include "allegro/sound.h" #include "allegro/file.h" #include "allegro/lzss.h" #include "allegro/datafile.h" #include "allegro/fixed.h" #include "allegro/fmaths.h" #include "allegro/matrix.h" #include "allegro/quat.h" #include "allegro/3d.h" #include "allegro/3dmaths.h" #ifndef ALLEGRO_NO_COMPATIBILITY #include "allegro/alcompat.h" #endif #ifndef ALLEGRO_NO_FIX_CLASS #ifdef __cplusplus #include "allegro/fix.h" #endif #endif #ifdef ALLEGRO_EXTRA_HEADER #include ALLEGRO_EXTRA_HEADER #endif #endif /* ifndef ALLEGRO_H */ allegro-4.4.3.1/include/osxalleg.h0000664000175000017500000000160513437077643015714 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main header file for the MacOS X Allegro library port. * Any OS X Allegro specific function is declared here. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #ifndef OSX_ALLEGRO_H #define OSX_ALLEGRO_H #ifndef ALLEGRO_H #error Please include allegro.h before osxalleg.h! #endif #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif #endif allegro-4.4.3.1/include/linalleg.h0000664000175000017500000000150613437077643015665 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux header file for the Allegro library. * * This file no longer contains anything. At the moment, * it exists only for backwards compatibility. * * See readme.txt for copyright information. */ #ifndef LIN_ALLEGRO_H #define LIN_ALLEGRO_H /* * THIS IS AN EX-PARROT!! */ #endif /* ifndef LIN_ALLEGRO_H */ allegro-4.4.3.1/include/qnxalleg.h0000664000175000017500000000170713437077643015714 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Header file for the QNX Allegro library port. * * This doesn't need to be included; it prototypes functions you * can use to control the library more closely. */ #ifndef QNX_ALLEGRO_H #define QNX_ALLEGRO_H #ifndef ALLEGRO_H #error Please include allegro.h before qnxalleg.h! #endif #ifndef SCAN_DEPEND #include #endif #ifdef __cplusplus extern "C" { #endif AL_FUNC(PtWidget_t *, qnx_get_window, (void)); #ifdef __cplusplus } #endif #endif allegro-4.4.3.1/include/bealleg.h0000664000175000017500000001567713437077643015507 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The Be Allegro Header File. * * Aren't you glad you used the BeOS header file? * Don't you wish everybody did? * * By Jason Wilkins. * * See readme.txt for copyright information. */ #ifndef BE_ALLEGRO_H #define BE_ALLEGRO_H /* There is namespace cross-talk between the Be API and Allegro, lets use my favorite namespace detergent. "Kludge!" Now with 25% more hack. */ #ifdef __cplusplus # define color_map al_color_map # define drawing_mode al_drawing_mode #endif #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef __cplusplus # undef color_map # undef drawing_mode # undef MIN # undef MAX # undef TRACE # undef ASSERT #ifdef DEBUGMODE # define AL_ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } #else # define AL_ASSERT(condition) #endif #ifndef SCAN_DEPEND #include #endif #define BE_ALLEGRO_VIEW_DIRECT 1 #define BE_ALLEGRO_VIEW_OVERLAY 2 #define LINE8_HOOK_NUM 3 #define LINE16_HOOK_NUM 12 #define LINE32_HOOK_NUM 4 #define ARRAY8_HOOK_NUM 8 #define ARRAY32_HOOK_NUM 9 #define RECT8_HOOK_NUM 5 #define RECT16_HOOK_NUM 16 #define RECT32_HOOK_NUM 6 #define INVERT_HOOK_NUM 11 #define BLIT_HOOK_NUM 7 #define SYNC_HOOK_NUM 10 typedef int32 (*LINE8_HOOK)(int32 startX, int32 endX, int32 startY, int32 endY, uint8 colorIndex, bool clipToRect, int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom); typedef int32 (*ARRAY8_HOOK)(indexed_color_line *array, int32 numItems, bool clipToRect, int16 top, int16 right, int16 bottom, int16 left); typedef int32 (*LINE16_HOOK)(int32 startX, int32 endX, int32 startY, int32 endY, uint16 color, bool clipToRect, int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom); typedef int32 (*LINE32_HOOK)(int32 startX, int32 endX, int32 startY, int32 endY, uint32 color, bool clipToRect, int16 clipLeft, int16 clipTop, int16 clipRight, int16 clipBottom); typedef int32 (*ARRAY32_HOOK)(rgb_color_line *array, int32 numItems, bool clipToRect, int16 top, int16 right, int16 bottom, int16 left); typedef int32 (*RECT8_HOOK)(int32 left, int32 top, int32 right, int32 bottom, uint8 colorIndex); typedef int32 (*RECT16_HOOK)(int32 left, int32 top, int32 right, int32 bottom, uint16 color); typedef int32 (*RECT32_HOOK)(int32 left, int32 top, int32 right, int32 bottom, uint32 color); typedef int32 (*INVERT_HOOK)(int32 left, int32 top, int32 right, int32 bottom); typedef int32 (*BLIT_HOOK)(int32 sourceX, int32 sourceY, int32 destinationX, int32 destinationY, int32 width, int32 height); typedef int32 (*SYNC_HOOK)(void); typedef struct HOOKS { LINE8_HOOK draw_line_8; LINE16_HOOK draw_line_16; LINE32_HOOK draw_line_32; ARRAY8_HOOK draw_array_8; ARRAY32_HOOK draw_array_32; RECT8_HOOK draw_rect_8; RECT16_HOOK draw_rect_16; RECT32_HOOK draw_rect_32; INVERT_HOOK invert_rect; BLIT_HOOK blit; SYNC_HOOK sync; } HOOKS; typedef struct { int d, w, h; uint32 mode; uint32 space; } BE_MODE_TABLE; class BeAllegroView : public BView { public: BeAllegroView(BRect, const char *, uint32, uint32, int); void MessageReceived(BMessage *); void Draw(BRect); private: int flags; }; class BeAllegroWindow : public BWindow { public: BeAllegroWindow(BRect, const char *, window_look, window_feel, uint32, uint32, uint32, uint32, uint32); ~BeAllegroWindow(); void MessageReceived(BMessage *); bool QuitRequested(void); void WindowActivated(bool); int screen_depth; int screen_width; int screen_height; BBitmap *buffer; BBitmap *aux_buffer; bool dying; thread_id drawing_thread_id; }; class BeAllegroDirectWindow : public BDirectWindow { public: BeAllegroDirectWindow(BRect, const char *, window_look, window_feel, uint32, uint32, uint32, uint32, uint32); ~BeAllegroDirectWindow(); void DirectConnected(direct_buffer_info *); void MessageReceived(BMessage *); bool QuitRequested(void); void WindowActivated(bool); void *screen_data; uint32 screen_pitch; uint32 screen_height; uint32 screen_depth; void *display_data; uint32 display_pitch; uint32 display_depth; uint32 num_rects; clipping_rect *rects; clipping_rect window; COLORCONV_BLITTER_FUNC *blitter; bool connected; bool dying; BLocker *locker; thread_id drawing_thread_id; }; class BeAllegroScreen : public BWindowScreen { public: BeAllegroScreen(const char *title, uint32 space, status_t *error, bool debugging = false); void MessageReceived(BMessage *); bool QuitRequested(void); void ScreenConnected(bool connected); }; class BeAllegroOverlay : public BWindow { public: BeAllegroOverlay(BRect, const char *, window_look, window_feel, uint32, uint32, uint32, uint32, uint32); ~BeAllegroOverlay(); void MessageReceived(BMessage *); bool QuitRequested(void); void WindowActivated(bool); BBitmap *buffer; rgb_color color_key; }; class BeAllegroApp : public BApplication { public: BeAllegroApp(const char *signature); bool QuitRequested(void); void ReadyToRun(void); }; AL_VAR(BeAllegroApp, *_be_allegro_app); AL_VAR(BeAllegroWindow, *_be_allegro_window); AL_VAR(BeAllegroDirectWindow, *_be_allegro_direct_window); AL_VAR(BeAllegroView, *_be_allegro_view); AL_VAR(BeAllegroScreen, *_be_allegro_screen); AL_VAR(BeAllegroOverlay, *_be_allegro_overlay); AL_VAR(BWindow, *_be_window); AL_VAR(BMidiSynth, *_be_midisynth); AL_VAR(sem_id, _be_sound_stream_lock); AL_VAR(sem_id, _be_fullscreen_lock); AL_VAR(sem_id, _be_window_lock); AL_VAR(sem_id, _be_mouse_view_attached); AL_VAR(BWindow, *_be_mouse_window); AL_VAR(BView, *_be_mouse_view); AL_VAR(int, _be_mouse_z); AL_VAR(bool, _be_mouse_window_mode); AL_VAR(HOOKS, _be_hooks); AL_VAR(int, _be_switch_mode); AL_VAR(volatile int, _be_lock_count); AL_VAR(volatile int, _be_focus_count); AL_VAR(volatile bool, _be_gfx_initialized); AL_VAR(int, *_be_dirty_lines); AL_ARRAY(AL_CONST BE_MODE_TABLE, _be_mode_table); extern int32 (*_be_sync_func)(); extern void (*_be_window_close_hook)(); void _be_terminate(thread_id caller, bool exit_caller); void _be_gfx_set_truecolor_shifts(); void _be_change_focus(bool active); bool _be_handle_window_close(const char *title); #endif /* ifdef C++ */ #endif /* ifndef BE_ALLEGRO_H */ allegro-4.4.3.1/src/0000775000175000017500000000000013437077643013067 5ustar siegesiegeallegro-4.4.3.1/src/config.c0000664000175000017500000010145313437077643014504 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Configuration routines. * * By Shawn Hargreaves. * * Hook functions added by Martijn Versteegh. * * Annie Testes lifted several hardcoded length limitations. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" typedef struct CONFIG_ENTRY { char *name; /* variable name (NULL if comment) */ char *data; /* variable value */ struct CONFIG_ENTRY *next; /* linked list */ } CONFIG_ENTRY; typedef struct CONFIG { CONFIG_ENTRY *head; /* linked list of config entries */ char *filename; /* where were we loaded from? */ int dirty; /* has our data changed? */ } CONFIG; typedef struct CONFIG_HOOK { char *section; /* hooked config section info */ int (*intgetter)(AL_CONST char *name, int def); AL_CONST char *(*stringgetter)(AL_CONST char *name, AL_CONST char *def); void (*stringsetter)(AL_CONST char *name, AL_CONST char *value); struct CONFIG_HOOK *next; } CONFIG_HOOK; #define MAX_CONFIGS 4 static CONFIG *config[MAX_CONFIGS] = { NULL, NULL, NULL, NULL }; static CONFIG *config_override = NULL; static CONFIG *config_language = NULL; static CONFIG *system_config = NULL; static CONFIG_HOOK *config_hook = NULL; static int config_installed = FALSE; static char **config_argv = NULL; static char *argv_buf = NULL; static int argv_buf_size = 0; /* flush_config: * Writes out a config structure to disk if the contents * have changed. */ static void flush_config(CONFIG *cfg) { CONFIG_ENTRY *pos; PACKFILE *f; char cr[16]; usetc(cr+usetc(cr, '\n'), 0); if (cfg && cfg->filename && cfg->dirty) { /* write changed data to disk */ f = pack_fopen(cfg->filename, F_WRITE); if (f) { pos = cfg->head; while (pos) { if (pos->name) { pack_fputs(pos->name, f); if (ugetc(pos->name) != '[') { pack_putc(' ', f); pack_putc('=', f); pack_putc(' ', f); } } if (pos->data) pack_fputs(pos->data, f); pack_fputs(cr, f); pos = pos->next; } pack_fclose(f); cfg->dirty = FALSE; } } } /* flush_config_file: * Writes out the config file to disk if the contents * have changed. */ void flush_config_file(void) { flush_config(config[0]); } /* destroy_config: * Destroys a config structure, writing it out to disk if the contents * have changed. */ static void destroy_config(CONFIG *cfg) { CONFIG_ENTRY *pos, *prev; if (cfg) { flush_config(cfg); if (cfg->filename) _AL_FREE(cfg->filename); /* destroy the variable list */ pos = cfg->head; while (pos) { prev = pos; pos = pos->next; if (prev->name) _AL_FREE(prev->name); if (prev->data) _AL_FREE(prev->data); _AL_FREE(prev); } _AL_FREE(cfg); } } /* config_cleanup: * Called at shutdown time to free memory being used by the config routines, * and write any changed data out to disk. */ static void config_cleanup(void) { CONFIG_HOOK *hook, *nexthook; int i; for (i=0; isection) _AL_FREE(hook->section); nexthook = hook->next; _AL_FREE(hook); hook = nexthook; } config_hook = NULL; } _AL_FREE(config_argv); config_argv = NULL; _AL_FREE(argv_buf); argv_buf = NULL; argv_buf_size = 0; _remove_exit_func(config_cleanup); config_installed = FALSE; } /* init_config: * Sets up the configuration routines ready for use, also loading the * default config file if the loaddata flag is set and no other config * file is in memory. */ static void init_config(int loaddata) { char filename[1024], tmp[128], *cfg_name; if (!config_installed) { _add_exit_func(config_cleanup, "config_cleanup"); config_installed = TRUE; } if ((loaddata) && (!config[0])) { cfg_name = uconvert_ascii("allegro.cfg", tmp); if (find_allegro_resource(filename, cfg_name, NULL, NULL, NULL, NULL, NULL, sizeof(filename)) != 0) { get_executable_name(filename, sizeof(filename)); usetc(get_filename(filename), 0); ustrzcat(filename, sizeof(filename), cfg_name); } set_config_file(filename); } if (!system_config) { system_config = _AL_MALLOC(sizeof(CONFIG)); if (system_config) { system_config->head = NULL; system_config->filename = NULL; system_config->dirty = FALSE; } } } /* get_line: * Helper for splitting files up into individual lines. Returns the length * in bytes of the sequence of characters delimited by the first EOL marker * in the array DATA of length LENGTH, and allocates NAME and VAL to record * the name and the value of the config entry respectively; otherwise set * NAME to NULL and returns a copy of the line through VAL if the line was * blank or a comment. Returns -1 and set allegro_errno on failure. */ static int get_line(AL_CONST char *data, int length, char **name, char **val) { char *buf; int buf_size=256; int inpos, outpos, i, j; int c, c2, w0; inpos = 0; outpos = 0; w0 = ucwidth(0); buf = _AL_MALLOC_ATOMIC(buf_size); if (!buf) { *allegro_errno = ENOMEM; return -1; } /* search for an EOL marker */ while (inpos=(int)buf_size-w0) { buf_size *= 2; buf = _al_sane_realloc(buf, buf_size); if (!buf) { *allegro_errno = ENOMEM; return -1; } } outpos += usetc(buf+outpos, c); inpos += uwidth(data+inpos); } usetc(buf+outpos, 0); /* skip leading spaces */ i = 0; c = ugetc(buf); while ((c) && (uisspace(c))) { i += uwidth(buf+i); c = ugetc(buf+i); } /* read name string */ j = 0; /* compute name length */ while ((c) && (!uisspace(c)) && (c != '=') && (c != '#')) { j += ucwidth(c); i += uwidth(buf+i); c = ugetc(buf+i); } if (j) { /* got a variable */ *name = _AL_MALLOC_ATOMIC(j+w0); if (!(*name)) { *allegro_errno = ENOMEM; _AL_FREE(buf); return -1; } ustrzcpy(*name, j+w0, buf+i-j); while ((c) && ((uisspace(c)) || (c == '='))) { i += uwidth(buf+i); c = ugetc(buf+i); } *val = _al_ustrdup(buf+i); if (!(*val)) { _AL_FREE(name); _AL_FREE(buf); return -1; } /* strip trailing spaces */ i = ustrlen(*val) - 1; while ((i >= 0) && (uisspace(ugetat(*val, i)))) usetat(*val, i--, 0); } else { /* blank line or comment */ *name = NULL; *val = _al_ustrdup(buf); if (!(*val)) { _AL_FREE(buf); return -1; } } _AL_FREE(buf); return inpos; } /* set_config: * Does the work of setting up a config structure. */ static void set_config(CONFIG **config, AL_CONST char *data, int length, AL_CONST char *filename) { CONFIG_ENTRY **prev, *p; char *name, *val; int ret, pos; init_config(FALSE); if (*config) { destroy_config(*config); *config = NULL; } *config = _AL_MALLOC(sizeof(CONFIG)); if (!(*config)) { *allegro_errno = ENOMEM; return; } (*config)->head = NULL; (*config)->dirty = FALSE; if (filename) { (*config)->filename = _al_ustrdup(filename); if (!(*config)->filename) { _AL_FREE(*config); *config = NULL; return; } } else (*config)->filename = NULL; prev = &(*config)->head; pos = 0; while (pos < length) { ret = get_line(data+pos, length-pos, &name, &val); if (ret<0) { _AL_FREE(*config); *config = NULL; return; } pos += ret; p = _AL_MALLOC(sizeof(CONFIG_ENTRY)); if (!p) { *allegro_errno = ENOMEM; _AL_FREE(*config); *config = NULL; return; } p->name = name; p->data = val; p->next = NULL; *prev = p; prev = &p->next; } } /* load_config_file: * Does the work of loading a config file. */ static void load_config_file(CONFIG **config, AL_CONST char *filename, AL_CONST char *savefile) { char *tmp, *tmp2; uint64_t length; if (*config) { destroy_config(*config); *config = NULL; } /* Special case when allegro_init has not been called yet. */ if (!system_driver) { set_config(config, NULL, 0, savefile); return; } length = file_size_ex(filename); if (length > 0) { PACKFILE *f = pack_fopen(filename, F_READ); if (f) { tmp = _AL_MALLOC_ATOMIC(length+1); if (tmp) { pack_fread(tmp, length, f); tmp[length] = 0; if (need_uconvert(tmp, U_UTF8, U_CURRENT)) { length = uconvert_size(tmp, U_UTF8, U_CURRENT); tmp2 = _AL_MALLOC_ATOMIC(length); if (tmp2) do_uconvert(tmp, U_UTF8, tmp2, U_CURRENT, length); length -= ucwidth(0); } else tmp2 = tmp; if (tmp2) { set_config(config, tmp2, length, savefile); if (tmp2 != tmp) _AL_FREE(tmp2); } _AL_FREE(tmp); } else set_config(config, NULL, 0, savefile); pack_fclose(f); } else set_config(config, NULL, 0, savefile); } else set_config(config, NULL, 0, savefile); } /* set_config_file: * Sets the file to be used for all future configuration operations. */ void set_config_file(AL_CONST char *filename) { ASSERT(filename); load_config_file(&config[0], filename, filename); } /* set_config_data: * Sets the block of data to be used for all future configuration * operations. */ void set_config_data(AL_CONST char *data, int length) { ASSERT(data); set_config(&config[0], data, length, NULL); } /* override_config_file: * Sets the file that will override all future configuration operations. */ void override_config_file(AL_CONST char *filename) { /* load other configuration file to override settings */ if (filename) load_config_file(&config_override, filename, filename); /* destroy the current one */ else if (config_override) { destroy_config(config_override); config_override = NULL; } } /* override_config_data: * Sets the block of data that will override all future configuration * operations. */ void override_config_data(AL_CONST char *data, int length) { ASSERT(data); set_config(&config_override, data, length, NULL); } /* push_config_state: * Pushes the current config state onto the stack. */ void push_config_state(void) { int i; if (config[MAX_CONFIGS-1]) destroy_config(config[MAX_CONFIGS-1]); for (i=MAX_CONFIGS-1; i>0; i--) config[i] = config[i-1]; config[0] = NULL; } /* pop_config_state: * Pops the current config state off the stack. */ void pop_config_state(void) { int i; if (config[0]) destroy_config(config[0]); for (i=0; isection) == 0) { if ((intgetter) || (stringgetter) || (stringsetter)) { /* modify existing hook */ hook->intgetter = intgetter; hook->stringgetter = stringgetter; hook->stringsetter = stringsetter; } else { /* remove a hook */ *prev = hook->next; _AL_FREE(hook->section); _AL_FREE(hook); } return; } prev = &hook->next; hook = hook->next; } /* add a new hook */ hook = _AL_MALLOC(sizeof(CONFIG_HOOK)); if (!hook) return; hook->section = _al_ustrdup(section_name); if (!(hook->section)) { _AL_FREE(hook); return; } hook->intgetter = intgetter; hook->stringgetter = stringgetter; hook->stringsetter = stringsetter; hook->next = config_hook; config_hook = hook; } /* is_config_hooked: * Checks whether a specific section is hooked in any way. */ int config_is_hooked(AL_CONST char *section) { CONFIG_HOOK *hook = config_hook; char section_name[256]; prettify_section_name(section, section_name, sizeof(section_name)); while (hook) { if (ustricmp(section_name, hook->section) == 0) return TRUE; hook = hook->next; } return FALSE; } /* find_config_string: * Helper for finding an entry in the configuration file. */ static CONFIG_ENTRY *find_config_string(CONFIG *config, AL_CONST char *section, AL_CONST char *name, CONFIG_ENTRY **prev) { CONFIG_ENTRY *p; int in_section; if (config) { p = config->head; if (prev) *prev = NULL; if (section && ugetc(section)) in_section = FALSE; else in_section = TRUE; while (p) { if (p->name) { if ((section) && (ugetc(p->name) == '[') && (ugetat(p->name, -1) == ']')) { /* change section */ in_section = (ustricmp(section, p->name) == 0); } if ((in_section) || (ugetc(name) == '[')) { /* is this the one? */ if (ustricmp(p->name, name) == 0) return p; } } if (prev) *prev = p; p = p->next; } } return NULL; } /* get_config_string: * Reads a string from the configuration file. */ AL_CONST char *get_config_string(AL_CONST char *section, AL_CONST char *name, AL_CONST char *def) { char section_name[256]; CONFIG_HOOK *hook; CONFIG_ENTRY *p; init_config(TRUE); prettify_section_name(section, section_name, sizeof(section_name)); /* check for hooked sections */ hook = config_hook; while (hook) { if (ustricmp(section_name, hook->section) == 0) { if (hook->stringgetter) return hook->stringgetter(name, def); else return def; } hook = hook->next; } /* find the string */ p = find_config_string(config_override, section_name, name, NULL); if (!p) { if ((ugetc(name) == '#') || ((ugetc(section_name) == '[') && (ugetat(section_name, 1) == '#'))) p = find_config_string(system_config, section_name, name, NULL); else p = find_config_string(config[0], section_name, name, NULL); } if (p && p->data && (ustrlen(p->data) != 0)) return p->data; else return def; } /* get_config_int: * Reads an integer from the configuration file. */ int get_config_int(AL_CONST char *section, AL_CONST char *name, int def) { CONFIG_HOOK *hook; char section_name[256]; AL_CONST char *s; prettify_section_name(section, section_name, sizeof(section_name)); /* check for hooked sections */ hook = config_hook; while (hook) { if (ustricmp(section_name, hook->section) == 0) { if (hook->intgetter) { return hook->intgetter(name, def); } else if (hook->stringgetter) { s = hook->stringgetter(name, NULL); if ((s) && (ugetc(s))) return ustrtol(s, NULL, 0); else return def; } else return def; } hook = hook->next; } /* read normal data */ s = get_config_string(section_name, name, NULL); if ((s) && (ugetc(s))) return ustrtol(s, NULL, 0); return def; } /* get_config_hex: * Reads a hexadecimal integer from the configuration file. */ int get_config_hex(AL_CONST char *section, AL_CONST char *name, int def) { AL_CONST char *s = get_config_string(section, name, NULL); char tmp[64]; int i; if ((s) && (ugetc(s))) { i = ustrtol(s, NULL, 16); if ((i == 0x7FFFFFFF) && (ustricmp(s, uconvert_ascii("7FFFFFFF", tmp)) != 0)) i = -1; return i; } return def; } /* get_config_float: * Reads a float from the configuration file. */ float get_config_float(AL_CONST char *section, AL_CONST char *name, float def) { AL_CONST char* s = get_config_string(section, name, NULL); if ((s) && (ugetc(s))) return uatof(s); return def; } /* get_config_id: * Reads a driver ID number from the configuration file. */ int get_config_id(AL_CONST char *section, AL_CONST char *name, int def) { AL_CONST char *s = get_config_string(section, name, NULL); char tmp[4]; char* endp; int val, i; if ((s) && (ugetc(s))) { val = ustrtol(s, &endp, 0); if (!ugetc(endp)) return val; tmp[0] = tmp[1] = tmp[2] = tmp[3] = ' '; for (i=0; i<4; i++) { if (ugetat(s, i)) tmp[i] = utoupper(ugetat(s ,i)); else break; } return AL_ID(tmp[0], tmp[1], tmp[2], tmp[3]); } return def; } /* get_config_argv: * Reads an argc/argv style token list from the configuration file. */ char **get_config_argv(AL_CONST char *section, AL_CONST char *name, int *argc) { int pos, ac, q, c; int s_size; int i; AL_CONST char *s = get_config_string(section, name, NULL); if (!s) { *argc = 0; return NULL; } /* clean up the old argv that was allocated the last time this function was * called. */ _AL_FREE(config_argv); config_argv = NULL; /* increase the buffer size if needed */ s_size = ustrsizez(s); if (s_size>argv_buf_size) { argv_buf_size = s_size; argv_buf = _al_sane_realloc(argv_buf, argv_buf_size); if (!argv_buf) { *allegro_errno = ENOMEM; *argc = 0; return NULL; } } ustrzcpy(argv_buf, argv_buf_size, s); pos = 0; ac = 0; /* tokenize the buffer and count the number of words; every space character * as well as single and double quotes are replaced with zeros; comments * that start with # are also cut off with a 0 */ c = ugetc(argv_buf); while ((c) && (c != '#')) { /* replace all spaces up to the next word with 0 */ while ((c) && (uisspace(c))) { usetat(argv_buf+pos, 0, 0); pos += ucwidth(0); c = ugetc(argv_buf+pos); } /* quit if we reached the end of the buffer or a comment */ if ((c) && (c != '#')) { /* found another word! */ ac++; /* cut away quotes by replacing them with 0 */ if ((c == '\'') || (c == '"')) { q = c; usetat(argv_buf+pos, 0, 0); pos += ucwidth(0); c = ugetc(argv_buf+pos); } else { q = 0; } /* search for the end of the word */ while ((c) && ((q) ? (c != q) : (!uisspace(c)))) { pos += ucwidth(c); c = ugetc(argv_buf+pos); } } } /* now that we know how many words there are in the buffer, allocate enough * space for a list of pointers to them, or return 0 if there are no words */ if (ac > 0) { config_argv = _AL_MALLOC(ac*sizeof *config_argv); } else { *argc = 0; return NULL; } /* go through the tokenized buffer and assign pointers in argv to point to * the beginning of each individual word */ for (i=0,pos=0,c=ugetc(argv_buf); iname = _al_ustrdup(name); else n->name = NULL; if (data) n->data = _al_ustrdup(data); else n->data = NULL; if (p) { n->next = p->next; p->next = n; } else { n->next = NULL; the_config->head = n; } return n; } /* set_config_string: * Writes a string to the configuration file. */ void set_config_string(AL_CONST char *section, AL_CONST char *name, AL_CONST char *val) { CONFIG *the_config; CONFIG_HOOK *hook; CONFIG_ENTRY *p, *prev; char section_name[256]; init_config(TRUE); prettify_section_name(section, section_name, sizeof(section_name)); /* check for hooked sections */ hook = config_hook; while (hook) { if (ustricmp(section_name, hook->section) == 0) { if (hook->stringsetter) hook->stringsetter(name, val); return; } hook = hook->next; } /* decide which config file to use */ if ((ugetc(name) == '#') || ((ugetc(section_name) == '[') && (ugetat(section_name, 1) == '#'))) the_config = system_config; else if (config_override) the_config = config_override; else the_config = config[0]; if (the_config) { p = find_config_string(the_config, section_name, name, &prev); if (p) { if ((val) && (ugetc(val))) { /* modify existing variable */ if (p->data) _AL_FREE(p->data); p->data = _al_ustrdup(val); } else { /* delete variable */ if (p->name) _AL_FREE(p->name); if (p->data) _AL_FREE(p->data); if (prev) prev->next = p->next; else the_config->head = p->next; _AL_FREE(p); } } else { if ((val) && (ugetc(val))) { /* add a new variable */ if (ugetc(section_name)) { p = find_config_string(the_config, NULL, section_name, &prev); if (!p) { /* create a new section */ p = the_config->head; while ((p) && (p->next)) p = p->next; if ((p) && (p->data) && (ugetc(p->data))) p = insert_variable(the_config, p, NULL, NULL); p = insert_variable(the_config, p, section_name, NULL); } /* append to the end of the section */ while ((p) && (p->next) && (((p->next->name) && (ugetc(p->next->name))) || ((p->next->data) && (ugetc(p->next->data))))) p = p->next; p = insert_variable(the_config, p, name, val); } else { /* global variable */ p = the_config->head; insert_variable(the_config, NULL, name, val); the_config->head->next = p; } } } the_config->dirty = TRUE; } } /* set_config_int: * Writes an integer to the configuration file. */ void set_config_int(AL_CONST char *section, AL_CONST char *name, int val) { char buf[32], tmp[32]; uszprintf(buf, sizeof(buf), uconvert_ascii("%d", tmp), val); set_config_string(section, name, buf); } /* set_config_hex: * Writes a hexadecimal integer to the configuration file. */ void set_config_hex(AL_CONST char *section, AL_CONST char *name, int val) { char buf[32], tmp[32]; if (val >= 0) { uszprintf(buf, sizeof(buf), uconvert_ascii("%X", tmp), val); set_config_string(section, name, buf); } else set_config_string(section, name, uconvert_ascii("-1", buf)); } /* set_config_float: * Writes a float to the configuration file. */ void set_config_float(AL_CONST char *section, AL_CONST char *name, float val) { char buf[32], tmp[32]; uszprintf(buf, sizeof(buf), uconvert_ascii("%f", tmp), val); set_config_string(section, name, buf); } /* set_config_id: * Writes a driver ID to the configuration file. */ void set_config_id(AL_CONST char *section, AL_CONST char *name, int val) { char buf[32], tmp[32]; int v[4]; int pos = 0; int i; if (val < 256) { uszprintf(buf, sizeof(buf), uconvert_ascii("%d", tmp), val); } else { v[0] = (val>>24)&0xFF; v[1] = (val>>16)&0xFF; v[2] = (val>>8)&0xFF; v[3] = val&0xFF; for (i=0; (i<4) && (v[i]) && (v[i] != ' '); i++) pos += usetc(buf+pos, v[i]); usetc(buf+pos, 0); } set_config_string(section, name, buf); } /* _reload_config: * Internal helper to reload the configuration from allegro_init, in case * set_config_file was called before allegro_init. */ void _reload_config(void) { if (config[0]) { char *name = _al_ustrdup(config[0]->filename); set_config_file(name); _AL_FREE(name); } } /* reload_config_texts: * Reads in a block of translated system text, looking for either a * user-specified file, a ??text.cfg file, or a language.dat#??TEXT_CFG * datafile object. If new_language is not NULL, the language config * variable will be set to new_language before reloading the * configuration files. */ void reload_config_texts(AL_CONST char *new_language) { char filename[1024], tmp1[128], tmp2[128]; AL_CONST char *name, *ext, *datafile; char *namecpy; if (config_language) { destroy_config(config_language); config_language = NULL; } if (new_language) set_config_string("system", "language", new_language); name = get_config_string(uconvert_ascii("system", tmp1), uconvert_ascii("language", tmp2), NULL); if ((name) && (ugetc(name))) { namecpy = _al_ustrdup(name); ustrlwr (namecpy); if ((ustrlen(namecpy)<4) || (ustricmp(namecpy+uoffset(namecpy, -4), uconvert_ascii("text", tmp1)) != 0)) ext = uconvert_ascii("text.cfg", tmp1); else ext = uconvert_ascii(".cfg", tmp1); datafile = uconvert_ascii("language.dat", tmp2); if (find_allegro_resource(filename, namecpy, ext, datafile, NULL, NULL, NULL, sizeof(filename)) == 0) { _AL_FREE(namecpy); load_config_file(&config_language, filename, NULL); return; } _AL_FREE(namecpy); } config_language = _AL_MALLOC(sizeof(CONFIG)); if (config_language ) { config_language ->head = NULL; config_language ->filename = NULL; config_language ->dirty = FALSE; } } /* get_config_text: * Looks up a translated version of the specified English string, * returning a suitable message in the current language if one is * available, or a copy of the parameter if no translation can be found. */ AL_CONST char *get_config_text(AL_CONST char *msg) { char tmp1[256]; AL_CONST char *section; AL_CONST char *umsg; AL_CONST char *s; AL_CONST char *ret = NULL; char *name; CONFIG_HOOK *hook; CONFIG_ENTRY *p; int c, pos, size; ASSERT(msg); /* Hack: the inline definition of install_allegro() from 4.2.0 calls * get_config_text() even before Allegro has been initialised, leading * to a crash in get_executable_name(). To retain binary compatibility * we check for this case. */ if (_allegro_count == 0) { return msg; } init_config(TRUE); section = uconvert_ascii("[language]", tmp1); /* allocate memory and convert message to current encoding format */ if (need_uconvert(msg, U_ASCII, U_CURRENT)) { size = uconvert_size(msg, U_ASCII, U_CURRENT); umsg = _AL_MALLOC_ATOMIC(size); if (!umsg) { *allegro_errno = ENOMEM; return empty_string; } name = _AL_MALLOC_ATOMIC(size); if (!name) { _AL_FREE((char *)umsg); /* remove constness */ *allegro_errno = ENOMEM; return empty_string; } do_uconvert(msg, U_ASCII, (char*)umsg, U_CURRENT, size); } else { umsg = msg; name = _AL_MALLOC_ATOMIC(ustrsizez(msg)); if (!name) { *allegro_errno = ENOMEM; return empty_string; } } s = umsg; pos = 0; while ((c = ugetxc(&s)) != 0) { if ((uisspace(c)) || (c == '=') || (c == '#')) pos += usetc(name+pos, '_'); else pos += usetc(name+pos, c); } usetc(name+pos, 0); /* check for hooked sections */ hook = config_hook; while (hook) { if (ustricmp(section, hook->section) == 0) { if (hook->stringgetter) { ret = hook->stringgetter(name, umsg); break; } } hook = hook->next; } if (!ret) { /* find the string */ p = find_config_string(config_override, section, name, NULL); if (!p) { p = find_config_string(config[0], section, name, NULL); if (!p) p = find_config_string(config_language, section, name, NULL); } if (p) { ret = (p->data ? p->data : empty_string); } else { /* no translation, so store off this value in the file */ p = config_language->head; insert_variable(config_language, NULL, name, umsg); config_language->head->next = p; ret = config_language->head->data; } } /* free memory */ if (umsg!=msg) _AL_FREE((char*) umsg); /* remove constness */ _AL_FREE(name); return ret; } /* add_unique_name * Helper to add a name to a list of names. */ static int add_unique_name(AL_CONST char ***names, int n, char const *name) { int i; /* FIXME: use better search algorithm */ for (i = 0; i < n; i++) if (!ustrcmp((*names)[i], name)) return n; *names = _al_sane_realloc((void *)*names, (n + 1) * sizeof **names); (*names)[n] = name; return n + 1; } /* attach_config_entries * Helper function to attach key or section names to a list of strings. */ static int attach_config_entries(CONFIG *conf, AL_CONST char *section, int n, AL_CONST char ***names, int list_sections) { CONFIG_ENTRY *p; char section_name[256]; int in_section; prettify_section_name(section, section_name, sizeof(section_name)); if (conf) { p = conf->head; /* If section is NULL, only initial, section-less entries are used. */ if (ugetc(section_name)) in_section = FALSE; else in_section = TRUE; while (p) { if (p->name) { /* a section start is just a list entry enclosed in [] */ if (ugetc(p->name) == '[' && ugetat(p->name, -1) == ']') { if (list_sections) { n = add_unique_name(names, n, p->name); } in_section = (ustricmp(section_name, p->name) == 0); } else if (in_section && !list_sections) { n = add_unique_name(names, n, p->name); } } p = p->next; } } return n; } /* list_config_entires: * Returns the names of all config entries in a section. The names parameter is * a pointer to a strings array that will contain the config keys. If it points to * a NULL pointer, it will be allocated, or else re-allocated accordingly. The * return value tells how many valid string pointers it contains after the * function returns. */ int list_config_entries(AL_CONST char *section, AL_CONST char ***names) { int n = 0; n = attach_config_entries(config_override, section, n, names, 0); n = attach_config_entries(config[0], section, n, names, 0); return n; } /* list_config_sections: * Returns the names of all current config sections, enclodes in []. The names * parameter and return value is like in list_config_entires above. */ int list_config_sections(AL_CONST char ***names) { int n = 0; n = attach_config_entries(config_override, NULL, n, names, 1); n = attach_config_entries(config[0], NULL, n, names, 1); return n; } /* free_config_entries: * Frees the entries list returned by list_config_entires or * list_config_sections again. */ void free_config_entries(AL_CONST char ***names) { _AL_FREE(*((char***)(names))); *names = NULL; } allegro-4.4.3.1/src/bmp.c0000664000175000017500000004712413437077643014021 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BMP reader. * * By Seymour Shlien. * * OS/2 BMP support and BMP save function by Jonas Petersen. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #define BI_RGB 0 #define BI_RLE8 1 #define BI_RLE4 2 #define BI_BITFIELDS 3 #define OS2INFOHEADERSIZE 12 #define WININFOHEADERSIZE 40 typedef struct BITMAPFILEHEADER { unsigned long bfType; unsigned long bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits; } BITMAPFILEHEADER; /* Used for both OS/2 and Windows BMP. * Contains only the parameters needed to load the image */ typedef struct BITMAPINFOHEADER { unsigned long biWidth; signed long biHeight; unsigned short biBitCount; unsigned long biCompression; } BITMAPINFOHEADER; typedef struct WINBMPINFOHEADER /* size: 40 */ { unsigned long biWidth; signed long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; unsigned long biXPelsPerMeter; unsigned long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } WINBMPINFOHEADER; typedef struct OS2BMPINFOHEADER /* size: 12 */ { unsigned short biWidth; unsigned short biHeight; unsigned short biPlanes; unsigned short biBitCount; } OS2BMPINFOHEADER; /* read_bmfileheader: * Reads a BMP file header and check that it has the BMP magic number. */ static int read_bmfileheader(PACKFILE *f, BITMAPFILEHEADER *fileheader) { fileheader->bfType = pack_igetw(f); fileheader->bfSize= pack_igetl(f); fileheader->bfReserved1= pack_igetw(f); fileheader->bfReserved2= pack_igetw(f); fileheader->bfOffBits= pack_igetl(f); if (fileheader->bfType != 19778) return -1; return 0; } /* read_win_bminfoheader: * Reads information from a BMP file header. */ static int read_win_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader) { WINBMPINFOHEADER win_infoheader; win_infoheader.biWidth = pack_igetl(f); win_infoheader.biHeight = pack_igetl(f); win_infoheader.biPlanes = pack_igetw(f); win_infoheader.biBitCount = pack_igetw(f); win_infoheader.biCompression = pack_igetl(f); win_infoheader.biSizeImage = pack_igetl(f); win_infoheader.biXPelsPerMeter = pack_igetl(f); win_infoheader.biYPelsPerMeter = pack_igetl(f); win_infoheader.biClrUsed = pack_igetl(f); win_infoheader.biClrImportant = pack_igetl(f); infoheader->biWidth = win_infoheader.biWidth; infoheader->biHeight = win_infoheader.biHeight; infoheader->biBitCount = win_infoheader.biBitCount; infoheader->biCompression = win_infoheader.biCompression; return 0; } /* read_os2_bminfoheader: * Reads information from an OS/2 format BMP file header. */ static int read_os2_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader) { OS2BMPINFOHEADER os2_infoheader; os2_infoheader.biWidth = pack_igetw(f); os2_infoheader.biHeight = pack_igetw(f); os2_infoheader.biPlanes = pack_igetw(f); os2_infoheader.biBitCount = pack_igetw(f); infoheader->biWidth = os2_infoheader.biWidth; infoheader->biHeight = os2_infoheader.biHeight; infoheader->biBitCount = os2_infoheader.biBitCount; infoheader->biCompression = 0; return 0; } /* read_bmicolors: * Loads the color palette for 1,4,8 bit formats. */ static void read_bmicolors(int bytes, RGB *pal, PACKFILE *f, int win_flag) { int i, j; for (i=j=0; (i+3 <= bytes && j < PAL_SIZE); j++) { pal[j].b = pack_getc(f) / 4; pal[j].g = pack_getc(f) / 4; pal[j].r = pack_getc(f) / 4; i += 3; if (win_flag && i < bytes) { pack_getc(f); i++; } } for (; i> 1; } } pix = b[j]; bmp->line[line][i] = pix; } } /* read_4bit_line: * Support function for reading the 4 bit bitmap file format. */ static void read_4bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) { unsigned char b[8]; unsigned long n; int i, j, k; int temp; int pix; for (i=0; i> 4; b[k*2] = temp & 15; n = n >> 8; } } pix = b[j]; bmp->line[line][i] = pix; } } /* read_8bit_line: * Support function for reading the 8 bit bitmap file format. */ static void read_8bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) { unsigned char b[4]; unsigned long n; int i, j, k; int pix; for (i=0; i> 8; } } pix = b[j]; bmp->line[line][i] = pix; } } /* read_16bit_line: * Support function for reading the 16 bit bitmap file format, doing * our best to convert it down to a 256 color palette. */ static void read_16bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) { int i, w; RGB c; for (i=0; i> 10) & 0x1f; c.g = (w >> 5) & 0x1f; c.b = w & 0x1f; bmp_write16(bmp->line[line]+i*2, makecol16(_rgb_scale_5[c.r], _rgb_scale_5[c.g], _rgb_scale_5[c.b])); } /* padding */ i = (i * 2) % 4; if (i != 0) { while (i++ < 4) pack_getc(f); } } /* read_24bit_line: * Support function for reading the 24 bit bitmap file format, doing * our best to convert it down to a 256 color palette. */ static void read_24bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) { int i; RGB c; for (i=0; iline[line]+i*3, makecol24(c.r, c.g, c.b)); } /* padding */ i = (i * 3) % 4; if (i != 0) { while (i++ < 4) pack_getc(f); } } /* read_32bit_line: * Support function for reading the 32 bit bitmap file format, doing * our best to convert it down to a 256 color palette. */ static void read_32bit_line(int length, PACKFILE *f, BITMAP *bmp, int line) { int i; RGB c; char a; for (i=0; iline[line]+i*4, makeacol32(c.r, c.g, c.b, a)); } } /* read_bitfields_image: * For reading the bitfield compressed BMP image format. */ static void read_bitfields_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) { int k, i, line, height, dir; int bpp; int bytes_per_pixel; int red, grn, blu; unsigned long buffer; height = infoheader->biHeight; line = height < 0 ? 0 : height-1; dir = height < 0 ? 1 : -1; height = ABS(height); bpp = bitmap_color_depth(bmp); bytes_per_pixel = BYTES_PER_PIXEL(bpp); for (i=0; ibiWidth; k++) { pack_fread(&buffer, bytes_per_pixel, f); if (bpp == 15) { red = (buffer >> 10) & 0x1f; grn = (buffer >> 5) & 0x1f; blu = (buffer) & 0x1f; buffer = (red << _rgb_r_shift_15) | (grn << _rgb_g_shift_15) | (blu << _rgb_b_shift_15); } else if (bpp == 16) { red = (buffer >> 11) & 0x1f; grn = (buffer >> 5) & 0x3f; blu = (buffer) & 0x1f; buffer = (red << _rgb_r_shift_16) | (grn << _rgb_g_shift_16) | (blu << _rgb_b_shift_16); } else { red = (buffer >> 16) & 0xff; grn = (buffer >> 8) & 0xff; blu = (buffer) & 0xff; buffer = (red << _rgb_r_shift_32) | (grn << _rgb_g_shift_32) | (blu << _rgb_b_shift_32); } memcpy(&bmp->line[line][k * bytes_per_pixel], &buffer, bytes_per_pixel); } /* padding */ k = (k * bytes_per_pixel) % 4; if (k > 0) { while (k++ < 4) pack_getc(f); } } } /* read_image: * For reading the noncompressed BMP image format. */ static void read_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) { int i, line, height, dir; height = infoheader->biHeight; line = height < 0 ? 0: height-1; dir = height < 0 ? 1: -1; height = ABS(height); for (i=0; ibiBitCount) { case 1: read_1bit_line(infoheader->biWidth, f, bmp, line); break; case 4: read_4bit_line(infoheader->biWidth, f, bmp, line); break; case 8: read_8bit_line(infoheader->biWidth, f, bmp, line); break; case 16: read_16bit_line(infoheader->biWidth, f, bmp, line); break; case 24: read_24bit_line(infoheader->biWidth, f, bmp, line); break; case 32: read_32bit_line(infoheader->biWidth, f, bmp, line); break; } } } /* read_RLE8_compressed_image: * For reading the 8 bit RLE compressed BMP image format. */ static void read_RLE8_compressed_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) { unsigned char count, val, val0; int j, pos, line; int eolflag, eopicflag; eopicflag = 0; line = infoheader->biHeight - 1; while (eopicflag == 0) { pos = 0; /* x position in bitmap */ eolflag = 0; /* end of line flag */ while ((eolflag == 0) && (eopicflag == 0)) { count = pack_getc(f); val = pack_getc(f); if (count > 0) { /* repeat pixel count times */ for (j=0;jline[line][pos] = val; pos++; } } else { switch (val) { case 0: /* end of line flag */ eolflag=1; break; case 1: /* end of picture flag */ eopicflag=1; break; case 2: /* displace picture */ count = pack_getc(f); val = pack_getc(f); pos += count; line -= val; break; default: /* read in absolute mode */ for (j=0; jline[line][pos] = val0; pos++; } if (j%2 == 1) val0 = pack_getc(f); /* align on word boundary */ break; } } if (pos-1 > (int)infoheader->biWidth) eolflag=1; } line--; if (line < 0) eopicflag = 1; } } /* read_RLE4_compressed_image: * For reading the 4 bit RLE compressed BMP image format. */ static void read_RLE4_compressed_image(PACKFILE *f, BITMAP *bmp, AL_CONST BITMAPINFOHEADER *infoheader) { unsigned char b[8]; unsigned char count; unsigned short val0, val; int j, k, pos, line; int eolflag, eopicflag; eopicflag = 0; /* end of picture flag */ line = infoheader->biHeight - 1; while (eopicflag == 0) { pos = 0; eolflag = 0; /* end of line flag */ while ((eolflag == 0) && (eopicflag == 0)) { count = pack_getc(f); val = pack_getc(f); if (count > 0) { /* repeat pixels count times */ b[1] = val & 15; b[0] = (val >> 4) & 15; for (j=0; jline[line][pos] = b[j%2]; pos++; } } else { switch (val) { case 0: /* end of line */ eolflag=1; break; case 1: /* end of picture */ eopicflag=1; break; case 2: /* displace image */ count = pack_getc(f); val = pack_getc(f); pos += count; line -= val; break; default: /* read in absolute mode */ for (j=0; j> 4; b[2*k] = val0 & 15; val0 = val0 >> 4; } } bmp->line[line][pos] = b[j%4]; pos++; } break; } } if (pos-1 > (int)infoheader->biWidth) eolflag=1; } line--; if (line < 0) eopicflag = 1; } } /* load_bmp: * Loads a Windows BMP file, returning a bitmap structure and storing * the palette data in the specified palette (this should be an array of * at least 256 RGB structures). * * Thanks to Seymour Shlien for contributing this function. */ BITMAP *load_bmp(AL_CONST char *filename, RGB *pal) { PACKFILE *f; BITMAP *bmp; ASSERT(filename); f = pack_fopen(filename, F_READ); if (!f) return NULL; bmp = load_bmp_pf(f, pal); pack_fclose(f); return bmp; } /* load_bmp_pf: * Like load_bmp, but starts loading from the current place in the PACKFILE * specified. If successful the offset into the file will be left just after * the image data. If unsuccessful the offset into the file is unspecified, * i.e. you must either reset the offset to some known place or close the * packfile. The packfile is not closed by this function. */ BITMAP *load_bmp_pf(PACKFILE *f, RGB *pal) { BITMAPFILEHEADER fileheader; BITMAPINFOHEADER infoheader; BITMAP *bmp; PALETTE tmppal; int want_palette = TRUE; unsigned long biSize; int bpp, dest_depth; ASSERT(f); /* we really need a palette */ if (!pal) { want_palette = FALSE; pal = tmppal; } if (read_bmfileheader(f, &fileheader) != 0) { return NULL; } biSize = pack_igetl(f); if (biSize == WININFOHEADERSIZE) { if (read_win_bminfoheader(f, &infoheader) != 0) { return NULL; } if (infoheader.biCompression != BI_BITFIELDS) read_bmicolors(fileheader.bfOffBits - 54, pal, f, 1); } else if (biSize == OS2INFOHEADERSIZE) { if (read_os2_bminfoheader(f, &infoheader) != 0) { return NULL; } if (infoheader.biCompression != BI_BITFIELDS) read_bmicolors(fileheader.bfOffBits - 26, pal, f, 0); } else { return NULL; } if (infoheader.biBitCount == 24) bpp = 24; else if (infoheader.biBitCount == 16) bpp = 16; else if (infoheader.biBitCount == 32) bpp = 32; else bpp = 8; if (infoheader.biCompression == BI_BITFIELDS) { unsigned long redMask = pack_igetl(f); unsigned long grnMask = pack_igetl(f); unsigned long bluMask = pack_igetl(f); (void)grnMask; if ((bluMask == 0x001f) && (redMask == 0x7C00)) bpp = 15; else if ((bluMask == 0x001f) && (redMask == 0xF800)) bpp = 16; else if ((bluMask == 0x0000FF) && (redMask == 0xFF0000)) bpp = 32; else { /* Unrecognised bit masks/depth, refuse to load. */ return NULL; } } dest_depth = _color_load_depth(bpp, FALSE); bmp = create_bitmap_ex(bpp, infoheader.biWidth, ABS(infoheader.biHeight)); if (!bmp) { return NULL; } clear_bitmap(bmp); switch (infoheader.biCompression) { case BI_RGB: read_image(f, bmp, &infoheader); break; case BI_RLE8: read_RLE8_compressed_image(f, bmp, &infoheader); break; case BI_RLE4: read_RLE4_compressed_image(f, bmp, &infoheader); break; case BI_BITFIELDS: read_bitfields_image(f, bmp, &infoheader); break; default: destroy_bitmap(bmp); bmp = NULL; } if (dest_depth != bpp) { /* restore original palette except if it comes from the bitmap */ if ((bpp != 8) && (!want_palette)) pal = NULL; if (bmp) { bmp = _fixup_loaded_bitmap(bmp, pal, dest_depth); } } /* construct a fake palette if 8-bit mode is not involved */ if ((bpp != 8) && (dest_depth != 8) && want_palette) generate_332_palette(pal); return bmp; } /* save_bmp: * Writes a bitmap into a BMP file, using the specified palette (this * should be an array of at least 256 RGB structures). */ int save_bmp(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) { PACKFILE *f; int ret; ASSERT(filename); f = pack_fopen(filename, F_WRITE); if (!f) return -1; ret = save_bmp_pf(f, bmp, pal); pack_fclose(f); return ret; } /* save_bmp_pf: * Like save_bmp but writes into the PACKFILE given instead of a new file. * The packfile is not closed after writing is completed. On success the * offset into the file is left after the TGA file just written. On failure * the offset is left at the end of whatever incomplete data was written. */ int save_bmp_pf(PACKFILE *f, BITMAP *bmp, AL_CONST RGB *pal) { PALETTE tmppal; int bfSize; int biSizeImage; int depth; int bpp; int filler; int c, i, j; ASSERT(f); ASSERT(bmp); depth = bitmap_color_depth(bmp); bpp = (depth == 8) ? 8 : 24; filler = 3 - ((bmp->w*(bpp/8)-1) & 3); if (!pal) { get_palette(tmppal); pal = tmppal; } if (bpp == 8) { biSizeImage = (bmp->w + filler) * bmp->h; bfSize = (54 /* header */ + 256*4 /* palette */ + biSizeImage); /* image data */ } else { biSizeImage = (bmp->w*3 + filler) * bmp->h; bfSize = 54 + biSizeImage; /* header + image data */ } *allegro_errno = 0; /* file_header */ pack_iputw(0x4D42, f); /* bfType ("BM") */ pack_iputl(bfSize, f); /* bfSize */ pack_iputw(0, f); /* bfReserved1 */ pack_iputw(0, f); /* bfReserved2 */ if (bpp == 8) /* bfOffBits */ pack_iputl(54+256*4, f); else pack_iputl(54, f); /* info_header */ pack_iputl(40, f); /* biSize */ pack_iputl(bmp->w, f); /* biWidth */ pack_iputl(bmp->h, f); /* biHeight */ pack_iputw(1, f); /* biPlanes */ pack_iputw(bpp, f); /* biBitCount */ pack_iputl(0, f); /* biCompression */ pack_iputl(biSizeImage, f); /* biSizeImage */ pack_iputl(0xB12, f); /* biXPelsPerMeter (0xB12 = 72 dpi) */ pack_iputl(0xB12, f); /* biYPelsPerMeter */ if (bpp == 8) { pack_iputl(256, f); /* biClrUsed */ pack_iputl(256, f); /* biClrImportant */ /* palette */ for (i=0; i<256; i++) { pack_putc(_rgb_scale_6[pal[i].b], f); pack_putc(_rgb_scale_6[pal[i].g], f); pack_putc(_rgb_scale_6[pal[i].r], f); pack_putc(0, f); } } else { pack_iputl(0, f); /* biClrUsed */ pack_iputl(0, f); /* biClrImportant */ } /* image data */ for (i=bmp->h-1; i>=0; i--) { for (j=0; jw; j++) { if (bpp == 8) { pack_putc(getpixel(bmp, j, i), f); } else { c = getpixel(bmp, j, i); pack_putc(getb_depth(depth, c), f); pack_putc(getg_depth(depth, c), f); pack_putc(getr_depth(depth, c), f); } } for (j=0; j> 10) & 0x1F) << _rgb_r_shift_15) | (((value >> 5) & 0x1F) << _rgb_g_shift_15) | ((value & 0x1F) << _rgb_b_shift_15); } /* raw_tga_read16: * Helper for reading 16-bit raw data from TGA files. */ static unsigned short *raw_tga_read16(unsigned short *b, int w, PACKFILE *f) { while (w--) *b++ = single_tga_read16(f); return b; } /* rle_tga_read16: * Helper for reading 16-bit RLE data from TGA files. */ static void rle_tga_read16(unsigned short *b, int w, PACKFILE *f) { int color, count, c = 0; do { count = pack_getc(f); if (count & 0x80) { /* run-length packet */ count = (count & 0x7F) + 1; c += count; color = single_tga_read16(f); while (count--) *b++ = color; } else { /* raw packet */ count++; c += count; b = raw_tga_read16(b, count, f); } } while (c < w); } /* load_tga: * Loads a TGA file, returning a bitmap structure and storing the * palette data in the specified palette (this should be an array * of at least 256 RGB structures). */ BITMAP *load_tga(AL_CONST char *filename, RGB *pal) { PACKFILE *f; BITMAP *bmp; ASSERT(filename); f = pack_fopen(filename, F_READ); if (!f) return NULL; bmp = load_tga_pf(f, pal); pack_fclose(f); return bmp; } /* load_tga_pf: * Like load_tga, but starts loading from the current place in the PACKFILE * specified. If successful the offset into the file will be left just after * the image data. If unsuccessful the offset into the file is unspecified, * i.e. you must either reset the offset to some known place or close the * packfile. The packfile is not closed by this function. */ BITMAP *load_tga_pf(PACKFILE *f, RGB *pal) { unsigned char image_id[256], image_palette[256][3]; unsigned char id_length, palette_type, image_type, palette_entry_size; unsigned char bpp, descriptor_bits; short unsigned int palette_colors; short unsigned int image_width, image_height; unsigned int c, i, y, yc; int dest_depth; int compressed; BITMAP *bmp; PALETTE tmppal; int want_palette = TRUE; ASSERT(f); /* we really need a palette */ if (!pal) { want_palette = FALSE; pal = tmppal; } id_length = pack_getc(f); palette_type = pack_getc(f); image_type = pack_getc(f); /* first_color */ pack_igetw(f); palette_colors = pack_igetw(f); palette_entry_size = pack_getc(f); /* left */ pack_igetw(f); /* top */ pack_igetw(f); image_width = pack_igetw(f); image_height = pack_igetw(f); bpp = pack_getc(f); descriptor_bits = pack_getc(f); pack_fread(image_id, id_length, f); if (palette_type == 1) { for (i = 0; i < palette_colors; i++) { switch (palette_entry_size) { case 16: c = pack_igetw(f); image_palette[i][0] = (c & 0x1F) << 3; image_palette[i][1] = ((c >> 5) & 0x1F) << 3; image_palette[i][2] = ((c >> 10) & 0x1F) << 3; break; case 24: case 32: image_palette[i][0] = pack_getc(f); image_palette[i][1] = pack_getc(f); image_palette[i][2] = pack_getc(f); if (palette_entry_size == 32) pack_getc(f); break; } } } else if (palette_type != 0) { return NULL; } /* Image type: * 0 = no image data * 1 = uncompressed color mapped * 2 = uncompressed true color * 3 = grayscale * 9 = RLE color mapped * 10 = RLE true color * 11 = RLE grayscale */ compressed = (image_type & 8); image_type &= 7; if ((image_type < 1) || (image_type > 3)) { return NULL; } switch (image_type) { case 1: /* paletted image */ if ((palette_type != 1) || (bpp != 8)) { return NULL; } for(i=0; i> 2; pal[i].g = image_palette[i][1] >> 2; pal[i].b = image_palette[i][0] >> 2; } dest_depth = _color_load_depth(8, FALSE); break; case 2: /* truecolor image */ if ((palette_type == 0) && ((bpp == 15) || (bpp == 16))) { bpp = 15; dest_depth = _color_load_depth(15, FALSE); } else if ((palette_type == 0) && ((bpp == 24) || (bpp == 32))) { dest_depth = _color_load_depth(bpp, (bpp == 32)); } else { return NULL; } break; case 3: /* grayscale image */ if ((palette_type != 0) || (bpp != 8)) { return NULL; } for (i=0; i<256; i++) { pal[i].r = i>>2; pal[i].g = i>>2; pal[i].b = i>>2; } dest_depth = _color_load_depth(bpp, FALSE); break; default: return NULL; } bmp = create_bitmap_ex(bpp, image_width, image_height); if (!bmp) { return NULL; } *allegro_errno = 0; for (y=image_height; y; y--) { yc = (descriptor_bits & 0x20) ? image_height-y : y-1; switch (image_type) { case 1: case 3: if (compressed) rle_tga_read8(bmp->line[yc], image_width, f); else raw_tga_read8(bmp->line[yc], image_width, f); break; case 2: if (bpp == 32) { if (compressed) rle_tga_read32((unsigned int *)bmp->line[yc], image_width, f); else raw_tga_read32((unsigned int *)bmp->line[yc], image_width, f); } else if (bpp == 24) { if (compressed) rle_tga_read24(bmp->line[yc], image_width, f); else raw_tga_read24(bmp->line[yc], image_width, f); } else { if (compressed) rle_tga_read16((unsigned short *)bmp->line[yc], image_width, f); else raw_tga_read16((unsigned short *)bmp->line[yc], image_width, f); } break; } } if (*allegro_errno) { destroy_bitmap(bmp); return NULL; } if (dest_depth != bpp) { /* restore original palette except if it comes from the bitmap */ if ((bpp != 8) && (!want_palette)) pal = NULL; bmp = _fixup_loaded_bitmap(bmp, pal, dest_depth); } /* construct a fake palette if 8-bit mode is not involved */ if ((bpp != 8) && (dest_depth != 8) && want_palette) generate_332_palette(pal); return bmp; } /* save_tga: * Writes a bitmap into a TGA file, using the specified palette (this * should be an array of at least 256 RGB structures). */ int save_tga(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) { PACKFILE *f; int ret; ASSERT(filename); f = pack_fopen(filename, F_WRITE); if (!f) return -1; ret = save_tga_pf(f, bmp, pal); pack_fclose(f); return ret; } /* save_tga_pf: * Like save_tga but writes into the PACKFILE given instead of a new file. * The packfile is not closed after writing is completed. On success the * offset into the file is left after the TGA file just written. On failure * the offset is left at the end of whatever incomplete data was written. */ int save_tga_pf(PACKFILE *f, BITMAP *bmp, AL_CONST RGB *pal) { unsigned char image_palette[256][3]; int x, y, c, r, g, b; int depth; PALETTE tmppal; ASSERT(f); ASSERT(bmp); if (!pal) { get_palette(tmppal); pal = tmppal; } depth = bitmap_color_depth(bmp); if (depth == 15) depth = 16; *allegro_errno = 0; pack_putc(0, f); /* id length (no id saved) */ pack_putc((depth == 8) ? 1 : 0, f); /* palette type */ pack_putc((depth == 8) ? 1 : 2, f); /* image type */ pack_iputw(0, f); /* first colour */ pack_iputw((depth == 8) ? 256 : 0, f); /* number of colours */ pack_putc((depth == 8) ? 24 : 0, f); /* palette entry size */ pack_iputw(0, f); /* left */ pack_iputw(0, f); /* top */ pack_iputw(bmp->w, f); /* width */ pack_iputw(bmp->h, f); /* height */ pack_putc(depth, f); /* bits per pixel */ pack_putc(_bitmap_has_alpha (bmp) ? 8 : 0, f); /* descriptor (bottom to top, 8-bit alpha) */ if (depth == 8) { for (y=0; y<256; y++) { image_palette[y][2] = _rgb_scale_6[pal[y].r]; image_palette[y][1] = _rgb_scale_6[pal[y].g]; image_palette[y][0] = _rgb_scale_6[pal[y].b]; } pack_fwrite(image_palette, 768, f); } switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: for (y=bmp->h; y; y--) for (x=0; xw; x++) pack_putc(getpixel(bmp, x, y-1), f); break; #endif #ifdef ALLEGRO_COLOR16 case 15: for (y=bmp->h; y; y--) { for (x=0; xw; x++) { c = getpixel(bmp, x, y-1); r = getr15(c); g = getg15(c); b = getb15(c); c = ((r<<7)&0x7C00) | ((g<<2)&0x3E0) | ((b>>3)&0x1F); pack_iputw(c, f); } } break; case 16: for (y=bmp->h; y; y--) { for (x=0; xw; x++) { c = getpixel(bmp, x, y-1); r = getr16(c); g = getg16(c); b = getb16(c); c = ((r<<7)&0x7C00) | ((g<<2)&0x3E0) | ((b>>3)&0x1F); pack_iputw(c, f); } } break; #endif #ifdef ALLEGRO_COLOR24 case 24: for (y=bmp->h; y; y--) { for (x=0; xw; x++) { c = getpixel(bmp, x, y-1); pack_putc(getb24(c), f); pack_putc(getg24(c), f); pack_putc(getr24(c), f); } } break; #endif #ifdef ALLEGRO_COLOR32 case 32: for (y=bmp->h; y; y--) { for (x=0; xw; x++) { c = getpixel(bmp, x, y-1); pack_putc(getb32(c), f); pack_putc(getg32(c), f); pack_putc(getr32(c), f); pack_putc(geta32(c), f); } } break; #endif } if (*allegro_errno) return -1; else return 0; } allegro-4.4.3.1/src/stream.c0000664000175000017500000001226413437077643014533 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Audio stream functions. * * By Shawn Hargreaves (original version by Andrew Ellem). * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* play_audio_stream: * Creates a new audio stream and starts it playing. The length is the * size of each transfer buffer. */ AUDIOSTREAM *play_audio_stream(int len, int bits, int stereo, int freq, int vol, int pan) { AUDIOSTREAM *stream; int i, bufcount; ASSERT(len > 0); ASSERT(bits > 0); ASSERT(freq > 0); /* decide how many buffer fragments we will need */ if ((digi_driver) && (digi_driver->buffer_size)) i = digi_driver->buffer_size(); else i = 2048; if (len >= i) bufcount = 1; else bufcount = (i + len-1) / len; /* create the stream structure */ stream = _AL_MALLOC(sizeof(AUDIOSTREAM)); if (!stream) return NULL; stream->len = len; stream->bufcount = bufcount; stream->bufnum = 0; stream->active = 1; stream->locked = NULL; /* create the underlying sample */ stream->samp = create_sample(bits, stereo, freq, len*bufcount*2); if (!stream->samp) { _AL_FREE(stream); return NULL; } /* fill with silence */ if (bits == 16) { unsigned short *p = stream->samp->data; for (i=0; i < len*bufcount*2 * ((stereo) ? 2 : 1); i++) p[i] = 0x8000; } else { unsigned char *p = stream->samp->data; for (i=0; i < len*bufcount*2 * ((stereo) ? 2 : 1); i++) p[i] = 0x80; } LOCK_DATA(stream, sizeof(AUDIOSTREAM)); /* play the sample in looped mode */ stream->voice = allocate_voice(stream->samp); if (stream->voice < 0) { destroy_sample(stream->samp); UNLOCK_DATA(stream, sizeof(AUDIOSTREAM)); _AL_FREE(stream); return NULL; } voice_set_playmode(stream->voice, PLAYMODE_LOOP); voice_set_volume(stream->voice, vol); voice_set_pan(stream->voice, pan); return stream; } /* stop_audio_stream: * Destroys an audio stream when it is no longer required. */ void stop_audio_stream(AUDIOSTREAM *stream) { ASSERT(stream); if ((stream->locked) && (digi_driver->unlock_voice)) digi_driver->unlock_voice(stream->voice); voice_stop(stream->voice); deallocate_voice(stream->voice); destroy_sample(stream->samp); UNLOCK_DATA(stream, sizeof(AUDIOSTREAM)); _AL_FREE(stream); } /* get_audio_stream_buffer: * Returns a pointer to the next audio buffer, or NULL if the previous * data is still playing. This must be called at regular intervals while * the stream is playing, and you must fill the return address with the * appropriate number (the same length that you specified when you create * the stream) of samples. Call free_audio_stream_buffer() after loading * the new samples, to indicate that the data is now valid. */ void *get_audio_stream_buffer(AUDIOSTREAM *stream) { int pos; char *data = NULL; ASSERT(stream); if (stream->bufnum == stream->active * stream->bufcount) { /* waiting for the sample to switch halves */ pos = voice_get_position(stream->voice); if (stream->active == 0) { if (pos < stream->len*stream->bufcount) return NULL; } else { if (pos >= stream->len*stream->bufcount) return NULL; } stream->active = 1-stream->active; } /* make sure we got access to the right bit of sample data */ if (!stream->locked) { pos = (1-stream->active) * stream->bufcount * stream->len; if (digi_driver->lock_voice) data = digi_driver->lock_voice(stream->voice, pos, pos+stream->bufcount*stream->len); if (data) stream->locked = data; else stream->locked = (char *)stream->samp->data + (pos * ((stream->samp->bits==8) ? 1 : sizeof(short)) * ((stream->samp->stereo) ? 2 : 1)); } return (char *)stream->locked + ((stream->bufnum % stream->bufcount) * stream->len * ((stream->samp->bits==8) ? 1 : sizeof(short)) * ((stream->samp->stereo) ? 2 : 1)); } /* free_audio_stream_buffer: * Indicates that a sample buffer previously returned by a call to * get_audio_stream_buffer() has now been filled with valid data. */ void free_audio_stream_buffer(AUDIOSTREAM *stream) { ASSERT(stream); /* flip buffers */ stream->bufnum++; if (stream->bufnum >= stream->bufcount*2) stream->bufnum = 0; /* unlock old waveform region */ if ((stream->locked) && ((stream->bufnum == 0) || (stream->bufnum == stream->bufcount))) { if (digi_driver->unlock_voice) digi_driver->unlock_voice(stream->voice); stream->locked = NULL; } /* start playing if it wasn't already */ if (voice_get_position(stream->voice) == -1) voice_start(stream->voice); } allegro-4.4.3.1/src/win/0000775000175000017500000000000013437077643013664 5ustar siegesiegeallegro-4.4.3.1/src/win/wtimer.c0000664000175000017500000001535613437077643015351 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows timer driver. * * By Stefan Schimanski. * * Enhanced low performance driver by Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wtimer INFO: " #define PREFIX_W "al-wtimer WARNING: " #define PREFIX_E "al-wtimer ERROR: " static TIMER_DRIVER timer_win32_high_perf; static TIMER_DRIVER timer_win32_low_perf; _DRIVER_INFO _timer_driver_list[] = { {TIMER_WIN32_HIGH_PERF, &timer_win32_high_perf, TRUE}, {TIMER_WIN32_LOW_PERF, &timer_win32_low_perf, TRUE}, {0, NULL, 0} }; static int tim_win32_high_perf_init(void); static int tim_win32_low_perf_init(void); static void tim_win32_exit(void); static void tim_win32_rest(unsigned int time, AL_METHOD(void, callback, (void))); static TIMER_DRIVER timer_win32_high_perf = { TIMER_WIN32_HIGH_PERF, empty_string, empty_string, "Win32 high performance timer", tim_win32_high_perf_init, tim_win32_exit, NULL, NULL, NULL, NULL, NULL, NULL, tim_win32_rest }; static TIMER_DRIVER timer_win32_low_perf = { TIMER_WIN32_LOW_PERF, empty_string, empty_string, "Win32 low performance timer", tim_win32_low_perf_init, tim_win32_exit, NULL, NULL, NULL, NULL, NULL, NULL, tim_win32_rest }; static HANDLE timer_thread = NULL; /* dedicated timer thread */ static HANDLE timer_stop_event = NULL; /* thread termination event */ /* high performance driver */ static LARGE_INTEGER counter_freq; static LARGE_INTEGER counter_per_msec; /* unit conversion */ #define COUNTER_TO_MSEC(x) ((unsigned long)(x / counter_per_msec.QuadPart)) #define COUNTER_TO_TIMER(x) ((unsigned long)(x * TIMERS_PER_SECOND / counter_freq.QuadPart)) #define MSEC_TO_COUNTER(x) (x * counter_per_msec.QuadPart) #define TIMER_TO_COUNTER(x) (x * counter_freq.QuadPart / TIMERS_PER_SECOND) #define TIMER_TO_MSEC(x) ((unsigned long)(x) / (TIMERS_PER_SECOND / 1000)) /* tim_win32_high_perf_thread: * Thread loop function for the high performance driver. */ static void tim_win32_high_perf_thread(void *unused) { DWORD result; unsigned long delay = 0x8000; LARGE_INTEGER curr_counter; LARGE_INTEGER prev_tick; LARGE_INTEGER diff_counter; /* init thread */ _win_thread_init(); /* get initial counter */ QueryPerformanceCounter(&prev_tick); while (TRUE) { if (!_win_app_foreground) { /* restart counter if the thread was blocked */ if (_win_thread_switch_out()) QueryPerformanceCounter(&prev_tick); } /* get current counter */ QueryPerformanceCounter(&curr_counter); /* get counter units till next tick */ diff_counter.QuadPart = curr_counter.QuadPart - prev_tick.QuadPart; /* save current counter for next tick */ prev_tick.QuadPart = curr_counter.QuadPart; /* call timer proc */ delay = _handle_timer_tick(COUNTER_TO_TIMER(diff_counter.QuadPart)); /* wait calculated time */ result = WaitForSingleObject(timer_stop_event, TIMER_TO_MSEC(delay)); if (result != WAIT_TIMEOUT) { _win_thread_exit(); return; } } } /* tim_win32_low_perf_thread: * Thread loop function for the low performance driver. */ static void tim_win32_low_perf_thread(void *unused) { DWORD result; unsigned long delay = 0x8000; DWORD prev_time; DWORD curr_time; /* in milliseconds */ DWORD diff_time; /* init thread */ _win_thread_init(); /* get initial time */ prev_time = timeGetTime(); while (TRUE) { if (!_win_app_foreground) { /* restart time if the thread was blocked */ if (_win_thread_switch_out()) prev_time = timeGetTime(); } /* get current time */ curr_time = timeGetTime(); /* get time till next tick */ diff_time = curr_time - prev_time; /* save current time for next tick */ prev_time = curr_time; /* call timer proc */ delay = _handle_timer_tick(MSEC_TO_TIMER(diff_time)); /* wait calculated time */ result = WaitForSingleObject(timer_stop_event, TIMER_TO_MSEC(delay)); if (result != WAIT_TIMEOUT) { _win_thread_exit(); return; } } } /* tim_win32_high_perf_init: * Initializes the high performance driver. */ static int tim_win32_high_perf_init(void) { if (!QueryPerformanceFrequency(&counter_freq)) { _TRACE(PREFIX_W "High performance timer not supported\n"); return -1; } /* setup high performance counter */ counter_per_msec.QuadPart = counter_freq.QuadPart / 1000; /* create thread termination event */ timer_stop_event = CreateEvent(NULL, FALSE, FALSE, NULL); /* start timer thread */ timer_thread = (void *)_beginthread(tim_win32_high_perf_thread, 0, 0); /* increase priority of timer thread */ SetThreadPriority(timer_thread, THREAD_PRIORITY_TIME_CRITICAL); return 0; } /* tim_win32_low_perf_init: * Initializes the low performance driver. */ static int tim_win32_low_perf_init(void) { /* create thread termination event */ timer_stop_event = CreateEvent(NULL, FALSE, FALSE, NULL); /* start timer thread */ timer_thread = (void *)_beginthread(tim_win32_low_perf_thread, 0, 0); /* increase priority of timer thread */ SetThreadPriority(timer_thread, THREAD_PRIORITY_TIME_CRITICAL); return 0; } /* tim_win32_exit: * Shuts down either timer driver. */ static void tim_win32_exit(void) { /* acknowledge that the thread should stop */ SetEvent(timer_stop_event); /* wait until thread has ended */ while (WaitForSingleObject(timer_thread, 100) == WAIT_TIMEOUT); /* thread has ended, now we can release all resources */ CloseHandle(timer_stop_event); } /* tim_win32_rest: * Rests the specified amount of milliseconds. */ static void tim_win32_rest(unsigned int time, AL_METHOD(void, callback, (void))) { unsigned int start; unsigned int ms = time; if (callback) { start = timeGetTime(); while (timeGetTime() - start < ms) (*callback)(); } else { Sleep(ms); } } allegro-4.4.3.1/src/win/wddbmp.c0000664000175000017500000005141313437077643015311 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw bitmap management routines. * * By Stefan Schimanski. * * Improved page flipping mechanism by Robin Burrows. * * Improved video bitmap allocation scheme by Eric Botcazou. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddbmp INFO: " #define PREFIX_W "al-wddbmp WARNING: " #define PREFIX_E "al-wddbmp ERROR: " /* The video bitmap allocation scheme works as follows: * - the screen is allocated as a single DirectDraw surface (primary or overlay, * depending on the driver) at startup, * - the first video bitmap reuses the DirectDraw surface of the screen which is * then assigned to flipping_page[0], * - the second video bitmap allocates flipping_page[1] and uses it as its * DirectDraw surface; it also destroys the single surface pointed to by * flipping_page[0] and creates a DirectDraw flipping chain whose frontbuffer * is connected back to flipping_page[0] and backbuffer to flipping_page[1], * - the third video bitmap allocates flipping_page[2] and uses it as its * DirectDraw surface; it also destroys the flipping chain pointed to by * flipping_page[0] and flipping_page[1] and creates a new flipping chain * whose frontbuffer is connected back to flipping_page[0], first backbuffer * back to flipping_page[1] and second backbuffer to flipping_page[2]. * * When a video bitmap is to be destroyed, the flipping chain (if it exists) is * destroyed and recreated with one less backbuffer, and its surfaces are assigned * back to the flipping_page[] array in order. If the video bitmap is not attached * to the surface that was just destroyed, its surface is assigned to the video * bitmap parent of the just destroyed surface. * * After triple buffering setup: * * screen video_bmp[0] video_bmp[1] video_bmp[2] * \ | | | * \ | | | * page_flipping[0] page_flipping[1] page_flipping[2] * (frontbuffer)-----(backbuffer1)-----(backbuffer2) * * After request_video_bitmap(video_bmp[1]): * * screen video_bmp[0] video_bmp[1] video_bmp[2] * \ \/ | * \ /\ | * page_flipping[0] page_flipping[1] page_flipping[2] * (frontbuffer)-----(backbuffer1)-----(backbuffer2) * * This ensures that every video bitmap keeps track of the actual part of the * video memory it represents (see the documentation of DirectDrawSurface::Flip). */ static DDRAW_SURFACE *flipping_page[3] = {NULL, NULL, NULL}; static int n_flipping_pages = 0; /* dd_err: * Returns a DirectDraw error string. */ #ifdef DEBUGMODE static char *dd_err(long err) { static char err_str[64]; switch (err) { case DD_OK: _al_sane_strncpy(err_str, "DD_OK", sizeof(err_str)); break; case DDERR_GENERIC: _al_sane_strncpy(err_str, "DDERR_GENERIC", sizeof(err_str)); break; case DDERR_INCOMPATIBLEPRIMARY: _al_sane_strncpy(err_str, "DDERR_INCOMPATIBLEPRIMARY", sizeof(err_str)); break; case DDERR_INVALIDCAPS: _al_sane_strncpy(err_str, "DDERR_INVALIDCAPS", sizeof(err_str)); break; case DDERR_INVALIDOBJECT: _al_sane_strncpy(err_str, "DDERR_INVALIDOBJECT", sizeof(err_str)); break; case DDERR_INVALIDPARAMS: _al_sane_strncpy(err_str, "DDERR_INVALIDPARAMS", sizeof(err_str)); break; case DDERR_INVALIDPIXELFORMAT: _al_sane_strncpy(err_str, "DDERR_INVALIDPIXELFORMAT", sizeof(err_str)); break; case DDERR_NOFLIPHW: _al_sane_strncpy(err_str, "DDERR_NOFLIPHW", sizeof(err_str)); break; case DDERR_NOTFLIPPABLE: _al_sane_strncpy(err_str, "DDERR_NOTFLIPPABLE", sizeof(err_str)); break; case DDERR_OUTOFMEMORY: _al_sane_strncpy(err_str, "DDERR_OUTOFMEMORY", sizeof(err_str)); break; case DDERR_OUTOFVIDEOMEMORY: _al_sane_strncpy(err_str, "DDERR_OUTOFVIDEOMEMORY", sizeof(err_str)); break; case DDERR_PRIMARYSURFACEALREADYEXISTS: _al_sane_strncpy(err_str, "DDERR_PRIMARYSURFACEALREADYEXISTS", sizeof(err_str)); break; case DDERR_SURFACEBUSY: _al_sane_strncpy(err_str, "DDERR_SURFACEBUSY", sizeof(err_str)); break; case DDERR_SURFACELOST: _al_sane_strncpy(err_str, "DDERR_SURFACELOST", sizeof(err_str)); break; case DDERR_UNSUPPORTED: _al_sane_strncpy(err_str, "DDERR_UNSUPPORTED", sizeof(err_str)); break; case DDERR_UNSUPPORTEDMODE: _al_sane_strncpy(err_str, "DDERR_UNSUPPORTEDMODE", sizeof(err_str)); break; case DDERR_WASSTILLDRAWING: _al_sane_strncpy(err_str, "DDERR_WASSTILLDRAWING", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "DDERR_UNKNOWN", sizeof(err_str)); break; } return err_str; } #else #define dd_err(hr) "\0" #endif /* create_directdraw2_surface: * Wrapper around DirectDraw2::CreateSurface taking the surface characteristics * as parameters. Returns a DirectDrawSurface2 interface if successful. */ static LPDIRECTDRAWSURFACE2 create_directdraw2_surface(int w, int h, LPDDPIXELFORMAT pixel_format, int type, int n_backbuffers) { DDSURFACEDESC ddsurf_desc; LPDIRECTDRAWSURFACE ddsurf1; LPVOID ddsurf2; HRESULT hr; /* describe surface characteristics */ memset(&ddsurf_desc, 0, sizeof(DDSURFACEDESC)); ddsurf_desc.dwSize = sizeof(DDSURFACEDESC); ddsurf_desc.dwFlags = DDSD_CAPS; switch (type) { case DDRAW_SURFACE_PRIMARY: ddsurf_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; _TRACE(PREFIX_I "Creating primary surface..."); break; case DDRAW_SURFACE_OVERLAY: ddsurf_desc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; ddsurf_desc.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH; ddsurf_desc.dwHeight = h; ddsurf_desc.dwWidth = w; if (pixel_format) { /* use pixel format */ ddsurf_desc.dwFlags |= DDSD_PIXELFORMAT; ddsurf_desc.ddpfPixelFormat = *pixel_format; } _TRACE(PREFIX_I "Creating overlay surface..."); break; case DDRAW_SURFACE_VIDEO: ddsurf_desc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN; ddsurf_desc.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH; ddsurf_desc.dwHeight = h; ddsurf_desc.dwWidth = w; _TRACE(PREFIX_I "Creating video surface..."); break; case DDRAW_SURFACE_SYSTEM: ddsurf_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; ddsurf_desc.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH; ddsurf_desc.dwHeight = h; ddsurf_desc.dwWidth = w; if (pixel_format) { /* use pixel format */ ddsurf_desc.dwFlags |= DDSD_PIXELFORMAT; ddsurf_desc.ddpfPixelFormat = *pixel_format; } _TRACE(PREFIX_I "Creating system surface..."); break; default: _TRACE(PREFIX_E "Unknown surface type\n"); return NULL; } /* set backbuffer requirements */ if (n_backbuffers > 0) { ddsurf_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP; ddsurf_desc.dwFlags |= DDSD_BACKBUFFERCOUNT; ddsurf_desc.dwBackBufferCount = n_backbuffers; _TRACE("...with %d backbuffer(s)\n", n_backbuffers); } /* create the surface */ hr = IDirectDraw2_CreateSurface(directdraw, &ddsurf_desc, &ddsurf1, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Unable to create the surface (%s)\n", dd_err(hr)); return NULL; } /* retrieve the DirectDrawSurface2 interface */ hr = IDirectDrawSurface_QueryInterface(ddsurf1, &IID_IDirectDrawSurface2, &ddsurf2); /* there is a bug in the COM part of DirectX 3: * If we release the DirectSurface interface, the actual * object is also released. It is fixed in DirectX 5. */ if (_dx_ver >= 0x500) IDirectDrawSurface_Release(ddsurf1); if (FAILED(hr)) { _TRACE(PREFIX_E "Unable to retrieve the DirectDrawSurface2 interface (%s)\n", dd_err(hr)); return NULL; } return (LPDIRECTDRAWSURFACE2)ddsurf2; } /* gfx_directx_create_surface: * Creates a DirectDraw surface. */ DDRAW_SURFACE *gfx_directx_create_surface(int w, int h, LPDDPIXELFORMAT pixel_format, int type) { DDRAW_SURFACE *surf; surf = _AL_MALLOC(sizeof(DDRAW_SURFACE)); if (!surf) return NULL; /* create the surface with the specified characteristics */ surf->id = create_directdraw2_surface(w, h, pixel_format,type, 0); if (!surf->id) { _AL_FREE(surf); return NULL; } surf->flags = type; surf->lock_nesting = 0; register_ddraw_surface(surf); return surf; } /* gfx_directx_destroy_surface: * Destroys a DirectDraw surface. */ void gfx_directx_destroy_surface(DDRAW_SURFACE *surf) { IDirectDrawSurface2_Release(surf->id); unregister_ddraw_surface(surf); _AL_FREE(surf); } /* gfx_directx_make_bitmap_from_surface: * Connects a DirectDraw surface with an Allegro bitmap. */ BITMAP *gfx_directx_make_bitmap_from_surface(DDRAW_SURFACE *surf, int w, int h, int id) { BITMAP *bmp; int i; bmp = (BITMAP *) _AL_MALLOC(sizeof(BITMAP) + sizeof(char *) * h); if (!bmp) return NULL; bmp->w =w; bmp->cr = w; bmp->h = h; bmp->cb = h; bmp->clip = TRUE; bmp->cl = 0; bmp->ct = 0; bmp->vtable = &_screen_vtable; bmp->write_bank = gfx_directx_write_bank; bmp->read_bank = gfx_directx_write_bank; bmp->dat = NULL; bmp->id = id; bmp->extra = NULL; bmp->x_ofs = 0; bmp->y_ofs = 0; bmp->seg = _video_ds(); for (i = 0; i < h; i++) bmp->line[i] = pseudo_surf_mem; bmp->extra = surf; return bmp; } /* gfx_directx_created_sub_bitmap: */ void gfx_directx_created_sub_bitmap(BITMAP *bmp, BITMAP *parent) { bmp->extra = parent; } /* recreate_flipping_chain: * Destroys the previous flipping chain and creates a new one. */ static int recreate_flipping_chain(int n_pages) { int w, h, type, n_backbuffers; DDSCAPS ddscaps; HRESULT hr; ASSERT(n_pages > 0); /* set flipping chain characteristics */ w = gfx_directx_forefront_bitmap->w; h = gfx_directx_forefront_bitmap->h; type = flipping_page[0]->flags & DDRAW_SURFACE_TYPE_MASK; n_backbuffers = n_pages - 1; /* release existing flipping chain */ if (flipping_page[0]->id) { hr = IDirectDrawSurface2_Release(flipping_page[0]->id); if (FAILED(hr)) { _TRACE(PREFIX_E "Unable to release the primary surface (%s)", dd_err(hr)); return -1; } } /* create the new flipping chain with the specified characteristics */ flipping_page[0]->id = create_directdraw2_surface(w, h, ddpixel_format, type, n_backbuffers); if (!flipping_page[0]->id) return -1; /* retrieve the backbuffers */ if (n_backbuffers > 0) { memset(&ddscaps, 0, sizeof(DDSCAPS)); /* first backbuffer */ ddscaps.dwCaps = DDSCAPS_BACKBUFFER; hr = IDirectDrawSurface2_GetAttachedSurface(flipping_page[0]->id, &ddscaps, &flipping_page[1]->id); if (FAILED(hr)) { _TRACE(PREFIX_E "Unable to retrieve the first backbuffer (%s)", dd_err(hr)); return -1; } flipping_page[1]->flags = flipping_page[0]->flags; flipping_page[1]->lock_nesting = 0; if (n_backbuffers > 1) { /* second backbuffer */ ddscaps.dwCaps = DDSCAPS_FLIP; hr = IDirectDrawSurface2_GetAttachedSurface(flipping_page[1]->id, &ddscaps, &flipping_page[2]->id); if (FAILED(hr)) { _TRACE(PREFIX_E "Unable to retrieve the second backbuffer (%s)", dd_err(hr)); return -1; } flipping_page[2]->flags = flipping_page[0]->flags; flipping_page[2]->lock_nesting = 0; } } /* attach the global palette if needed */ if (flipping_page[0]->flags & DDRAW_SURFACE_INDEXED) { hr = IDirectDrawSurface2_SetPalette(flipping_page[0]->id, ddpalette); if (FAILED(hr)) { _TRACE(PREFIX_E "Unable to attach the global palette (%s)", dd_err(hr)); return -1; } } return 0; } /* gfx_directx_create_video_bitmap: */ BITMAP *gfx_directx_create_video_bitmap(int width, int height) { DDRAW_SURFACE *surf; BITMAP *bmp; /* try to detect page flipping and triple buffering patterns */ if ((width == gfx_directx_forefront_bitmap->w) && (height == gfx_directx_forefront_bitmap->h)) { switch (n_flipping_pages) { case 0: /* recycle the forefront surface as the first flipping page */ flipping_page[0] = DDRAW_SURFACE_OF(gfx_directx_forefront_bitmap); bmp = gfx_directx_make_bitmap_from_surface(flipping_page[0], width, height, BMP_ID_VIDEO); if (bmp) { flipping_page[0]->parent_bmp = bmp; n_flipping_pages++; return bmp; } else { flipping_page[0] = NULL; return NULL; } case 1: case 2: /* try to attach an additional page to the flipping chain */ flipping_page[n_flipping_pages] = _AL_MALLOC(sizeof(DDRAW_SURFACE)); if (recreate_flipping_chain(n_flipping_pages+1) == 0) { bmp = gfx_directx_make_bitmap_from_surface(flipping_page[n_flipping_pages], width, height, BMP_ID_VIDEO); if (bmp) { flipping_page[n_flipping_pages]->parent_bmp = bmp; n_flipping_pages++; return bmp; } } recreate_flipping_chain(n_flipping_pages); _AL_FREE(flipping_page[n_flipping_pages]); flipping_page[n_flipping_pages] = NULL; return NULL; } } /* create the DirectDraw surface */ if (ddpixel_format) surf = gfx_directx_create_surface(width, height, ddpixel_format, DDRAW_SURFACE_SYSTEM); else surf = gfx_directx_create_surface(width, height, NULL, DDRAW_SURFACE_VIDEO); if (!surf) return NULL; /* create the bitmap that wraps up the surface */ bmp = gfx_directx_make_bitmap_from_surface(surf, width, height, BMP_ID_VIDEO); if (!bmp) { gfx_directx_destroy_surface(surf); return NULL; } return bmp; } /* gfx_directx_destroy_video_bitmap: */ void gfx_directx_destroy_video_bitmap(BITMAP *bmp) { DDRAW_SURFACE *surf, *tail_page; surf = DDRAW_SURFACE_OF(bmp); if ((surf == flipping_page[0]) || (surf == flipping_page[1]) || (surf == flipping_page[2])) { /* handle surfaces belonging to the flipping chain */ if (--n_flipping_pages > 0) { tail_page = flipping_page[n_flipping_pages]; /* If the surface attached to the bitmap is not the tail page * that is to be destroyed, attach it to the bitmap whose * attached surface is the tail page. */ if (surf != tail_page) { surf->parent_bmp = tail_page->parent_bmp; surf->parent_bmp->extra = surf; } /* remove the tail page from the flipping chain */ recreate_flipping_chain(n_flipping_pages); _AL_FREE(tail_page); } flipping_page[n_flipping_pages] = NULL; } else { /* destroy the surface */ gfx_directx_destroy_surface(surf); } _AL_FREE(bmp); } /* flip_with_forefront_bitmap: * Worker function for DirectDraw page flipping. */ static int flip_with_forefront_bitmap(BITMAP *bmp, int wait) { DDRAW_SURFACE *surf; HRESULT hr; /* flip only in the foreground */ if (!_win_app_foreground) { _win_thread_switch_out(); return 0; } /* retrieve the underlying surface */ surf = DDRAW_SURFACE_OF(bmp); if (surf == flipping_page[0]) return 0; ASSERT((surf == flipping_page[1]) || (surf == flipping_page[2])); /* flip the contents of the surfaces */ hr = IDirectDrawSurface2_Flip(flipping_page[0]->id, surf->id, wait ? DDFLIP_WAIT : 0); /* if the surface has been lost, try to restore all surfaces */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_Flip(flipping_page[0]->id, surf->id, wait ? DDFLIP_WAIT : 0); } if (FAILED(hr)) { _TRACE(PREFIX_E "Can't flip (%s)\n", dd_err(hr)); return -1; } /* attach the surface to the former forefront bitmap */ surf->parent_bmp = flipping_page[0]->parent_bmp; surf->parent_bmp->extra = surf; /* make the bitmap point to the forefront surface */ flipping_page[0]->parent_bmp = bmp; bmp->extra = flipping_page[0]; return 0; } /* gfx_directx_show_video_bitmap: */ int gfx_directx_show_video_bitmap(BITMAP *bmp) { /* guard against show_video_bitmap(screen); */ if (bmp == gfx_directx_forefront_bitmap) return 0; return flip_with_forefront_bitmap(bmp, _wait_for_vsync); } /* gfx_directx_request_video_bitmap: */ int gfx_directx_request_video_bitmap(BITMAP *bmp) { /* guard against request_video_bitmap(screen); */ if (bmp == gfx_directx_forefront_bitmap) return 0; return flip_with_forefront_bitmap(bmp, FALSE); } /* gfx_directx_poll_scroll: */ int gfx_directx_poll_scroll(void) { HRESULT hr; ASSERT(n_flipping_pages == 3); hr = IDirectDrawSurface2_GetFlipStatus(flipping_page[0]->id, DDGFS_ISFLIPDONE); /* if the surface has been lost, try to restore all surfaces */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_GetFlipStatus(flipping_page[0]->id, DDGFS_ISFLIPDONE); } if (FAILED(hr)) return -1; return 0; } /* gfx_directx_create_system_bitmap: */ BITMAP *gfx_directx_create_system_bitmap(int width, int height) { DDRAW_SURFACE *surf; BITMAP *bmp; /* create the DirectDraw surface */ surf = gfx_directx_create_surface(width, height, ddpixel_format, DDRAW_SURFACE_SYSTEM); if (!surf) return NULL; /* create the bitmap that wraps up the surface */ bmp = gfx_directx_make_bitmap_from_surface(surf, width, height, BMP_ID_SYSTEM); if (!bmp) { gfx_directx_destroy_surface(surf); return NULL; } return bmp; } /* gfx_directx_destroy_system_bitmap: */ void gfx_directx_destroy_system_bitmap(BITMAP *bmp) { /* Special case: use normal destroy_bitmap() for subbitmaps of system * bitmaps. Checked here rather than in destroy_bitmap() because that * function should not make assumptions about the relation between system * bitmaps and subbitmaps thereof. This duplicates code though and a * different solution would be better. */ if (is_sub_bitmap(bmp)) { if (system_driver->destroy_bitmap) { if (system_driver->destroy_bitmap(bmp)) return; } if (bmp->dat) _AL_FREE(bmp->dat); _AL_FREE(bmp); return; } /* destroy the surface */ gfx_directx_destroy_surface(DDRAW_SURFACE_OF(bmp)); _AL_FREE(bmp); } /* win_get_dc: (WinAPI) * Returns device context of a video or system bitmap. */ HDC win_get_dc(BITMAP *bmp) { LPDIRECTDRAWSURFACE2 ddsurf; HDC dc; HRESULT hr; if (bmp) { if (bmp->id & (BMP_ID_SYSTEM | BMP_ID_VIDEO)) { ddsurf = DDRAW_SURFACE_OF(bmp)->id; hr = IDirectDrawSurface2_GetDC(ddsurf, &dc); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to get the DC. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_GetDC(ddsurf, &dc); } if (hr == DD_OK) return dc; } } return NULL; } /* win_release_dc: (WinAPI) * Releases device context of a video or system bitmap. */ void win_release_dc(BITMAP *bmp, HDC dc) { LPDIRECTDRAWSURFACE2 ddsurf; HRESULT hr; if (bmp) { if (bmp->id & (BMP_ID_SYSTEM | BMP_ID_VIDEO)) { ddsurf = DDRAW_SURFACE_OF(bmp)->id; hr = IDirectDrawSurface2_ReleaseDC(ddsurf, dc); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to release the DC. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_ReleaseDC(ddsurf, dc); } } } } allegro-4.4.3.1/src/win/wddfull.c0000664000175000017500000002251413437077643015475 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw gfx fullscreen drivers. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "wddraw.h" static struct BITMAP *init_directx_accel(int w, int h, int v_w, int v_h, int color_depth); static struct BITMAP *init_directx_soft(int w, int h, int v_w, int v_h, int color_depth); static struct BITMAP *init_directx_safe(int w, int h, int v_w, int v_h, int color_depth); static void finalize_fullscreen_init(void); static void switch_in_fullscreen(void); static void switch_out_fullscreen(void); GFX_DRIVER gfx_directx_accel = { GFX_DIRECTX_ACCEL, empty_string, empty_string, "DirectDraw accel", init_directx_accel, gfx_directx_exit, NULL, // AL_METHOD(int, scroll, (int x, int y)); gfx_directx_sync, gfx_directx_set_palette, NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); gfx_directx_create_video_bitmap, gfx_directx_destroy_video_bitmap, gfx_directx_show_video_bitmap, gfx_directx_request_video_bitmap, gfx_directx_create_system_bitmap, gfx_directx_destroy_system_bitmap, NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_video_state, (void*)); NULL, // AL_METHOD(void, restore_video_state, (void*)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); gfx_directx_fetch_mode_list, 0, 0, // physical (not virtual!) screen size TRUE, // true if video memory is linear 0, // bank size, in bytes 0, // bank granularity, in bytes 0, // video memory size, in bytes 0, // physical address of video memory FALSE // true if driver runs windowed }; GFX_DRIVER gfx_directx_soft = { GFX_DIRECTX_SOFT, empty_string, empty_string, "DirectDraw soft", init_directx_soft, gfx_directx_exit, NULL, // AL_METHOD(int, scroll, (int x, int y)); gfx_directx_sync, gfx_directx_set_palette, NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); gfx_directx_create_video_bitmap, gfx_directx_destroy_video_bitmap, gfx_directx_show_video_bitmap, gfx_directx_request_video_bitmap, gfx_directx_create_system_bitmap, gfx_directx_destroy_system_bitmap, NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_video_state, (void*)); NULL, // AL_METHOD(void, restore_video_state, (void*)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); gfx_directx_fetch_mode_list, 0, 0, // physical (not virtual!) screen size TRUE, // true if video memory is linear 0, // bank size, in bytes 0, // bank granularity, in bytes 0, // video memory size, in bytes 0, // physical address of video memory FALSE // true if driver runs windowed }; GFX_DRIVER gfx_directx_safe = { GFX_DIRECTX_SAFE, empty_string, empty_string, "DirectDraw safe", init_directx_safe, gfx_directx_exit, NULL, // AL_METHOD(int, scroll, (int x, int y)); gfx_directx_sync, gfx_directx_set_palette, NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, NULL, NULL, NULL, NULL, NULL, NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_video_state, (void*)); NULL, // AL_METHOD(void, restore_video_state, (void*)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); gfx_directx_fetch_mode_list, 0, 0, // physical (not virtual!) screen size TRUE, // true if video memory is linear 0, // bank size, in bytes 0, // bank granularity, in bytes 0, // video memory size, in bytes 0, // physical address of video memory FALSE // true if driver runs windowed }; static WIN_GFX_DRIVER win_gfx_fullscreen = { FALSE, // true if driver has backing store switch_in_fullscreen, switch_out_fullscreen, NULL, // AL_METHOD(void, enter_sysmode, (void)); NULL, // AL_METHOD(void, exit_sysmode, (void)); NULL, // AL_METHOD(void, move, (int x, int y, int w, int h)); NULL, // AL_METHOD(void, iconify, (void)); NULL // AL_METHOD(void, paint, (RECT *)); }; /* When switching away from an 8-bit fullscreen program, the palette is lost. * This stores the palette so it can be restored when switching back in. */ static PALETTE wddfull_saved_palette; /* init_directx_accel: * Initializes the DirectDraw fullscreen hardware-accelerated driver. */ static struct BITMAP *init_directx_accel(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; _enter_critical(); bmp = gfx_directx_init(&gfx_directx_accel, w, h, v_w, v_h, color_depth); if (bmp) { gfx_directx_enable_acceleration(&gfx_directx_accel); gfx_directx_enable_triple_buffering(&gfx_directx_accel); finalize_fullscreen_init(); } _exit_critical(); return bmp; } /* init_directx_soft: * Initializes the DirectDraw fullscreen software-only driver. */ static struct BITMAP *init_directx_soft(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; _enter_critical(); bmp = gfx_directx_init(&gfx_directx_soft, w, h, v_w, v_h, color_depth); if (bmp) { gfx_directx_enable_triple_buffering(&gfx_directx_soft); finalize_fullscreen_init(); } _exit_critical(); return bmp; } /* init_directx_safe: * Initializes the DirectDraw fullscreen safe driver. */ static struct BITMAP *init_directx_safe(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; _enter_critical(); bmp = gfx_directx_init(&gfx_directx_safe, w, h, v_w, v_h, color_depth); if (bmp) finalize_fullscreen_init(); _exit_critical(); return bmp; } /* finalize_fullscreen_init: * Finalizes initialization of the three fullscreen drivers. */ static void finalize_fullscreen_init(void) { /* connect to the system driver */ win_gfx_driver = &win_gfx_fullscreen; /* set the default switching policy */ set_display_switch_mode(SWITCH_AMNESIA); /* grab input devices */ win_grab_input(); } /* switch_in_fullscreen: * Handles screen switched in. */ static void switch_in_fullscreen(void) { restore_all_ddraw_surfaces(); if (_color_depth == 8) set_palette(wddfull_saved_palette); } /* switch_out_fullscreen: * Handles screen switched out. */ static void switch_out_fullscreen(void) { if (_color_depth == 8) get_palette(wddfull_saved_palette); } allegro-4.4.3.1/src/win/wsnddrv.c0000664000175000017500000000176313437077643015526 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of Windows sound drivers, kept in a seperate file so that * they can be overriden by user programs. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif BEGIN_DIGI_DRIVER_LIST /* nothing here: the driver list is dynamically generated */ END_DIGI_DRIVER_LIST BEGIN_MIDI_DRIVER_LIST /* nothing here: the driver list is dynamically generated */ END_MIDI_DRIVER_LIST allegro-4.4.3.1/src/win/wmidi.c0000664000175000017500000002015413437077643015143 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows midi driver. * * By Stefan Schimanski. * * Midi input added by Daniel Verkamp. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #ifdef ALLEGRO_MSVC #include #endif #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wmidi INFO: " #define PREFIX_W "al-wmidi WARNING: " #define PREFIX_E "al-wmidi ERROR: " int midi_win32_detect(int input); int midi_win32_init(int input, int voices); void midi_win32_exit(int input); int midi_win32_set_mixer_volume(int volume); int midi_win32_get_mixer_volume(void); void midi_win32_raw_midi(int data); int midi_win32_in_detect(int input); int midi_win32_in_init(int input, int voices); void midi_win32_in_exit(int input); static void CALLBACK midi_in_proc(HMIDIIN, UINT, DWORD, DWORD, DWORD); /* driver globals */ static HMIDIOUT midi_device = NULL; static HMIDIIN midi_in_device = NULL; /* dynamically generated driver list */ static _DRIVER_INFO *driver_list = NULL; /* MIDI recording callback */ static void CALLBACK midi_in_proc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { if ((midi_in_device == NULL) || (midi_recorder == NULL)) return; midi_recorder((unsigned char)(dwParam1 & 0xff)); /* status byte */ midi_recorder((unsigned char)((dwParam1 >> 8) & 0xff)); /* data byte 1 */ midi_recorder((unsigned char)((dwParam1 >> 16) & 0xff)); /* data byte 2 */ } /* _get_win_midi_driver_list: * System driver hook for listing the available MIDI drivers. This generates * the device list at runtime, to match whatever Windows devices are * available. */ _DRIVER_INFO *_get_win_midi_driver_list(void) { MIDI_DRIVER *driver; MIDIOUTCAPS caps; MIDIINCAPS caps_in; int num_drivers, i; if (!driver_list) { num_drivers = midiOutGetNumDevs(); /* include the MIDI mapper (id == -1) */ if (num_drivers) num_drivers++; driver_list = _create_driver_list(); /* MidiOut drivers */ for (i=0; iid = MIDI_WIN32MAPPER; else driver->id = MIDI_WIN32(i-1); midiOutGetDevCaps(i-1, &caps, sizeof(caps)); driver->ascii_name = strdup(caps.szPname); driver->detect = midi_win32_detect; driver->init = midi_win32_init; driver->exit = midi_win32_exit; driver->set_mixer_volume = midi_win32_set_mixer_volume; driver->get_mixer_volume = midi_win32_get_mixer_volume; driver->raw_midi = midi_win32_raw_midi; _driver_list_append_driver(&driver_list, driver->id, driver, TRUE); } /* MidiIn drivers */ num_drivers = midiInGetNumDevs(); for (i=0; iid = MIDI_WIN32_IN(i); /* added MIDI_WIN32_IN to alwin.h */ midiInGetDevCaps(i, &caps_in, sizeof(caps_in)); driver->ascii_name = strdup(caps_in.szPname); driver->detect = midi_win32_in_detect; driver->init = midi_win32_in_init; driver->exit = midi_win32_in_exit; _driver_list_append_driver(&driver_list, driver->id, driver, TRUE); } /* cross-platform DIGital MIDi driver */ _driver_list_append_driver(&driver_list, MIDI_DIGMID, &midi_digmid, TRUE); } return driver_list; } /* _free_win_midi_driver_list: * Helper function for freeing the dynamically generated driver list. */ void _free_win_midi_driver_list(void) { int i = 0; if (driver_list) { while (driver_list[i].driver) { if (driver_list[i].id != MIDI_DIGMID) { _AL_FREE((char*)((MIDI_DRIVER*)driver_list[i].driver)->ascii_name); _AL_FREE(driver_list[i].driver); } i++; } _destroy_driver_list(driver_list); driver_list = NULL; } } /* midi_win32_detect: */ int midi_win32_detect(int input) { /* the input drivers are separate from the output drivers */ if (input) return FALSE; return TRUE; } /* midi_win32_in_detect: */ int midi_win32_in_detect(int input) { if (input) return TRUE; return FALSE; } /* midi_win32_init: */ int midi_win32_init(int input, int voices) { MMRESULT hr; int id; /* deduce our device number from the driver ID code */ if ((midi_driver->id & 0xFF) == 'M') /* we are using the midi mapper (driver id is WIN32M) */ id = MIDI_MAPPER; else /* actual driver */ id = (midi_driver->id & 0xFF) - 'A'; /* open midi mapper */ hr = midiOutOpen(&midi_device, id, 0, 0, CALLBACK_NULL); if (hr != MMSYSERR_NOERROR) { _TRACE(PREFIX_E "midiOutOpen failed (%x)\n", hr); goto Error; } /* resets midi mapper */ midiOutReset(midi_device); return 0; Error: midi_win32_exit(input); return -1; } /* midi_win32_in_init: */ int midi_win32_in_init(int input, int voices) { MMRESULT hr; int id; /* deduce our device number from the driver ID code */ id = (midi_input_driver->id & 0xFF) - 'A'; /* open midi input device */ hr = midiInOpen(&midi_in_device, id, (DWORD)midi_in_proc, (DWORD)NULL, CALLBACK_FUNCTION); if (hr != MMSYSERR_NOERROR) { _TRACE(PREFIX_E "midiInOpen failed (%x)\n", hr); midi_win32_in_exit(input); return -1; } midiInReset(midi_in_device); midiInStart(midi_in_device); return 0; } /* midi_win32_exit: */ void midi_win32_exit(int input) { /* close midi stream and release device */ if (midi_device != NULL) { midiOutReset(midi_device); midiOutClose(midi_device); midi_device = NULL; } } /* midi_win32_in_exit: */ void midi_win32_in_exit(int input) { if (midi_in_device != NULL) { midiInStop(midi_in_device); midiInReset(midi_in_device); midiInClose(midi_in_device); midi_in_device = NULL; } } /* midi_win32_set_mixer_volume: */ int midi_win32_set_mixer_volume(int volume) { unsigned long win32_midi_vol = (volume << 8) + (volume << 24); midiOutSetVolume(midi_device, win32_midi_vol); return 1; } /* midi_win32_get_mixer_volume: */ int midi_win32_get_mixer_volume(void) { DWORD vol; if (!midi_device) return -1; if (midiOutGetVolume(midi_device, &vol) != MMSYSERR_NOERROR) return -1; vol &= 0xffff; return vol / (0xffff / 255); } /* midi_switch_out: */ void midi_switch_out(void) { if (midi_device) midiOutReset(midi_device); } /* midi_win32_raw_midi: */ void midi_win32_raw_midi(int data) { static int msg_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 0}; static unsigned long midi_msg; static int midi_msg_len; static int midi_msg_pos; if (data >= 0x80) { midi_msg_len = msg_lengths[(data >> 4) & 0x07]; midi_msg = 0; midi_msg_pos = 0; } if (midi_msg_len > 0) { midi_msg |= ((unsigned long)data) << (midi_msg_pos * 8); midi_msg_pos++; if (midi_msg_pos == midi_msg_len) { if (midi_device != NULL) { switch (get_display_switch_mode()) { case SWITCH_AMNESIA: case SWITCH_PAUSE: if (_win_app_foreground) midiOutShortMsg(midi_device, midi_msg); else midiOutReset(midi_device); break; default: midiOutShortMsg(midi_device, midi_msg); } } } } } allegro-4.4.3.1/src/win/wjoydx.c0000664000175000017500000003414513437077643015363 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows DirectInput joystick driver. * * By Eric Botcazou. * * Omar Cornut fixed it to handle a weird peculiarity of * the DirectInput joystick API. * * See readme.txt for copyright information. */ #define DIRECTINPUT_VERSION 0x0500 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wjoy INFO: " #define PREFIX_W "al-wjoy WARNING: " #define PREFIX_E "al-wjoy ERROR: " static int joystick_dinput_init(void); static void joystick_dinput_exit(void); static int joystick_dinput_poll(void); JOYSTICK_DRIVER joystick_directx = { JOY_TYPE_DIRECTX, empty_string, empty_string, "DirectInput joystick", joystick_dinput_init, joystick_dinput_exit, joystick_dinput_poll, NULL, NULL, NULL, NULL }; struct DINPUT_JOYSTICK_INFO { WINDOWS_JOYSTICK_INFO_MEMBERS LPDIRECTINPUTDEVICE2 device; }; static LPDIRECTINPUT joystick_dinput = NULL; static struct DINPUT_JOYSTICK_INFO dinput_joystick[MAX_JOYSTICKS]; static int dinput_joy_num = 0; /* dinput_err_str: * Returns a DirectInput error string. */ #ifdef DEBUGMODE static char* dinput_err_str(long err) { static char err_str[64]; switch (err) { case DIERR_NOTACQUIRED: _al_sane_strncpy(err_str, "the device is not acquired", sizeof(err_str)); break; case DIERR_INPUTLOST: _al_sane_strncpy(err_str, "access to the device was not granted", sizeof(err_str)); break; case DIERR_INVALIDPARAM: _al_sane_strncpy(err_str, "the device does not have a selected data format", sizeof(err_str)); break; case DIERR_OTHERAPPHASPRIO: _al_sane_strncpy(err_str, "can't acquire the device in background", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "unknown error", sizeof(err_str)); } return err_str; } #else #define dinput_err_str(hr) "\0" #endif /* joystick_dinput_acquire: [window thread] * Acquires the joystick devices. */ int joystick_dinput_acquire(void) { HRESULT hr; int i; if (joystick_dinput) { for (i=0; iguidType, &GUID_XAxis, sizeof(GUID)) == 0) { joy->axis_name[0] = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_YAxis, sizeof(GUID)) == 0) { joy->axis_name[1] = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0) { joy->axis_name[2] = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->caps |= JOYCAPS_HASZ; joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0) { joy->axis_name[joy->num_axes] = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->caps |= JOYCAPS_HASR; joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_Slider, sizeof(GUID)) == 0) { if (joy->caps & JOYCAPS_HASV) { /* we support at most 2 sliders */ return DIENUM_CONTINUE; } else { if (joy->caps & JOYCAPS_HASU) joy->caps |= JOYCAPS_HASV; else joy->caps |= JOYCAPS_HASU; joy->axis_name[joy->num_axes] = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_axes++; } } else if (memcmp(&lpddoi->guidType, &GUID_POV, sizeof(GUID)) == 0) { if (joy->caps & JOYCAPS_HASPOV) { /* we support at most 1 point-of-view device */ return DIENUM_CONTINUE; } else { joy->hat_name = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->caps |= JOYCAPS_HASPOV; } } else if (memcmp(&lpddoi->guidType, &GUID_Button, sizeof(GUID)) == 0) { if (joy->num_buttons == MAX_JOYSTICK_BUTTONS-1) { return DIENUM_CONTINUE; } else { joy->button_name[joy->num_buttons] = _al_ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_buttons++; } } return DIENUM_CONTINUE; } /* joystick_enum_callback: * Helper function to find out how many joysticks we have and set them up. */ static BOOL CALLBACK joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { LPDIRECTINPUTDEVICE _dinput_device1; LPDIRECTINPUTDEVICE2 dinput_device = NULL; HRESULT hr; LPVOID temp; HWND allegro_wnd = win_get_window(); DIPROPRANGE property_range = { /* the header */ { sizeof(DIPROPRANGE), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ 0, // lMin 256 // lMax }; DIPROPDWORD property_deadzone = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ 2000, // dwData }; if (dinput_joy_num == MAX_JOYSTICKS-1) { _TRACE(PREFIX_W "The system supports more than %d joysticks\n", MAX_JOYSTICKS); return DIENUM_STOP; } /* create the DirectInput joystick device */ hr = IDirectInput_CreateDevice(joystick_dinput, &lpddi->guidInstance, &_dinput_device1, NULL); if (FAILED(hr)) goto Error; /* query the DirectInputDevice2 interface needed for the poll() method */ hr = IDirectInputDevice_QueryInterface(_dinput_device1, &IID_IDirectInputDevice2, &temp); IDirectInputDevice_Release(_dinput_device1); if (FAILED(hr)) goto Error; dinput_device = temp; /* set cooperative level */ hr = IDirectInputDevice2_SetCooperativeLevel(dinput_device, allegro_wnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if (FAILED(hr)) goto Error; /* enumerate objects available on the device */ memset(&dinput_joystick[dinput_joy_num], 0, sizeof(struct DINPUT_JOYSTICK_INFO)); hr = IDirectInputDevice2_EnumObjects(dinput_device, object_enum_callback, &dinput_joystick[dinput_joy_num], DIDFT_PSHBUTTON | DIDFT_AXIS | DIDFT_POV); if (FAILED(hr)) goto Error; /* set data format */ hr = IDirectInputDevice2_SetDataFormat(dinput_device, &c_dfDIJoystick); if (FAILED(hr)) goto Error; /* set the range of axes */ hr = IDirectInputDevice2_SetProperty(dinput_device, DIPROP_RANGE, &property_range.diph); if (FAILED(hr)) goto Error; /* set the dead zone of axes */ hr = IDirectInputDevice2_SetProperty(dinput_device, DIPROP_DEADZONE, &property_deadzone.diph); if (FAILED(hr)) goto Error; /* register this joystick */ dinput_joystick[dinput_joy_num].device = dinput_device; if (win_add_joystick((WINDOWS_JOYSTICK_INFO *)&dinput_joystick[dinput_joy_num]) != 0) return DIENUM_STOP; dinput_joy_num++; return DIENUM_CONTINUE; Error: if (dinput_device) IDirectInputDevice2_Release(dinput_device); return DIENUM_CONTINUE; } /* joystick_dinput_init: [primary thread] * Initialises the DirectInput joystick devices. */ static int joystick_dinput_init(void) { HRESULT hr; /* the DirectInput joystick interface is not part of DirectX 3 */ if (_dx_ver < 0x0500) return -1; /* get the DirectInput interface */ hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput, (void**)&joystick_dinput); if (FAILED(hr)) return -1; hr = IDirectInput_Initialize(joystick_dinput, allegro_inst, DIRECTINPUT_VERSION); if (FAILED(hr)) { IDirectInput_Release(joystick_dinput); return -1; } /* enumerate the joysticks attached to the system */ hr = IDirectInput_EnumDevices(joystick_dinput, DIDEVTYPE_JOYSTICK, joystick_enum_callback, NULL, DIEDFL_ATTACHEDONLY); if (FAILED(hr)) { IDirectInput_Release(joystick_dinput); return -1; } /* acquire the devices */ wnd_call_proc(joystick_dinput_acquire); return (dinput_joy_num == 0); } /* joystick_dinput_exit: [primary thread] * Shuts down the DirectInput joystick devices. */ static void joystick_dinput_exit(void) { int i, j; /* unacquire the devices */ wnd_call_proc(joystick_dinput_unacquire); /* destroy the devices */ for (i=0; iy_ofs +line] = 1; if (!(bmp->id & BMP_ID_LOCKED)) gfx_gdi_autolock(bmp); return (uintptr_t) bmp->line[line]; } void gfx_gdi_unwrite_bank(BITMAP *bmp) { if (!(bmp->id & BMP_ID_AUTOLOCK)) return; gfx_gdi_unlock(bmp); bmp->id &= ~ BMP_ID_AUTOLOCK; } #else /* !defined(ALLEGRO_NO_ASM) */ /* asmlock.s requires these two variables */ void (*ptr_gfx_gdi_autolock)(struct BITMAP* bmp) = gfx_gdi_autolock; void (*ptr_gfx_gdi_unlock)(struct BITMAP* bmp) = gfx_gdi_unlock; /* wddraw.h, despite its name, includes the exports from asmlock.s */ #include "wddraw.h" #endif /* !defined(ALLEGRO_NO_ASM) */ static struct BITMAP *gfx_gdi_init(int w, int h, int v_w, int v_h, int color_depth); static void gfx_gdi_exit(struct BITMAP *b); static void gfx_gdi_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); static void gfx_gdi_vsync(void); /* hardware mouse cursor emulation */ static int gfx_gdi_set_mouse_sprite(struct BITMAP *sprite, int xfocus, int yfocus); static int gfx_gdi_show_mouse(struct BITMAP *bmp, int x, int y); static void gfx_gdi_hide_mouse(void); static void gfx_gdi_move_mouse(int x, int y); GFX_DRIVER gfx_gdi = { GFX_GDI, empty_string, empty_string, "GDI", gfx_gdi_init, gfx_gdi_exit, NULL, // AL_METHOD(int, scroll, (int x, int y)); gfx_gdi_vsync, gfx_gdi_set_palette, NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, NULL, NULL, NULL, NULL, NULL, gfx_gdi_set_mouse_sprite, gfx_gdi_show_mouse, gfx_gdi_hide_mouse, gfx_gdi_move_mouse, NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_video_state, (void*)); NULL, // AL_METHOD(void, restore_video_state, (void*)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, // AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; TRUE, // int linear; 0, // long bank_size; 0, // long bank_gran; 0, // long vid_mem; 0, // long vid_phys_base; TRUE // int windowed; }; static void gdi_enter_sysmode(void); static void gdi_exit_sysmode(void); static void gdi_update_window(RECT *rect); static WIN_GFX_DRIVER win_gfx_driver_gdi = { TRUE, NULL, // AL_METHOD(void, switch_in, (void)); NULL, // AL_METHOD(void, switch_out, (void)); gdi_enter_sysmode, gdi_exit_sysmode, NULL, // AL_METHOD(void, move, (int x, int y, int w, int h)); NULL, // AL_METHOD(void, iconify, (void)); gdi_update_window }; static char *screen_surf; static BITMAP *gdi_screen; static int lock_nesting = 0; static int render_semaphore = FALSE; static PALETTE palette; static HANDLE vsync_event = NULL; #define RENDER_DELAY (1000/70) /* 70 Hz */ /* hardware mouse cursor emulation */ static int mouse_on = FALSE; static int mouse_was_on = FALSE; static BITMAP *wgdi_mouse_sprite = NULL; static BITMAP *mouse_frontbuffer = NULL; static BITMAP *mouse_backbuffer = NULL; static int mouse_xfocus, mouse_yfocus; static int mouse_xpos, mouse_ypos; /* gfx_gdi_set_mouse_sprite: */ static int gfx_gdi_set_mouse_sprite(struct BITMAP *sprite, int xfocus, int yfocus) { if (wgdi_mouse_sprite) { destroy_bitmap(wgdi_mouse_sprite); wgdi_mouse_sprite = NULL; destroy_bitmap(mouse_frontbuffer); mouse_frontbuffer = NULL; destroy_bitmap(mouse_backbuffer); mouse_backbuffer = NULL; } wgdi_mouse_sprite = create_bitmap(sprite->w, sprite->h); blit(sprite, wgdi_mouse_sprite, 0, 0, 0, 0, sprite->w, sprite->h); mouse_xfocus = xfocus; mouse_yfocus = yfocus; mouse_frontbuffer = create_bitmap(sprite->w, sprite->h); mouse_backbuffer = create_bitmap(sprite->w, sprite->h); return 0; } /* update_mouse_pointer: * Worker function that updates the mouse pointer. */ static void update_mouse_pointer(int x, int y, int retrace) { HDC hdc; HWND allegro_wnd = win_get_window(); /* put the screen contents located at the new position into the frontbuffer */ blit(gdi_screen, mouse_frontbuffer, x, y, 0, 0, mouse_frontbuffer->w, mouse_frontbuffer->h); /* draw the mouse pointer onto the frontbuffer */ draw_sprite(mouse_frontbuffer, wgdi_mouse_sprite, 0, 0); hdc = GetDC(allegro_wnd); if (_color_depth == 8) set_palette_to_hdc(hdc, palette); if (retrace) { /* restore the screen contents located at the old position */ blit_to_hdc(mouse_backbuffer, hdc, 0, 0, mouse_xpos, mouse_ypos, mouse_backbuffer->w, mouse_backbuffer->h); } /* blit the mouse pointer onto the screen */ blit_to_hdc(mouse_frontbuffer, hdc, 0, 0, x, y, mouse_frontbuffer->w, mouse_frontbuffer->h); ReleaseDC(allegro_wnd, hdc); /* save the screen contents located at the new position into the backbuffer */ blit(gdi_screen, mouse_backbuffer, x, y, 0, 0, mouse_backbuffer->w, mouse_backbuffer->h); /* save the new position */ mouse_xpos = x; mouse_ypos = y; } /* gfx_gdi_show_mouse: */ static int gfx_gdi_show_mouse(struct BITMAP *bmp, int x, int y) { /* handle only the screen */ if (bmp != gdi_screen) return -1; mouse_on = TRUE; x -= mouse_xfocus; y -= mouse_yfocus; update_mouse_pointer(x, y, FALSE); return 0; } /* gfx_gdi_hide_mouse: */ static void gfx_gdi_hide_mouse(void) { HDC hdc; HWND allegro_wnd = win_get_window(); if (!mouse_on) return; hdc = GetDC(allegro_wnd); if (_color_depth == 8) set_palette_to_hdc(hdc, palette); /* restore the screen contents located at the old position */ blit_to_hdc(mouse_backbuffer, hdc, 0, 0, mouse_xpos, mouse_ypos, mouse_backbuffer->w, mouse_backbuffer->h); ReleaseDC(allegro_wnd, hdc); mouse_on = FALSE; } /* gfx_gdi_move_mouse: */ static void gfx_gdi_move_mouse(int x, int y) { if (!mouse_on) return; x -= mouse_xfocus; y -= mouse_yfocus; if ((mouse_xpos == x) && (mouse_ypos == y)) return; update_mouse_pointer(x, y, TRUE); } /* render_proc: * Timer proc that updates the window. */ static void render_proc(void) { int top_line, bottom_line; HDC hdc = NULL; HWND allegro_wnd = win_get_window(); /* to prevent reentrant calls */ if (render_semaphore) return; render_semaphore = TRUE; /* to prevent the drawing threads and the rendering proc * from concurrently accessing the dirty lines array. */ _enter_gfx_critical(); if (!gdi_screen) { _exit_gfx_critical(); render_semaphore = FALSE; return; } /* pseudo dirty rectangles mechanism: * at most only one GDI call is performed for each frame, * a true dirty rectangles mechanism makes the demo game * unplayable in 640x480 on my system. */ /* find the first dirty line */ top_line = 0; while (!gdi_dirty_lines[top_line]) top_line++; if (top_line < gfx_gdi.h) { /* find the last dirty line */ bottom_line = gfx_gdi.h-1; while (!gdi_dirty_lines[bottom_line]) bottom_line--; hdc = GetDC(allegro_wnd); if (_color_depth == 8) set_palette_to_hdc(hdc, palette); blit_to_hdc(gdi_screen, hdc, 0, top_line, 0, top_line, gfx_gdi.w, bottom_line - top_line + 1); /* update mouse pointer if needed */ if (mouse_on) { if ((mouse_ypos+wgdi_mouse_sprite->h > top_line) && (mouse_ypos <= bottom_line)) { blit(gdi_screen, mouse_backbuffer, mouse_xpos, mouse_ypos, 0, 0, mouse_backbuffer->w, mouse_backbuffer->h); update_mouse_pointer(mouse_xpos, mouse_ypos, TRUE); } } /* clean up the dirty lines */ while (top_line <= bottom_line) gdi_dirty_lines[top_line++] = 0; ReleaseDC(allegro_wnd, hdc); } _exit_gfx_critical(); /* simulate vertical retrace */ PulseEvent(vsync_event); render_semaphore = FALSE; } /* gdi_enter_sysmode: */ static void gdi_enter_sysmode(void) { /* hide the mouse pointer */ if (mouse_on) { mouse_was_on = TRUE; gfx_gdi_hide_mouse(); _TRACE(PREFIX_I "mouse pointer off\n"); } } /* gdi_exit_sysmode: */ static void gdi_exit_sysmode(void) { if (mouse_was_on) { mouse_on = TRUE; mouse_was_on = FALSE; _TRACE(PREFIX_I "mouse pointer on\n"); } } /* gdi_update_window: * Updates the window. */ static void gdi_update_window(RECT *rect) { HDC hdc; HWND allegro_wnd = win_get_window(); _enter_gfx_critical(); if (!gdi_screen) { _exit_gfx_critical(); return; } hdc = GetDC(allegro_wnd); if (_color_depth == 8) set_palette_to_hdc(hdc, palette); blit_to_hdc(gdi_screen, hdc, rect->left, rect->top, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top); ReleaseDC(allegro_wnd, hdc); _exit_gfx_critical(); } /* gfx_gdi_lock: */ static void gfx_gdi_lock(struct BITMAP *bmp) { /* to prevent the drawing threads and the rendering proc * from concurrently accessing the dirty lines array */ _enter_gfx_critical(); /* arrange for drawing requests to pause when we are in the background */ if (!_win_app_foreground) { /* stop timer */ remove_int(render_proc); _exit_gfx_critical(); if (GFX_CRITICAL_RELEASED) _win_thread_switch_out(); _enter_gfx_critical(); /* restart timer */ install_int(render_proc, RENDER_DELAY); } lock_nesting++; bmp->id |= BMP_ID_LOCKED; } /* gfx_gdi_autolock: */ static void gfx_gdi_autolock(struct BITMAP *bmp) { gfx_gdi_lock(bmp); bmp->id |= BMP_ID_AUTOLOCK; } /* gfx_gdi_unlock: */ static void gfx_gdi_unlock(struct BITMAP *bmp) { if (lock_nesting > 0) { lock_nesting--; if (!lock_nesting) bmp->id &= ~BMP_ID_LOCKED; _exit_gfx_critical(); } } /* gfx_gdi_init: */ static struct BITMAP *gfx_gdi_init(int w, int h, int v_w, int v_h, int color_depth) { /* virtual screen are not supported */ if ((v_w!=0 && v_w!=w) || (v_h!=0 && v_h!=h)) return NULL; _enter_critical(); gfx_gdi.w = w; gfx_gdi.h = h; if (adjust_window(w, h) != 0) { _TRACE(PREFIX_E "window size not supported.\n"); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto Error; } /* the last flag serves as an end of loop delimiter */ gdi_dirty_lines = _AL_MALLOC_ATOMIC((h+1) * sizeof(char)); if (!gdi_dirty_lines) { _TRACE(PREFIX_E "Could not allocate memory for gdi_dirty_lines.\n"); goto Error; } memset(gdi_dirty_lines, 0, (h+1) * sizeof(char)); gdi_dirty_lines[h] = 1; /* create the screen surface */ screen_surf = _AL_MALLOC_ATOMIC(w * h * BYTES_PER_PIXEL(color_depth)); gdi_screen = _make_bitmap(w, h, (unsigned long)screen_surf, &gfx_gdi, color_depth, w * BYTES_PER_PIXEL(color_depth)); if (!gdi_screen) { _TRACE(PREFIX_E "Could not make a bitmap out of the screen surface.\n"); goto Error; } gdi_screen->write_bank = gfx_gdi_write_bank; _screen_vtable.acquire = gfx_gdi_lock; _screen_vtable.release = gfx_gdi_unlock; _screen_vtable.unwrite_bank = gfx_gdi_unwrite_bank; /* create render timer */ vsync_event = CreateEvent(NULL, FALSE, FALSE, NULL); install_int(render_proc, RENDER_DELAY); /* connect to the system driver */ win_gfx_driver = &win_gfx_driver_gdi; /* set the default switching policy */ set_display_switch_mode(SWITCH_PAUSE); /* grab input devices */ win_grab_input(); _exit_critical(); return gdi_screen; Error: _exit_critical(); gfx_gdi_exit(NULL); return NULL; } /* gfx_gdi_exit: */ static void gfx_gdi_exit(struct BITMAP *bmp) { _enter_critical(); _enter_gfx_critical(); if (bmp) { save_window_pos(); clear_bitmap(bmp); } /* stop timer */ remove_int(render_proc); CloseHandle(vsync_event); vsync_event = NULL; /* disconnect from the system driver */ win_gfx_driver = NULL; /* destroy dirty lines array */ if (gdi_dirty_lines) { _AL_FREE(gdi_dirty_lines); gdi_dirty_lines = NULL; } /* destroy screen surface */ if (screen_surf) { _AL_FREE(screen_surf); screen_surf = NULL; } gdi_screen = NULL; /* destroy mouse bitmaps */ if (wgdi_mouse_sprite) { destroy_bitmap(wgdi_mouse_sprite); wgdi_mouse_sprite = NULL; destroy_bitmap(mouse_frontbuffer); mouse_frontbuffer = NULL; destroy_bitmap(mouse_backbuffer); mouse_backbuffer = NULL; } _exit_gfx_critical(); /* before restoring video mode, hide window */ set_display_switch_mode(SWITCH_PAUSE); system_driver->restore_console_state(); restore_window_style(); _exit_critical(); } /* gfx_gdi_set_palette: */ static void gfx_gdi_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { int c; for (c=from; c<=to; c++) palette[c] = p[c]; /* invalidate the whole screen */ _enter_gfx_critical(); gdi_dirty_lines[0] = gdi_dirty_lines[gfx_gdi.h-1] = 1; _exit_gfx_critical(); } /* gfx_gdi_vsync: */ static void gfx_gdi_vsync(void) { WaitForSingleObject(vsync_event, INFINITE); } allegro-4.4.3.1/src/win/wddraw.h0000664000175000017500000001322513437077643015330 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw gfx drivers header. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #ifndef WDDRAW_H_INCLUDED #define WDDRAW_H_INCLUDED #define DIRECTDRAW_VERSION 0x0300 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_BCC32 #undef NONAMELESSUNION #endif #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif /* wrapper for DirectDraw surfaces */ typedef struct DDRAW_SURFACE { LPDIRECTDRAWSURFACE2 id; int flags; int lock_nesting; BITMAP *parent_bmp; /* only used by the flipping chain */ struct DDRAW_SURFACE *next; struct DDRAW_SURFACE *prev; } DDRAW_SURFACE; #define DDRAW_SURFACE_OF(bmp) ((DDRAW_SURFACE *)(bmp->extra)) #define DDRAW_SURFACE_PRIMARY 0x01 #define DDRAW_SURFACE_OVERLAY 0x02 #define DDRAW_SURFACE_VIDEO 0x04 #define DDRAW_SURFACE_SYSTEM 0x08 #define DDRAW_SURFACE_TYPE_MASK 0x0F #define DDRAW_SURFACE_INDEXED 0x10 #define DDRAW_SURFACE_LOST 0x20 /* DirectDraw globals (from wddraw.c) */ AL_VAR(LPDIRECTDRAW2, directdraw); AL_VAR(LPDIRECTDRAWCLIPPER, ddclipper); AL_VAR(LPDIRECTDRAWPALETTE, ddpalette); AL_VAR(LPDDPIXELFORMAT, ddpixel_format); AL_VAR(DDCAPS, ddcaps); AL_VAR(DDRAW_SURFACE *, gfx_directx_primary_surface); AL_VAR(BITMAP *, gfx_directx_forefront_bitmap); AL_VAR(unsigned char *, pseudo_surf_mem); /* driver routines */ AL_FUNC(BITMAP *, gfx_directx_init, (GFX_DRIVER *drv, int w, int h, int v_w, int v_h, int color_depth)); AL_FUNC(void, gfx_directx_exit, (BITMAP *bmp)); AL_FUNC(void, gfx_directx_sync, (void)); AL_FUNC(void, gfx_directx_set_palette, (AL_CONST RGB *p, int from, int to, int vsync)); AL_FUNC(int, gfx_directx_poll_scroll, (void)); AL_FUNC(void, gfx_directx_created_sub_bitmap, (BITMAP *bmp, BITMAP *parent)); AL_FUNC(BITMAP *, gfx_directx_create_video_bitmap, (int width, int height)); AL_FUNC(void, gfx_directx_destroy_video_bitmap, (BITMAP *bmp)); AL_FUNC(int, gfx_directx_show_video_bitmap, (BITMAP *bmp)); AL_FUNC(int, gfx_directx_request_video_bitmap, (BITMAP *bmp)); AL_FUNC(BITMAP *, gfx_directx_create_system_bitmap, (int width, int height)); AL_FUNC(void, gfx_directx_destroy_system_bitmap, (BITMAP *bmp)); AL_FUNC(GFX_MODE_LIST *, gfx_directx_fetch_mode_list, (void)); AL_FUNC(int, gfx_directx_set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); AL_FUNC(int, gfx_directx_show_mouse, (struct BITMAP *bmp, int x, int y)); AL_FUNC(void, gfx_directx_hide_mouse, (void)); AL_FUNC(void, gfx_directx_move_mouse, (int x, int y)); /* driver initialisation and shutdown (from wddraw.c) */ AL_FUNC(int, init_directx, (void)); AL_FUNC(int, gfx_directx_create_primary, (void)); AL_FUNC(int, gfx_directx_create_clipper, (HWND hwnd)); AL_FUNC(int, gfx_directx_create_palette, (DDRAW_SURFACE *surf)); AL_FUNC(int, gfx_directx_setup_driver, (GFX_DRIVER * drv, int w, int h, int color_depth)); AL_FUNC(int, finalize_directx_init, (void)); AL_FUNC(int, exit_directx, (void)); /* driver initialisation and shutdown (from wddaccel.c) */ AL_FUNC(void, gfx_directx_enable_acceleration, (GFX_DRIVER *drv)); AL_FUNC(void, gfx_directx_enable_triple_buffering, (GFX_DRIVER *drv)); /* video mode setting (from wddmode.c) */ AL_VAR(int, _win_desktop_depth); AL_VAR(RGB_MAP, _win_desktop_rgb_map); AL_FUNC(void, build_desktop_rgb_map, (void)); AL_FUNC(int, gfx_directx_compare_color_depth, (int color_depth)); AL_FUNC(int, gfx_directx_update_color_format, (DDRAW_SURFACE *surf, int color_depth)); AL_FUNC(int, set_video_mode, (int w, int h, int v_w, int v_h, int color_depth)); /* bitmap locking (from wddlock.c and wgdi.c and possibly asmlock.s) */ AL_FUNC(void, gfx_directx_lock, (BITMAP *bmp)); AL_FUNC(void, gfx_directx_autolock, (BITMAP* bmp)); AL_FUNC(void, gfx_directx_unlock, (BITMAP *bmp)); AL_FUNC(void, gfx_directx_unlock_win, (BITMAP *bmp)); AL_FUNC(void, gfx_directx_release_lock, (BITMAP * bmp)); AL_FUNC(uintptr_t, gfx_directx_write_bank, (BITMAP *bmp, int line)); AL_FUNC(void, gfx_directx_unwrite_bank, (BITMAP *bmp)); AL_FUNC(uintptr_t, gfx_directx_write_bank_win, (BITMAP *bmp, int line)); AL_FUNC(void, gfx_directx_unwrite_bank_win, (BITMAP *bmp)); AL_FUNC(void, gfx_gdi_autolock, (struct BITMAP* bmp)); AL_FUNC(void, gfx_gdi_unlock, (struct BITMAP* bmp)); AL_FUNC(uintptr_t, gfx_gdi_write_bank, (BITMAP *bmp, int line)); AL_FUNC(void, gfx_gdi_unwrite_bank, (BITMAP *bmp)); /* dirty window updating (from wddwin.c, used in wddlock.c or asmlock.s) */ AL_VAR(char *, _al_wd_dirty_lines); AL_FUNCPTR(void, _al_wd_update_window, (RECT *rect)); /* bitmap creation (from wddbmp.c) */ AL_FUNC(DDRAW_SURFACE *, gfx_directx_create_surface, (int w, int h, LPDDPIXELFORMAT pixel_format, int type)); AL_FUNC(void, gfx_directx_destroy_surface, (DDRAW_SURFACE *surf)); AL_FUNC(BITMAP *, gfx_directx_make_bitmap_from_surface, (DDRAW_SURFACE *surf, int w, int h, int id)); /* video bitmap list (from wddbmpl.c) */ AL_FUNC(void, register_ddraw_surface, (DDRAW_SURFACE *surf)); AL_FUNC(void, unregister_ddraw_surface, (DDRAW_SURFACE *surf)); AL_FUNC(void, unregister_all_ddraw_surfaces, (void)); AL_FUNC(int, restore_all_ddraw_surfaces, (void)); #endif allegro-4.4.3.1/src/win/wdsndmix.c0000664000175000017500000005126413437077643015675 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Allegro mixer to DirectSound driver. * * By Robin Burrows. * * Based on original src/win/wdsound.c by Stefan Schimanski * and src/unix/oss.c by Joshua Heyer. * * Bugfixes by Javier Gonzalez. * * See readme.txt for copyright information. */ #define DIRECTSOUND_VERSION 0x0300 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #include #ifdef ALLEGRO_MSVC #include #endif #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-dsndmix INFO: " #define PREFIX_W "al-dsndmix WARNING: " #define PREFIX_E "al-dsndmix ERROR: " static int digi_dsoundmix_detect(int input); static int digi_dsoundmix_init(int input, int voices); static void digi_dsoundmix_exit(int input); static int digi_dsoundmix_set_mixer_volume(int volume); static int digi_dsoundmix_get_mixer_volume(void); static int digi_dsoundmix_buffer_size(void); /* template driver: will be cloned for each device */ static DIGI_DRIVER digi_dsoundmix = { 0, empty_string, empty_string, empty_string, 0, // available voices 0, // voice number offset MIXER_MAX_SFX, // maximum voices we can support MIXER_DEF_SFX, // default number of voices to use /* setup routines */ digi_dsoundmix_detect, digi_dsoundmix_init, digi_dsoundmix_exit, digi_dsoundmix_set_mixer_volume, digi_dsoundmix_get_mixer_volume, /* audiostream locking functions */ NULL, // AL_METHOD(void *, lock_voice, (int voice, int start, int end)); NULL, // AL_METHOD(void, unlock_voice, (int voice)); digi_dsoundmix_buffer_size, /* voice control functions */ _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, /* position control functions */ _mixer_get_position, _mixer_set_position, /* volume control functions */ _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, /* pitch control functions */ _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, /* pan control functions */ _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, /* effect control functions */ _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, /* input functions */ 0, // int rec_cap_bits; 0, // int rec_cap_stereo; digi_directsound_rec_cap_rate, digi_directsound_rec_cap_param, digi_directsound_rec_source, digi_directsound_rec_start, digi_directsound_rec_stop, digi_directsound_rec_read }; #define MAX_DRIVERS 16 static char *driver_names[MAX_DRIVERS]; static LPGUID driver_guids[MAX_DRIVERS]; #define USE_NEW_CODE 0 /* sound driver globals */ static LPDIRECTSOUND directsound = NULL; static LPDIRECTSOUNDBUFFER prim_buf = NULL; static LPDIRECTSOUNDBUFFER alleg_buf = NULL; static long int initial_volume; static int _freq, _bits, _stereo; static int alleg_to_dsound_volume[256]; static unsigned int digidsbufsize; static unsigned char *digidsbufdata; #if !USE_NEW_CODE static unsigned int bufdivs = 16, digidsbufpos; #else static int digidsbufdirty; #endif static int alleg_buf_paused = FALSE; static int alleg_buf_vol; /* ds_err: * Returns a DirectSound error string. */ #ifdef DEBUGMODE static char *ds_err(long err) { static char err_str[64]; switch (err) { case DS_OK: _al_sane_strncpy(err_str, "DS_OK", sizeof(err_str)); break; case DSERR_ALLOCATED: _al_sane_strncpy(err_str, "DSERR_ALLOCATED", sizeof(err_str)); break; case DSERR_BADFORMAT: _al_sane_strncpy(err_str, "DSERR_BADFORMAT", sizeof(err_str)); break; case DSERR_INVALIDPARAM: _al_sane_strncpy(err_str, "DSERR_INVALIDPARAM", sizeof(err_str)); break; case DSERR_NOAGGREGATION: _al_sane_strncpy(err_str, "DSERR_NOAGGREGATION", sizeof(err_str)); break; case DSERR_OUTOFMEMORY: _al_sane_strncpy(err_str, "DSERR_OUTOFMEMORY", sizeof(err_str)); break; case DSERR_UNINITIALIZED: _al_sane_strncpy(err_str, "DSERR_UNINITIALIZED", sizeof(err_str)); break; case DSERR_UNSUPPORTED: _al_sane_strncpy(err_str, "DSERR_UNSUPPORTED", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "DSERR_UNKNOWN", sizeof(err_str)); break; } return err_str; } #else #define ds_err(hr) "\0" #endif /* _get_dsalmix_driver: * System driver hook for listing the available sound drivers. This * generates the device list at runtime, to match whatever DirectSound * devices are available. */ DIGI_DRIVER *_get_dsalmix_driver(char *name, LPGUID guid, int num) { DIGI_DRIVER *driver; driver = _AL_MALLOC(sizeof(DIGI_DRIVER)); if (!driver) return NULL; memcpy(driver, &digi_dsoundmix, sizeof(DIGI_DRIVER)); driver->id = DIGI_DIRECTAMX(num); driver_names[num] = _AL_MALLOC_ATOMIC(strlen(name)+10); if (driver_names[num]) { _al_sane_strncpy(driver_names[num], "Allegmix ", strlen(name)+10); _al_sane_strncpy(driver_names[num]+9, name, strlen(name)+1); driver->ascii_name = driver_names[num]; } driver_guids[num] = guid; return driver; } /* _free_win_dsalmix_name_list * Helper function for freeing dynamically generated driver names. */ void _free_win_dsalmix_name_list(void) { int i = 0; for (i = 0; i < MAX_DRIVERS; i++) { if (driver_names[i]) _AL_FREE(driver_names[i]); } } /* create_dsound_buffer: * Worker function for creating a DirectSound buffer. */ static LPDIRECTSOUNDBUFFER create_dsound_buffer(int len, int freq, int bits, int stereo, int vol) { LPDIRECTSOUNDBUFFER snd_buf; WAVEFORMATEX wf; DSBUFFERDESC dsbdesc; HRESULT hr; /* setup wave format structure */ memset(&wf, 0, sizeof(WAVEFORMATEX)); wf.wFormatTag = WAVE_FORMAT_PCM; wf.nChannels = stereo ? 2 : 1; wf.nSamplesPerSec = freq; wf.wBitsPerSample = bits; wf.nBlockAlign = bits * (stereo ? 2 : 1) / 8; wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; /* setup DSBUFFERDESC structure */ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); /* need volume control and global focus */ dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; dsbdesc.dwBufferBytes = len * (bits / 8) * (stereo ? 2 : 1); dsbdesc.lpwfxFormat = &wf; /* create buffer */ hr = IDirectSound_CreateSoundBuffer(directsound, &dsbdesc, &snd_buf, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "create_directsound_buffer() failed (%s).\n", ds_err(hr)); _TRACE(PREFIX_E " - %d Hz, %s, %d bits\n", freq, stereo ? "stereo" : "mono", bits); return NULL; } /* set volume */ IDirectSoundBuffer_SetVolume(snd_buf, alleg_to_dsound_volume[CLAMP(0, vol, 255)]); return snd_buf; } /* digi_dsoundmix_mixer_callback: * Callback function to update sound in the DS buffer. */ static void digi_dsoundmix_mixer_callback(void) { LPVOID lpvPtr1, lpvPtr2; DWORD dwBytes1, dwBytes2; DWORD playcurs, writecurs; HRESULT hr; int switch_mode; /* handle display switchs */ switch_mode = get_display_switch_mode(); if (alleg_buf_paused) { if (_win_app_foreground || (switch_mode == SWITCH_BACKGROUND) || (switch_mode == SWITCH_BACKAMNESIA)) { /* get current state of the sound buffer */ hr = IDirectSoundBuffer_GetStatus(alleg_buf, &dwBytes1); if ((hr == DS_OK) && (dwBytes1 & DSBSTATUS_BUFFERLOST)) { if(IDirectSoundBuffer_Restore(alleg_buf) != DS_OK) return; IDirectSoundBuffer_SetVolume(alleg_buf, alleg_buf_vol); } alleg_buf_paused = FALSE; IDirectSoundBuffer_Play(alleg_buf, 0, 0, DSBPLAY_LOOPING); } else return; } else { if (!_win_app_foreground && ((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA))) { alleg_buf_paused = TRUE; IDirectSoundBuffer_Stop(alleg_buf); return; } } #if USE_NEW_CODE /* this should work, dammit */ /* write data into the buffer */ if (digidsbufdirty) { _mix_some_samples((uintptr_t)digidsbufdata, 0, TRUE); digidsbufdirty = FALSE; } hr = IDirectSoundBuffer_GetCurrentPosition(alleg_buf, &playcurs, &writecurs); if (FAILED(hr)) return; if (((playcurs-writecurs)%(digidsbufsize*2)) < digidsbufsize) return; /* Consider the buffer used. Even if the buffer was lost, mark the data as old so the mixer doesn't stall */ digidsbufdirty = TRUE; hr = IDirectSoundBuffer_Lock(alleg_buf, 0, digidsbufsize, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, DSBLOCK_FROMWRITECURSOR); /* only try to restore the buffer once. don't wait around forever */ if (hr == DSERR_BUFFERLOST) { if(IDirectSoundBuffer_Restore(alleg_buf) != DS_OK) return; IDirectSoundBuffer_Play(alleg_buf, 0, 0, DSBPLAY_LOOPING); IDirectSoundBuffer_SetVolume(alleg_buf, alleg_buf_vol); hr = IDirectSoundBuffer_Lock(alleg_buf, 0, digidsbufsize, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, DSBLOCK_FROMWRITECURSOR); } if (FAILED(hr)) return; /* if the first buffer has enough room, put it all there */ if(dwBytes1 >= digidsbufsize) { dwBytes1 = digidsbufsize; memcpy(lpvPtr1, digidsbufdata, dwBytes1); dwBytes2 = 0; } /* else, sput the first part into the first buffer, and the rest into the second */ else { memcpy(lpvPtr1, digidsbufdata, dwBytes1); dwBytes2 = digidsbufsize-dwBytes1; memcpy(lpvPtr2, digidsbufdata+dwBytes1, dwBytes2); } IDirectSoundBuffer_Unlock(alleg_buf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); #else hr = IDirectSoundBuffer_GetCurrentPosition(alleg_buf, &playcurs, &writecurs); if (FAILED(hr)) return; writecurs /= (digidsbufsize/bufdivs); writecurs += 8; while (writecurs > (bufdivs-1)) writecurs -= bufdivs; /* avoid locking the buffer if no data to write */ if (writecurs == digidsbufpos) return; hr = IDirectSoundBuffer_Lock(alleg_buf, 0, 0, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, DSBLOCK_FROMWRITECURSOR | DSBLOCK_ENTIREBUFFER); if (FAILED(hr)) return; /* write data into the buffer */ while (writecurs != digidsbufpos) { if (lpvPtr2) { memcpy((char*)lpvPtr2 + (((dwBytes1+dwBytes2)/bufdivs)*digidsbufpos), digidsbufdata + (((dwBytes1+dwBytes2)/bufdivs)*digidsbufpos), (dwBytes1+dwBytes2)/bufdivs); } else { memcpy((char*)lpvPtr1 + (((dwBytes1)/bufdivs)*digidsbufpos), digidsbufdata + (((dwBytes1)/bufdivs)*digidsbufpos), (dwBytes1)/bufdivs); } if (++digidsbufpos > (bufdivs-1)) digidsbufpos = 0; _mix_some_samples((uintptr_t) (digidsbufdata+(((dwBytes1+dwBytes2)/bufdivs)*digidsbufpos)), 0, TRUE); } IDirectSoundBuffer_Unlock(alleg_buf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); #endif } /* digi_dsoundmix_detect: */ static int digi_dsoundmix_detect(int input) { HRESULT hr; int id; /* deduce our device number from the driver ID code */ id = ((digi_driver->id >> 8) & 0xFF) - 'A'; if (input) return digi_directsound_capture_detect(driver_guids[id]); if (!directsound) { /* initialize DirectSound interface */ hr = DirectSoundCreate(driver_guids[id], &directsound, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "DirectSound interface creation failed during detect (%s)\n", ds_err(hr)); return 0; } _TRACE(PREFIX_I "DirectSound interface successfully created\n"); /* release DirectSound */ IDirectSound_Release(directsound); directsound = NULL; } return 1; } /* digi_dsoundmix_init: */ static int digi_dsoundmix_init(int input, int voices) { LPVOID lpvPtr1, lpvPtr2; DWORD dwBytes1, dwBytes2; HRESULT hr; DSCAPS dscaps; DSBUFFERDESC desc; WAVEFORMATEX format; HWND allegro_wnd = win_get_window(); char tmp1[128], tmp2[128]; int v, id; /* deduce our device number from the driver ID code */ id = ((digi_driver->id >> 8) & 0xFF) - 'A'; if (input) return digi_directsound_capture_init(driver_guids[id]); digi_driver->voices = voices; /* initialize DirectSound interface */ hr = DirectSoundCreate(driver_guids[id], &directsound, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't create DirectSound interface (%s)\n", ds_err(hr)); goto Error; } /* set cooperative level */ hr = IDirectSound_SetCooperativeLevel(directsound, allegro_wnd, DSSCL_PRIORITY); if (FAILED(hr)) _TRACE(PREFIX_W "Can't set DirectSound cooperative level (%s)\n", ds_err(hr)); else _TRACE(PREFIX_I "DirectSound cooperation level set to DSSCL_PRIORITY\n"); /* get hardware capabilities */ dscaps.dwSize = sizeof(DSCAPS); hr = IDirectSound_GetCaps(directsound, &dscaps); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get DirectSound caps (%s)\n", ds_err(hr)); goto Error; } /* For some reason the audio driver on my machine doesn't seem to set either * PRIMARY16BIT or PRIMARY8BIT; of course it actually does support 16-bit * sound. */ if (((dscaps.dwFlags & DSCAPS_PRIMARY16BIT) || !(dscaps.dwFlags & DSCAPS_PRIMARY8BIT)) && ((_sound_bits >= 16) || (_sound_bits <= 0))) _bits = 16; else _bits = 8; if ((dscaps.dwFlags & DSCAPS_PRIMARYSTEREO) && _sound_stereo) _stereo = 1; else _stereo = 0; /* Try to set the requested frequency */ if ((dscaps.dwMaxSecondarySampleRate > (DWORD)_sound_freq) && (_sound_freq > 0)) _freq = _sound_freq; /* If no frequency is specified, make sure it's clamped to a reasonable value by default */ else if ((_sound_freq <= 0) && (dscaps.dwMaxSecondarySampleRate > 44100)) _freq = 44100; else _freq = dscaps.dwMaxSecondarySampleRate; _TRACE(PREFIX_I "DirectSound caps: %u bits, %s, %uHz\n", _bits, _stereo ? "stereo" : "mono", _freq); memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GLOBALFOCUS;// | DSBCAPS_CTRLVOLUME | DSBCAPS_STICKYFOCUS; hr = IDirectSound_CreateSoundBuffer(directsound, &desc, &prim_buf, NULL); if (FAILED(hr)) _TRACE(PREFIX_W "Can't create primary buffer (%s)\nGlobal volume control won't be available\n", ds_err(hr)); if (prim_buf) { hr = IDirectSoundBuffer_GetFormat(prim_buf, &format, sizeof(format), NULL); if (FAILED(hr)) { _TRACE(PREFIX_W "Can't get primary buffer format (%s)\n", ds_err(hr)); } else { format.nChannels = (_stereo ? 2 : 1); format.nSamplesPerSec = _freq; format.wBitsPerSample = _bits; format.nBlockAlign = (format.wBitsPerSample * format.nChannels) >> 3; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; hr = IDirectSoundBuffer_SetFormat(prim_buf, &format); if (FAILED(hr)) _TRACE(PREFIX_W "Can't set primary buffer format (%s)\n", ds_err(hr)); hr = IDirectSoundBuffer_GetFormat(prim_buf, &format, sizeof(format), NULL); if (FAILED(hr)) { _TRACE(PREFIX_W "Can't get primary buffer format (%s)\n", ds_err(hr)); } else { _TRACE(PREFIX_I "primary format:\n"); _TRACE(PREFIX_I " %u channels\n %u Hz\n %u AvgBytesPerSec\n %u BlockAlign\n %u bits\n %u size\n", format.nChannels, format.nSamplesPerSec, format.nAvgBytesPerSec, format.nBlockAlign, format.wBitsPerSample, format.cbSize); } } } /* setup volume lookup table */ alleg_to_dsound_volume[0] = DSBVOLUME_MIN; for (v = 1; v < 256; v++) { int dB = DSBVOLUME_MAX + 2000.0*log10(v/255.0); alleg_to_dsound_volume[v] = MAX(DSBVOLUME_MIN, dB); } /* create the sound buffer to mix into */ alleg_buf = create_dsound_buffer(get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("dsound_numfrags", tmp2), 6) * 1024, _freq, _bits, _stereo, 255); if(!alleg_buf) { _TRACE(PREFIX_E "Can't create mixing buffer\n"); return -1; } /* fill the sound buffer with zeros */ hr = IDirectSoundBuffer_Lock(alleg_buf, 0, 0, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, DSBLOCK_ENTIREBUFFER); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't lock sound buffer (%s)\n", ds_err(hr)); return -1; } memset(lpvPtr1, 0, dwBytes1); digidsbufsize = dwBytes1; if (lpvPtr2) { _TRACE(PREFIX_E "Second buffer set when locking buffer. Error?\n"); memset(lpvPtr2, 0, dwBytes2); digidsbufsize += dwBytes2; } IDirectSoundBuffer_Unlock(alleg_buf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); _TRACE(PREFIX_I "Sound buffer length is %u\n", digidsbufsize); /* shouldn't ever happen */ if (digidsbufsize&1023) { _TRACE(PREFIX_E "Sound buffer is not multiple of 1024, failed\n"); return -1; } #if USE_NEW_CODE digidsbufsize /= 2; #endif digidsbufdata = _AL_MALLOC_ATOMIC(digidsbufsize); if (!digidsbufdata) { _TRACE(PREFIX_E "Can't create temp buffer\n"); return -1; } #if USE_NEW_CODE if (_mixer_init(digidsbufsize / (_bits /8), _freq, _stereo, ((_bits == 16) ? 1 : 0), &digi_driver->voices) != 0) { _TRACE(PREFIX_E "Can't init software mixer\n"); return -1; } #else bufdivs = digidsbufsize/1024; if (_mixer_init((digidsbufsize / (_bits /8)) / bufdivs, _freq, _stereo, ((_bits == 16) ? 1 : 0), &digi_driver->voices) != 0) { _TRACE(PREFIX_E "Can't init software mixer\n"); return -1; } _mix_some_samples((uintptr_t)digidsbufdata, 0, TRUE); #endif /* get primary buffer volume */ IDirectSoundBuffer_GetVolume(alleg_buf, &initial_volume); alleg_buf_vol = initial_volume; /* mark the buffer as paused, so the mixer callback will start it */ alleg_buf_paused = TRUE; #if USE_NEW_CODE digidsbufdirty = TRUE; #endif install_int(digi_dsoundmix_mixer_callback, 20); /* 50 Hz */ return 0; Error: _TRACE(PREFIX_E "digi_directsound_init() failed\n"); digi_dsoundmix_exit(0); return -1; } /* digi_dsoundmix_exit: */ static void digi_dsoundmix_exit(int input) { if (input) { digi_directsound_capture_exit(); return; } /* stop playing */ remove_int(digi_dsoundmix_mixer_callback); if (digidsbufdata) { _AL_FREE(digidsbufdata); digidsbufdata = NULL; } /* destroy mixer buffer */ if (alleg_buf) { IDirectSoundBuffer_Release(alleg_buf); alleg_buf = NULL; } /* destroy primary buffer */ if (prim_buf) { /* restore primary buffer initial volume */ IDirectSoundBuffer_SetVolume(prim_buf, initial_volume); IDirectSoundBuffer_Release(prim_buf); prim_buf = NULL; } /* shutdown DirectSound */ if (directsound) { IDirectSound_Release(directsound); directsound = NULL; } } /* digi_dsoundmix_set_mixer_volume: */ static int digi_dsoundmix_set_mixer_volume(int volume) { if (prim_buf) { alleg_buf_vol = alleg_to_dsound_volume[CLAMP(0, volume, 255)]; IDirectSoundBuffer_SetVolume(alleg_buf, alleg_buf_vol); } return 0; } /* digi_dsoundmix_get_mixer_volume: */ static int digi_dsoundmix_get_mixer_volume(void) { LONG vol; if (!prim_buf) return -1; IDirectSoundBuffer_GetVolume(alleg_buf, &vol); vol = CLAMP(0, pow(10, (vol/2000.0))*255.0 - DSBVOLUME_MAX, 255); return vol; } /* digi_dsoundmix_buffer_size: */ static int digi_dsoundmix_buffer_size(void) { return digidsbufsize / (_bits / 8) / (_stereo ? 2 : 1); } allegro-4.4.3.1/src/win/wsndwo.c0000664000175000017500000002262613437077643015361 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Allegro mixer to WaveOut driver. * * By Robin Burrows. * * Based on original src/unix/uoss.c by Joshua Heyer. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #ifdef ALLEGRO_MSVC #include #endif #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wsnd INFO: " #define PREFIX_W "al-wsnd WARNING: " #define PREFIX_E "al-wsnd ERROR: " static int digi_waveout_detect(int input); static int digi_waveout_init(int input, int voices); static void digi_waveout_exit(int input); static int digi_waveout_set_mixer_volume(int volume); static int digi_waveout_get_mixer_volume(void); static int digi_waveout_buffer_size(void); /* template driver: will be cloned for each device */ static DIGI_DRIVER digi_waveout = { 0, empty_string, empty_string, empty_string, 0, // available voices 0, // voice number offset MIXER_MAX_SFX, // maximum voices we can support MIXER_DEF_SFX, // default number of voices to use /* setup routines */ digi_waveout_detect, digi_waveout_init, digi_waveout_exit, digi_waveout_set_mixer_volume, digi_waveout_get_mixer_volume, /* audiostream locking functions */ NULL, // AL_METHOD(void *, lock_voice, (int voice, int start, int end)); NULL, // AL_METHOD(void, unlock_voice, (int voice)); digi_waveout_buffer_size, /* voice control functions */ _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, /* position control functions */ _mixer_get_position, _mixer_set_position, /* volume control functions */ _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, /* pitch control functions */ _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, /* pan control functions */ _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, /* effect control functions */ _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, /* input functions */ 0, // int rec_cap_bits; 0, // int rec_cap_stereo; NULL, // AL_METHOD(int, rec_cap_rate, (int bits, int stereo)); NULL, // AL_METHOD(int, rec_cap_parm, (int rate, int bits, int stereo)); NULL, // AL_METHOD(int, rec_source, (int source)); NULL, // AL_METHOD(int, rec_start, (int rate, int bits, int stereo)); NULL, // AL_METHOD(void, rec_stop, (void)); NULL // AL_METHOD(int, rec_read, (void *buf)); }; /* sound driver globals */ static HWAVEOUT hWaveOut = NULL; static LPWAVEHDR lpWaveHdr = NULL; static unsigned long int initial_volume; static int digiwobufsize, digiwobufdivs, digiwobufpos; static char * digiwobufdata = NULL; static int _freq, _bits, _stereo; static int waveout_paused = FALSE; /* _get_woalmix_driver: * System driver hook for listing the available sound drivers. This * generates the device list at runtime, to match whatever WaveOut * devices are available. */ DIGI_DRIVER *_get_woalmix_driver(int num) { DIGI_DRIVER *driver; driver = _AL_MALLOC(sizeof(DIGI_DRIVER)); if (!driver) return NULL; memcpy(driver, &digi_waveout, sizeof(DIGI_DRIVER)); driver->id = DIGI_WAVOUTID(num); if (num == 0) driver->ascii_name = "WaveOut 44100hz 16bit stereo"; else driver->ascii_name = "WaveOut 22050hz 8bit mono"; return driver; } /* digi_waveout_mixer_callback: * Callback function to update sound in WaveOut buffer. */ static void digi_waveout_mixer_callback(void) { MMTIME mmt; MMRESULT mmr; int writecurs; int switch_mode; /* handle display switchs */ switch_mode = get_display_switch_mode(); if (waveout_paused) { if (_win_app_foreground || (switch_mode == SWITCH_BACKGROUND) || (switch_mode == SWITCH_BACKAMNESIA)) { waveout_paused = FALSE; waveOutRestart(hWaveOut); } else return; } else { if (!_win_app_foreground && ((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA))) { waveout_paused = TRUE; waveOutPause(hWaveOut); return; } } /* get current state of buffer */ memset(&mmt, 0, sizeof(MMTIME)); mmt.wType = TIME_BYTES; mmr = waveOutGetPosition(hWaveOut, &mmt, sizeof(MMTIME)); if (mmr != MMSYSERR_NOERROR) return; writecurs = (int) mmt.u.cb; writecurs /= (digiwobufsize/digiwobufdivs); writecurs += 8; while (writecurs > (digiwobufdivs-1)) writecurs -= digiwobufdivs; /* write data into the buffer */ while (writecurs != digiwobufpos) { if (++digiwobufpos > (digiwobufdivs-1)) digiwobufpos = 0; _mix_some_samples((unsigned long) (digiwobufdata+((digiwobufsize/digiwobufdivs)*digiwobufpos)), 0, TRUE); } } /* digi_waveout_detect: */ static int digi_waveout_detect(int input) { if (input) return 0; /* always present */ return 1; } /* digi_waveout_init: */ static int digi_waveout_init(int input, int voices) { MMRESULT mmr; WAVEFORMATEX format; int id; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } /* deduce our device number from the driver ID code */ id = ((digi_driver->id >> 8) & 0xFF) - 'A'; digi_driver->voices = voices; /* get hardware capabilities */ digiwobufdivs = 32; digiwobufpos = 0; if (id == 0) { _bits = 16; _freq = 44100; _stereo = 1; digiwobufsize = digiwobufdivs * 1024; } else { _bits = 8; _freq = 22050; _stereo = 0; digiwobufsize = digiwobufdivs * 512; } digiwobufdata = _AL_MALLOC_ATOMIC(digiwobufsize); if (!digiwobufdata) { _TRACE (PREFIX_E "_AL_MALLOC_ATOMIC() failed\n"); goto Error; } format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = _stereo ? 2 : 1; format.nSamplesPerSec = _freq; format.wBitsPerSample = _bits; format.nBlockAlign = (format.wBitsPerSample * format.nChannels) >> 3; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL); if (mmr != MMSYSERR_NOERROR) { _TRACE (PREFIX_E "Can't open WaveOut\n"); goto Error; } lpWaveHdr = _AL_MALLOC(sizeof(WAVEHDR)); lpWaveHdr->lpData = digiwobufdata; lpWaveHdr->dwBufferLength = digiwobufsize; lpWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; lpWaveHdr->dwLoops = 0x7fffffffL; mmr = waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { _TRACE (PREFIX_E "waveOutPrepareHeader() failed\n"); goto Error; } mmr = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { _TRACE (PREFIX_E "waveOutWrite() failed\n" ); goto Error; } if (_mixer_init((digiwobufsize / (_bits /8)) / digiwobufdivs, _freq, _stereo, ((_bits == 16) ? 1 : 0), &digi_driver->voices) != 0) { _TRACE(PREFIX_E "Can't init software mixer\n"); goto Error; } _mix_some_samples((unsigned long) digiwobufdata, 0, TRUE); /* get volume */ waveOutGetVolume(hWaveOut, &initial_volume); /* start playing */ install_int(digi_waveout_mixer_callback, 20); /* 50 Hz */ return 0; Error: _TRACE(PREFIX_E "digi_waveout_init() failed\n"); digi_waveout_exit(0); return -1; } /* digi_waveout_exit: */ static void digi_waveout_exit(int input) { /* stop playing */ remove_int(digi_waveout_mixer_callback); if (hWaveOut) { waveOutReset(hWaveOut); /* restore initial volume */ waveOutSetVolume(hWaveOut, initial_volume); waveOutUnprepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)); waveOutClose(hWaveOut); hWaveOut = NULL; } if (lpWaveHdr) { _AL_FREE(lpWaveHdr); lpWaveHdr = NULL; } if (digiwobufdata) { _AL_FREE(digiwobufdata); digiwobufdata = NULL; } } /* digi_waveout_set_mixer_volume: */ static int digi_waveout_set_mixer_volume(int volume) { DWORD realvol; if (hWaveOut) { realvol = (DWORD) volume; realvol |= realvol<<8; realvol |= realvol<<16; waveOutSetVolume(hWaveOut, realvol); } return 0; } /* digi_waveout_get_mixer_volume: */ static int digi_waveout_get_mixer_volume(void) { DWORD vol; if (!hWaveOut) return -1; if (waveOutGetVolume(hWaveOut, &vol) != MMSYSERR_NOERROR) return -1; vol &= 0xffff; return vol / (0xffff / 255); } /* digi_waveout_buffer_size: */ static int digi_waveout_buffer_size(void) { return digiwobufsize / (_bits / 8) / (_stereo ? 2 : 1); } allegro-4.4.3.1/src/win/wddraw.c0000664000175000017500000003122013437077643015316 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw gfx drivers. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddraw INFO: " #define PREFIX_W "al-wddraw WARNING: " #define PREFIX_E "al-wddraw ERROR: " /* DirectDraw globals */ LPDIRECTDRAW2 directdraw = NULL; LPDIRECTDRAWCLIPPER ddclipper = NULL; LPDIRECTDRAWPALETTE ddpalette = NULL; LPDDPIXELFORMAT ddpixel_format = NULL; DDCAPS ddcaps; DDRAW_SURFACE *gfx_directx_primary_surface = NULL; BITMAP *gfx_directx_forefront_bitmap = NULL; unsigned char *pseudo_surf_mem; /* DirectDraw internals */ static PALETTEENTRY palette_entry[256]; /* init_directx: * Low-level DirectDraw initialization routine. */ int init_directx(void) { LPDIRECTDRAW directdraw1; HRESULT hr; LPVOID temp; HWND allegro_wnd = win_get_window(); /* first we have to set up the DirectDraw1 interface... */ hr = DirectDrawCreate(NULL, &directdraw1, NULL); if (FAILED(hr)) return -1; /* ...then query the DirectDraw2 interface */ hr = IDirectDraw_QueryInterface(directdraw1, &IID_IDirectDraw2, &temp); if (FAILED(hr)) return -1; directdraw = temp; IDirectDraw_Release(directdraw1); /* set the default cooperation level */ hr = IDirectDraw2_SetCooperativeLevel(directdraw, allegro_wnd, DDSCL_NORMAL); if (FAILED(hr)) return -1; /* get capabilities */ ddcaps.dwSize = sizeof(ddcaps); hr = IDirectDraw2_GetCaps(directdraw, &ddcaps, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get driver caps\n"); return -1; } return 0; } /* gfx_directx_create_primary: * Low-level DirectDraw screen creation routine. */ int gfx_directx_create_primary(void) { /* create primary surface */ gfx_directx_primary_surface = gfx_directx_create_surface(0, 0, NULL, DDRAW_SURFACE_PRIMARY); if (!gfx_directx_primary_surface) { _TRACE(PREFIX_E "Can't create primary surface.\n"); return -1; } return 0; } /* gfx_directx_create_clipper: * Low-level DirectDraw clipper creation routine. */ int gfx_directx_create_clipper(HWND hwnd) { HRESULT hr; hr = IDirectDraw2_CreateClipper(directdraw, 0, &ddclipper, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't create clipper (%x)\n", hr); return -1; } hr = IDirectDrawClipper_SetHWnd(ddclipper, 0, hwnd); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't set clipper window (%x)\n", hr); return -1; } return 0; } /* gfx_directx_create_palette: * Low-level DirectDraw palette creation routine. */ int gfx_directx_create_palette(DDRAW_SURFACE *surf) { HRESULT hr; int n; /* prepare palette entries */ for (n = 0; n < 256; n++) { palette_entry[n].peFlags = PC_NOCOLLAPSE | PC_RESERVED; } hr = IDirectDraw2_CreatePalette(directdraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entry, &ddpalette, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't create palette (%x)\n", hr); return -1; } hr = IDirectDrawSurface2_SetPalette(surf->id, ddpalette); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't set palette (%x)\n", hr); return -1; } surf->flags |= DDRAW_SURFACE_INDEXED; return 0; } /* gfx_directx_setup_driver: * Helper function for initializing the gfx driver. */ int gfx_directx_setup_driver(GFX_DRIVER *drv, int w, int h, int color_depth) { DDSCAPS ddsCaps; /* setup the driver structure */ drv->w = w; drv->h = h; drv->linear = 1; ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; IDirectDraw2_GetAvailableVidMem(directdraw, &ddsCaps, (unsigned long*)&drv->vid_mem, NULL); drv->vid_mem += w * h * BYTES_PER_PIXEL(color_depth); /* create our pseudo surface memory */ pseudo_surf_mem = _AL_MALLOC_ATOMIC(2048 * BYTES_PER_PIXEL(color_depth)); /* modify the vtable to work with video memory */ memcpy(&_screen_vtable, _get_vtable(color_depth), sizeof(_screen_vtable)); _screen_vtable.unwrite_bank = gfx_directx_unwrite_bank; _screen_vtable.acquire = gfx_directx_lock; _screen_vtable.release = gfx_directx_unlock; _screen_vtable.created_sub_bitmap = gfx_directx_created_sub_bitmap; return 0; } /* finalize_directx_init: * Low-level DirectDraw init finalization routine. */ int finalize_directx_init(void) { HRESULT hr; unsigned long int freq; /* set current refresh rate */ hr = IDirectDraw2_GetMonitorFrequency(directdraw, &freq); if (FAILED(hr)) _set_current_refresh_rate(0); else _set_current_refresh_rate(freq); return 0; } /* exit_directx: * Low-level DirectDraw shut down routine. */ int exit_directx(void) { if (directdraw) { /* set cooperative level back to normal */ IDirectDraw2_SetCooperativeLevel(directdraw, win_get_window(), DDSCL_NORMAL); /* release DirectDraw interface */ IDirectDraw2_Release(directdraw); directdraw = NULL; } return 0; } /* gfx_directx_init: */ struct BITMAP *gfx_directx_init(GFX_DRIVER *drv, int w, int h, int v_w, int v_h, int color_depth) { if ((v_w != w && v_w != 0) || (v_h != h && v_h != 0)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } /* set up DirectDraw */ if (init_directx() != 0) goto Error; /* switch to fullscreen */ if (set_video_mode(w, h, v_w, v_h, color_depth) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not set video mode")); goto Error; } if (finalize_directx_init() != 0) goto Error; /* create screen */ if (gfx_directx_create_primary() != 0) goto Error; /* set color format */ if (color_depth == 8) { if (gfx_directx_create_palette(gfx_directx_primary_surface) != 0) goto Error; } else { if (gfx_directx_update_color_format(gfx_directx_primary_surface, color_depth) != 0) goto Error; } /* set gfx driver interface */ if (gfx_directx_setup_driver(drv, w, h, color_depth) != 0) goto Error; /* create forefront bitmap */ gfx_directx_forefront_bitmap = gfx_directx_make_bitmap_from_surface(gfx_directx_primary_surface, w, h, BMP_ID_VIDEO); return gfx_directx_forefront_bitmap; Error: gfx_directx_exit(NULL); return NULL; } /* gfx_directx_set_palette: */ void gfx_directx_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { int n; /* convert into Windows format */ for (n = from; n <= to; n++) { palette_entry[n].peRed = (p[n].r << 2) | ((p[n].r & 0x30) >> 4); palette_entry[n].peGreen = (p[n].g << 2) | ((p[n].g & 0x30) >> 4); palette_entry[n].peBlue = (p[n].b << 2) | ((p[n].b & 0x30) >> 4); } /* wait for vertical retrace */ if (vsync) gfx_directx_sync(); /* set the convert palette */ IDirectDrawPalette_SetEntries(ddpalette, 0, from, to - from + 1, &palette_entry[from]); } /* gfx_directx_sync: * wait for vertical sync */ void gfx_directx_sync(void) { IDirectDraw2_WaitForVerticalBlank(directdraw, DDWAITVB_BLOCKBEGIN, NULL); } /* gfx_directx_exit: */ void gfx_directx_exit(struct BITMAP *bmp) { _enter_critical(); _set_current_refresh_rate(0); if (bmp) clear_bitmap(bmp); /* disconnect from the system driver */ win_gfx_driver = NULL; /* destroy primary surface */ if (gfx_directx_primary_surface) { gfx_directx_destroy_surface(gfx_directx_primary_surface); gfx_directx_primary_surface = NULL; gfx_directx_forefront_bitmap = NULL; } /* normally this list must be empty */ unregister_all_ddraw_surfaces(); /* destroy clipper */ if (ddclipper) { IDirectDrawClipper_Release(ddclipper); ddclipper = NULL; } /* destroy palette */ if (ddpalette) { IDirectDrawPalette_Release(ddpalette); ddpalette = NULL; } /* free pseudo memory */ if (pseudo_surf_mem) { _AL_FREE(pseudo_surf_mem); pseudo_surf_mem = NULL; } /* before restoring video mode, hide window */ set_display_switch_mode(SWITCH_PAUSE); system_driver->restore_console_state(); restore_window_style(); /* let the window thread set the coop level back * to normal and destroy the directdraw object */ wnd_call_proc(exit_directx); _exit_critical(); } static HCURSOR hcursor = NULL; static HBITMAP and_mask = NULL; static HBITMAP xor_mask = NULL; /* gfx_directx_set_mouse_sprite: * Create a Windows system cursor from the specified bitmap */ int gfx_directx_set_mouse_sprite(struct BITMAP *sprite, int xfocus, int yfocus) { int mask_color; int x, y; int sys_sm_cx, sys_sm_cy; HDC h_dc; HDC h_and_dc; HDC h_xor_dc; ICONINFO iconinfo; HBITMAP hOldAndMaskBitmap; HBITMAP hOldXorMaskBitmap; HWND allegro_wnd = win_get_window(); if (hcursor) { if (_win_hcursor == hcursor) _win_hcursor = NULL; DestroyIcon(hcursor); hcursor = NULL; } if (and_mask) { DeleteObject(and_mask); and_mask = NULL; } if (xor_mask) { DeleteObject(xor_mask); xor_mask = NULL; } /* Get allowed cursor size - Windows can't make cursors of arbitrary size */ sys_sm_cx = GetSystemMetrics(SM_CXCURSOR); sys_sm_cy = GetSystemMetrics(SM_CYCURSOR); /* Test if we can make a cursor compatible with the one requested */ if (sprite && (sprite->w <= sys_sm_cx) && (sprite->h <= sys_sm_cy)) { /* Create bitmap */ h_dc = GetDC(allegro_wnd); h_xor_dc = CreateCompatibleDC(h_dc); h_and_dc = CreateCompatibleDC(h_dc); /* Prepare AND (monochrome) and XOR (colour) mask */ and_mask = CreateBitmap(sys_sm_cx, sys_sm_cy, 1, 1, NULL); xor_mask = CreateCompatibleBitmap(h_dc, sys_sm_cx, sys_sm_cy); hOldAndMaskBitmap = SelectObject(h_and_dc, and_mask); hOldXorMaskBitmap = SelectObject(h_xor_dc, xor_mask); /* Create transparent cursor */ for (y = 0; y < sys_sm_cy; y++) { for (x = 0; x < sys_sm_cx; x++) { SetPixel(h_and_dc, x, y, WINDOWS_RGB(255, 255, 255)); SetPixel(h_xor_dc, x, y, WINDOWS_RGB(0, 0, 0)); } } draw_to_hdc(h_xor_dc, sprite, 0, 0); mask_color = bitmap_mask_color(sprite); /* Make cursor background transparent */ for (y = 0; y < sprite->h; y++) { for (x = 0; x < sprite->w; x++) { if (getpixel(sprite, x, y) != mask_color) { /* Don't touch XOR value */ SetPixel(h_and_dc, x, y, 0); } else { /* No need to touch AND value */ SetPixel(h_xor_dc, x, y, WINDOWS_RGB(0, 0, 0)); } } } SelectObject(h_and_dc, hOldAndMaskBitmap); SelectObject(h_xor_dc, hOldXorMaskBitmap); DeleteDC(h_and_dc); DeleteDC(h_xor_dc); ReleaseDC(allegro_wnd, h_dc); iconinfo.fIcon = FALSE; iconinfo.xHotspot = xfocus; iconinfo.yHotspot = yfocus; iconinfo.hbmMask = and_mask; iconinfo.hbmColor = xor_mask; hcursor = CreateIconIndirect(&iconinfo); return 0; } return -1; } /* gfx_directx_show_mouse: * Switch the Windows cursor to a hardware cursor */ int gfx_directx_show_mouse(struct BITMAP *bmp, int x, int y) { if (hcursor) { _win_hcursor = hcursor; } if (_win_hcursor) { POINT p; SetCursor(_win_hcursor); /* Windows is too stupid to actually display the mouse pointer when we * change it and waits until it is moved, so we have to generate a fake * mouse move to actually show the cursor. */ GetCursorPos(&p); SetCursorPos(p.x, p.y); return 0; } return -1; } /* gfx_directx_hide_mouse: * Hide the hardware cursor */ void gfx_directx_hide_mouse(void) { POINT p; /* We need to destroy the custom cursor image too, otherwise Allegro will * get confused when we try to display a system cursor. */ if (hcursor) { DestroyIcon(hcursor); hcursor = NULL; } _win_hcursor = NULL; SetCursor(NULL); /* Windows is too stupid to actually display the mouse pointer when we * change it and waits until it is moved, so we have to generate a fake * mouse move to actually show the cursor. */ GetCursorPos(&p); SetCursorPos(p.x, p.y); } /* gfx_directx_move_mouse: * Move the hardware cursor (not needed) */ void gfx_directx_move_mouse(int x, int y) { } allegro-4.4.3.1/src/win/winput.c0000664000175000017500000001364013437077643015362 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Input management functions. * * By Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-winput INFO: " #define PREFIX_W "al-winput WARNING: " #define PREFIX_E "al-winput ERROR: " #define MAX_EVENTS 8 /* input thread event queue */ int _win_input_events; HANDLE _win_input_event_id[MAX_EVENTS]; void (*_win_input_event_handler[MAX_EVENTS])(void); /* pending event waiting for being processed */ static HANDLE pending_event_id; static void (*pending_event_handler)(void); /* internal input thread management */ static HANDLE ack_event = NULL; static int reserved_events = 0; static int input_need_thread = FALSE; static HANDLE input_thread = NULL; /* input_thread_proc: [input thread] * Thread function that handles the input when there is * no dedicated window thread because the library has * been attached to an external window. */ static void input_thread_proc(LPVOID unused) { DWORD result; _win_thread_init(); _TRACE(PREFIX_I "input thread starts\n"); /* event loop */ while (TRUE) { result = WaitForMultipleObjects(_win_input_events, _win_input_event_id, FALSE, INFINITE); if (result == WAIT_OBJECT_0 + 2) break; /* thread suicide */ else if (result < (DWORD)(WAIT_OBJECT_0 + _win_input_events)) (*_win_input_event_handler[result - WAIT_OBJECT_0])(); } _TRACE(PREFIX_I "input thread exits\n"); _win_thread_exit(); } /* register_pending_event: [input thread] * Registers effectively the pending event. */ static void register_pending_event(void) { /* add the pending event to the queue */ _win_input_event_id[_win_input_events] = pending_event_id; _win_input_event_handler[_win_input_events] = pending_event_handler; /* adjust the size of the queue */ _win_input_events++; /* acknowledge the registration */ SetEvent(ack_event); } /* unregister_pending_event: [input thread] * Unregisters effectively the pending event. */ static void unregister_pending_event(void) { int i, found = -1; /* look for the pending event in the event queue */ for (i=reserved_events; i<_win_input_events; i++) { if (_win_input_event_id[i] == pending_event_id) { found = i; break; } } if (found >= 0) { /* shift the queue to the left */ for (i=found; i<_win_input_events-1; i++) { _win_input_event_id[i] = _win_input_event_id[i+1]; _win_input_event_handler[i] = _win_input_event_handler[i+1]; } /* adjust the size of the queue */ _win_input_events--; } /* acknowledge the unregistration */ SetEvent(ack_event); } /* _win_input_register_event: [primary thread] * Adds an event to the input thread event queue. */ int _win_input_register_event(HANDLE event_id, void (*event_handler)(void)) { if (_win_input_events == MAX_EVENTS) return -1; /* record the event */ pending_event_id = event_id; pending_event_handler = event_handler; /* create the input thread if none */ if (input_need_thread && !input_thread) input_thread = (HANDLE) _beginthread(input_thread_proc, 0, NULL); /* ask the input thread to register the pending event */ SetEvent(_win_input_event_id[0]); /* wait for the input thread to acknowledge */ WaitForSingleObject(ack_event, INFINITE); _TRACE(PREFIX_I "1 input event registered (total = %d)\n", _win_input_events-reserved_events); return 0; } /* _win_input_unregister_event: [primary thread] * Removes an event from the input thread event queue. */ void _win_input_unregister_event(HANDLE event_id) { /* record the event */ pending_event_id = event_id; /* ask the input thread to unregister the pending event */ SetEvent(_win_input_event_id[1]); /* wait for the input thread to acknowledge */ WaitForSingleObject(ack_event, INFINITE); /* kill the input thread if no more event */ if (input_need_thread && (_win_input_events == reserved_events)) { SetEvent(_win_input_event_id[2]); /* thread suicide */ input_thread = NULL; } _TRACE(PREFIX_I "1 input event unregistered (total = %d)\n", _win_input_events-reserved_events); } /* _win_input_init: [primary thread] * Initializes the module. */ void _win_input_init(int need_thread) { int i; for (i = 0; i < MAX_EVENTS; ++i) { _win_input_event_id[i] = 0; _win_input_event_handler[i] = NULL; } _win_input_event_id[0] = CreateEvent(NULL, FALSE, FALSE, NULL); _win_input_event_handler[0] = register_pending_event; _win_input_event_id[1] = CreateEvent(NULL, FALSE, FALSE, NULL); _win_input_event_handler[1] = unregister_pending_event; if (need_thread) { input_need_thread = TRUE; _win_input_event_id[2] = CreateEvent(NULL, FALSE, FALSE, NULL); reserved_events = 3; } else { input_need_thread = FALSE; reserved_events = 2; } _win_input_events = reserved_events; ack_event = CreateEvent(NULL, FALSE, FALSE, NULL); } /* _win_input_exit: [primary thread] * Shuts down the module. */ void _win_input_exit(void) { int i; for (i=0; i #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wjoy INFO: " #define PREFIX_W "al-wjoy WARNING: " #define PREFIX_E "al-wjoy ERROR: " static int joystick_win32_init(void); static void joystick_win32_exit(void); static int joystick_win32_poll(void); JOYSTICK_DRIVER joystick_win32 = { JOY_TYPE_WIN32, empty_string, empty_string, "Win32 joystick", joystick_win32_init, joystick_win32_exit, joystick_win32_poll, NULL, NULL, NULL, NULL }; struct WIN32_JOYSTICK_INFO { WINDOWS_JOYSTICK_INFO_MEMBERS int device; int axis_min[WINDOWS_MAX_AXES]; int axis_max[WINDOWS_MAX_AXES]; }; struct WIN32_JOYSTICK_INFO win32_joystick[MAX_JOYSTICKS]; static int win32_joy_num = 0; /* joystick_win32_poll: * Polls the Win32 joystick devices. */ static int joystick_win32_poll(void) { int n_joy, n_axis, n_but, p, range; JOYINFOEX js; for (n_joy = 0; n_joy < win32_joy_num; n_joy++) { js.dwSize = sizeof(js); js.dwFlags = JOY_RETURNALL; if (joyGetPosEx(win32_joystick[n_joy].device, &js) == JOYERR_NOERROR) { /* axes */ win32_joystick[n_joy].axis[0] = js.dwXpos; win32_joystick[n_joy].axis[1] = js.dwYpos; n_axis = 2; if (win32_joystick[n_joy].caps & JOYCAPS_HASZ) { win32_joystick[n_joy].axis[n_axis] = js.dwZpos; n_axis++; } if (win32_joystick[n_joy].caps & JOYCAPS_HASR) { win32_joystick[n_joy].axis[n_axis] = js.dwRpos; n_axis++; } if (win32_joystick[n_joy].caps & JOYCAPS_HASU) { win32_joystick[n_joy].axis[n_axis] = js.dwUpos; n_axis++; } if (win32_joystick[n_joy].caps & JOYCAPS_HASV) { win32_joystick[n_joy].axis[n_axis] = js.dwVpos; n_axis++; } /* map Windows axis range to 0-256 Allegro range */ for (n_axis = 0; n_axis < win32_joystick[n_joy].num_axes; n_axis++) { p = win32_joystick[n_joy].axis[n_axis] - win32_joystick[n_joy].axis_min[n_axis]; range = win32_joystick[n_joy].axis_max[n_axis] - win32_joystick[n_joy].axis_min[n_axis]; if (range > 0) win32_joystick[n_joy].axis[n_axis] = p * 256 / range; else win32_joystick[n_joy].axis[n_axis] = 0; } /* hat */ if (win32_joystick[n_joy].caps & JOYCAPS_HASPOV) win32_joystick[n_joy].hat = js.dwPOV; /* buttons */ for (n_but = 0; n_but < win32_joystick[n_joy].num_buttons; n_but++) win32_joystick[n_joy].button[n_but] = ((js.dwButtons & (1 << n_but)) != 0); } else { for(n_axis = 0; n_axis MAX_JOYSTICKS) _TRACE(PREFIX_W "The system supports more than %d joysticks\n", MAX_JOYSTICKS); /* retrieve joystick infos */ n_joy = 0; for (n_joyat = 0; n_joyat < win32_joy_num; n_joyat++) { if (n_joy == MAX_JOYSTICKS) break; if (joyGetDevCaps(n_joyat, &caps, sizeof(caps)) == JOYERR_NOERROR) { /* is the joystick physically attached? */ js.dwSize = sizeof(js); js.dwFlags = JOY_RETURNALL; if (joyGetPosEx(n_joyat, &js) == JOYERR_UNPLUGGED) continue; memset(&win32_joystick[n_joy], 0, sizeof(struct WIN32_JOYSTICK_INFO)); /* set global properties */ win32_joystick[n_joy].device = n_joyat; win32_joystick[n_joy].caps = caps.wCaps; win32_joystick[n_joy].num_buttons = MIN(caps.wNumButtons, MAX_JOYSTICK_BUTTONS); win32_joystick[n_joy].num_axes = MIN(caps.wNumAxes, WINDOWS_MAX_AXES); /* fill in ranges of axes */ win32_joystick[n_joy].axis_min[0] = caps.wXmin; win32_joystick[n_joy].axis_max[0] = caps.wXmax; win32_joystick[n_joy].axis_min[1] = caps.wYmin; win32_joystick[n_joy].axis_max[1] = caps.wYmax; n_axis = 2; if (caps.wCaps & JOYCAPS_HASZ) { win32_joystick[n_joy].axis_min[2] = caps.wZmin; win32_joystick[n_joy].axis_max[2] = caps.wZmax; n_axis++; } if (caps.wCaps & JOYCAPS_HASR) { win32_joystick[n_joy].axis_min[n_axis] = caps.wRmin; win32_joystick[n_joy].axis_max[n_axis] = caps.wRmax; n_axis++; } if (caps.wCaps & JOYCAPS_HASU) { win32_joystick[n_joy].axis_min[n_axis] = caps.wUmin; win32_joystick[n_joy].axis_max[n_axis] = caps.wUmax; n_axis++; } if (caps.wCaps & JOYCAPS_HASV) { win32_joystick[n_joy].axis_min[n_axis] = caps.wVmin; win32_joystick[n_joy].axis_max[n_axis] = caps.wVmax; n_axis++; } /* register this joystick */ if (win_add_joystick((WINDOWS_JOYSTICK_INFO *)&win32_joystick[n_joy]) != 0) break; n_joy++; } } win32_joy_num = n_joy; return (win32_joy_num == 0); } /* joystick_win32_exit: * Shuts down the Win32 joystick driver. */ static void joystick_win32_exit(void) { win_remove_all_joysticks(); win32_joy_num = 0; } allegro-4.4.3.1/src/win/wfile.c0000664000175000017500000002133013437077643015135 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper routines to make file.c work on Windows platforms. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #endif #include "allegro.h" #include "winalleg.h" #include "allegro/internal/aintern.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif /* _al_file_isok: * Helper function to check if it is safe to access a file on a floppy * drive. This really only applies to the DOS library, so we don't bother * with it. */ int _al_file_isok(AL_CONST char *filename) { return TRUE; } /* _al_detect_filename_encoding: * Platform specific function to detect the filename encoding. This is called * after setting a system driver, and even if this driver is SYSTEM_NONE. */ void _al_detect_filename_encoding(void) { #ifdef ALLEGRO_DMC /* DMC's C library does not support _wfinddata_t */ set_filename_encoding(U_ASCII); #else /* Windows NT 4.0, 2000, XP, etc support unicode filenames */ set_filename_encoding(GetVersion() & 0x80000000 ? U_ASCII : U_UNICODE); #endif } /* _al_file_size_ex: * Measures the size of the specified file. */ uint64_t _al_file_size_ex(AL_CONST char *filename) { struct _stat s; char tmp[1024]; if (get_filename_encoding() != U_UNICODE) { if (_stat(uconvert(filename, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } } else { if (_wstat((wchar_t*)uconvert(filename, U_CURRENT, tmp, U_UNICODE, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } } return s.st_size; } /* _al_file_time: * Returns the timestamp of the specified file. */ time_t _al_file_time(AL_CONST char *filename) { struct _stat s; char tmp[1024]; if (get_filename_encoding() != U_UNICODE) { if (_stat(uconvert(filename, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } } else { if (_wstat((wchar_t*)uconvert(filename, U_CURRENT, tmp, U_UNICODE, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } } return s.st_mtime; } /* structure for use by the directory scanning routines */ struct FF_DATA { union { struct _finddata_t a; struct _wfinddata_t w; } data; long handle; int attrib; }; /* fill_ffblk: * Helper function to fill in an al_ffblk structure. */ static void fill_ffblk(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; if (get_filename_encoding() != U_UNICODE) { info->attrib = ff_data->data.a.attrib; info->time = ff_data->data.a.time_write; info->size = ff_data->data.a.size; do_uconvert(ff_data->data.a.name, U_ASCII, info->name, U_CURRENT, sizeof(info->name)); } else { info->attrib = ff_data->data.w.attrib; info->time = ff_data->data.w.time_write; info->size = ff_data->data.w.size; do_uconvert((const char*)ff_data->data.w.name, U_UNICODE, info->name, U_CURRENT, sizeof(info->name)); } } /* al_findfirst: * Initiates a directory search. */ int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) { struct FF_DATA *ff_data; char tmp[1024]; /* allocate ff_data structure */ ff_data = _AL_MALLOC(sizeof(struct FF_DATA)); if (!ff_data) { *allegro_errno = ENOMEM; return -1; } /* attach it to the info structure */ info->ff_data = (void *) ff_data; /* Windows defines specific flags for NTFS permissions: * FA_TEMPORARY 0x0100 * FA_SPARSE_FILE 0x0200 * FA_REPARSE_POINT 0x0400 * FA_COMPRESSED 0x0800 * FA_OFFLINE 0x1000 * FA_NOT_CONTENT_INDEXED 0x2000 * FA_ENCRYPTED 0x4000 * so we must set them in the mask by default; moreover, * in order to avoid problems with flags added in the * future, we simply set all bits past the first byte. */ ff_data->attrib = attrib | 0xFFFFFF00; /* start the search */ errno = *allegro_errno = 0; if (get_filename_encoding() != U_UNICODE) { ff_data->handle = _findfirst(uconvert(pattern, U_CURRENT, tmp, U_ASCII, sizeof(tmp)), &ff_data->data.a); if (ff_data->handle < 0) { *allegro_errno = errno; _AL_FREE(ff_data); info->ff_data = NULL; return -1; } if (ff_data->data.a.attrib & ~ff_data->attrib) { if (al_findnext(info) != 0) { al_findclose(info); return -1; } else return 0; } } else { ff_data->handle = _wfindfirst((wchar_t*)uconvert(pattern, U_CURRENT, tmp, U_UNICODE, sizeof(tmp)), &ff_data->data.w); if (ff_data->handle < 0) { *allegro_errno = errno; _AL_FREE(ff_data); info->ff_data = NULL; return -1; } if (ff_data->data.w.attrib & ~ff_data->attrib) { if (al_findnext(info) != 0) { al_findclose(info); return -1; } else return 0; } } fill_ffblk(info); return 0; } /* al_findnext: * Retrieves the next file from a directory search. */ int al_findnext(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; if (get_filename_encoding() != U_UNICODE) { do { if (_findnext(ff_data->handle, &ff_data->data.a) != 0) { *allegro_errno = errno; return -1; } } while (ff_data->data.a.attrib & ~ff_data->attrib); } else { do { if (_wfindnext(ff_data->handle, &ff_data->data.w) != 0) { *allegro_errno = errno; return -1; } } while (ff_data->data.w.attrib & ~ff_data->attrib); } fill_ffblk(info); return 0; } /* al_findclose: * Cleans up after a directory search. */ void al_findclose(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; if (ff_data) { _findclose(ff_data->handle); _AL_FREE(ff_data); info->ff_data = NULL; } } /* _al_drive_exists: * Checks whether the specified drive is valid. */ int _al_drive_exists(int drive) { return GetLogicalDrives() & (1 << drive); } /* _al_getdrive: * Returns the current drive number (0=A, 1=B, etc). */ int _al_getdrive(void) { return _getdrive() - 1; } /* _al_getdcwd: * Returns the current directory on the specified drive. */ void _al_getdcwd(int drive, char *buf, int size) { char tmp[1024]; if (get_filename_encoding() != U_UNICODE) { if (_getdcwd(drive+1, tmp, sizeof(tmp))) do_uconvert(tmp, U_ASCII, buf, U_CURRENT, size); else usetc(buf, 0); } else { if (_wgetdcwd(drive+1, (wchar_t*)tmp, sizeof(tmp)/sizeof(wchar_t))) do_uconvert(tmp, U_UNICODE, buf, U_CURRENT, size); else usetc(buf, 0); } } /* _al_ffblk_get_size: * Returns the size out of an _al_ffblk structure. */ uint64_t al_ffblk_get_size(struct al_ffblk *info) { struct FF_DATA *ff_data; ASSERT(info); ff_data = (struct FF_DATA *) info->ff_data; if (get_filename_encoding() != U_UNICODE) { return ff_data->data.a.size; } else { return ff_data->data.w.size; } } /* _al_win_open: * Open a file with open() or _wopen() depending on whether Unicode filenames * are supported by this version of Windows and compiler. */ int _al_win_open(const char *filename, int mode, int perm) { if (get_filename_encoding() != U_UNICODE) { return open(filename, mode, perm); } else { return _wopen((wchar_t*)filename, mode, perm); } } /* _al_win_unlink: * Remove a file with unlink() or _wunlink() depending on whether Unicode * filenames are supported by this version of Windows and compiler. */ int _al_win_unlink(const char *pathname) { if (get_filename_encoding() != U_UNICODE) { return unlink(pathname); } else { return _wunlink((wchar_t*)pathname); } } allegro-4.4.3.1/src/win/wddwin.c0000664000175000017500000005546713437077643015345 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw windowed gfx driver. * * By Isaac Cruz. * * General overhaul by Eric Botcazou. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddwin INFO: " #define PREFIX_W "al-wddwin WARNING: " #define PREFIX_E "al-wddwin ERROR: " char *_al_wd_dirty_lines = NULL; /* used in WRITE_BANK() */ void (*_al_wd_update_window) (RECT *rect) = NULL; /* window updater */ static void gfx_directx_set_palette_win(AL_CONST struct RGB *p, int from, int to, int vsync); static BITMAP *gfx_directx_create_video_bitmap_win(int width, int height); static void gfx_directx_destroy_video_bitmap_win(BITMAP *bmp); static int gfx_directx_show_video_bitmap_win(struct BITMAP *bmp); static BITMAP *init_directx_win(int w, int h, int v_w, int v_h, int color_depth); static void gfx_directx_win_exit(struct BITMAP *bmp); GFX_DRIVER gfx_directx_win = { GFX_DIRECTX_WIN, empty_string, empty_string, "DirectDraw window", init_directx_win, gfx_directx_win_exit, NULL, // AL_METHOD(int, scroll, (int x, int y)); gfx_directx_sync, gfx_directx_set_palette, NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); gfx_directx_create_video_bitmap_win, gfx_directx_destroy_video_bitmap_win, gfx_directx_show_video_bitmap_win, NULL, gfx_directx_create_system_bitmap, gfx_directx_destroy_system_bitmap, gfx_directx_set_mouse_sprite, gfx_directx_show_mouse, gfx_directx_hide_mouse, gfx_directx_move_mouse, NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_video_state, (void*)); NULL, // AL_METHOD(void, restore_video_state, (void*)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, // AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; TRUE, // int linear; 0, // long bank_size; 0, // long bank_gran; 0, // long vid_mem; 0, // long vid_phys_base; TRUE // int windowed; }; static void switch_in_win(void); static void handle_window_enter_sysmode_win(void); static void handle_window_exit_sysmode_win(void); static void handle_window_move_win(int, int, int, int); static void paint_win(RECT *); static WIN_GFX_DRIVER win_gfx_driver_windowed = { TRUE, switch_in_win, NULL, // AL_METHOD(void, switch_out, (void)); handle_window_enter_sysmode_win, handle_window_exit_sysmode_win, handle_window_move_win, NULL, // AL_METHOD(void, iconify, (void)); paint_win }; static char gfx_driver_desc[256] = EMPTY_STRING; static DDRAW_SURFACE *offscreen_surface = NULL; static RECT working_area; static COLORCONV_BLITTER_FUNC *colorconv_blit = NULL; static int direct_updating_mode_enabled; /* configuration flag */ static int direct_updating_mode_on; /* live flag */ static GFX_VTABLE _special_vtable; /* special vtable for offscreen bitmap */ static int reused_offscreen_surface = FALSE; /* get_working_area: * Retrieves the rectangle of the working area. */ static void get_working_area(RECT *working_area) { SystemParametersInfo(SPI_GETWORKAREA, 0, working_area, 0); working_area->left += 3; /* for the taskbar */ working_area->top += 3; working_area->right -= 3; working_area->bottom -= 3; } /* switch_in_win: * Handles window switched in. */ static void switch_in_win(void) { restore_all_ddraw_surfaces(); get_working_area(&working_area); } /* handle_window_enter_sysmode_win: * Causes the driver to switch to indirect updating mode. */ static void handle_window_enter_sysmode_win(void) { if (direct_updating_mode_enabled && colorconv_blit) { if (direct_updating_mode_on) { direct_updating_mode_on = FALSE; _TRACE(PREFIX_I "direct updating mode off\n"); } } } /* handle_window_exit_sysmode_win: * Causes the driver to switch back to direct updating mode. */ static void handle_window_exit_sysmode_win(void) { if (direct_updating_mode_enabled && colorconv_blit) { if (!direct_updating_mode_on) { direct_updating_mode_on = TRUE; _TRACE(PREFIX_I "direct updating mode on\n"); } } } /* handle_window_move_win: * Makes sure alignment is kept after the window has been moved. */ static void handle_window_move_win(int x, int y, int w, int h) { int xmod; RECT window_rect; HWND allegro_wnd = win_get_window(); if (colorconv_blit) { if (((BYTES_PER_PIXEL(_win_desktop_depth) == 1) && (xmod=ABS(x)%4)) || ((BYTES_PER_PIXEL(_win_desktop_depth) == 2) && (xmod=ABS(x)%2)) || ((BYTES_PER_PIXEL(_win_desktop_depth) == 3) && (xmod=ABS(x)%4))) { GetWindowRect(allegro_wnd, &window_rect); SetWindowPos(allegro_wnd, 0, window_rect.left + (x > 0 ? -xmod : xmod), window_rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); _TRACE(PREFIX_I "window shifted by %d pixe%s to the %s to enforce alignment\n", xmod, xmod > 1 ? "ls" : "l", x > 0 ? "left" : "right"); } } else { /* JG: avoid artifacts when moving fast the window on WinXP. */ InvalidateRect(allegro_wnd, NULL, FALSE); } } /* paint_win: * Handles window paint events. */ static void paint_win(RECT *rect) { /* we may have lost the DirectDraw surfaces * (e.g after the monitor has gone to low power) */ if (IDirectDrawSurface2_IsLost(gfx_directx_primary_surface->id)) switch_in_win(); /* clip the rectangle */ rect->right = MIN(rect->right, gfx_directx_win.w); rect->bottom = MIN(rect->bottom, gfx_directx_win.h); _al_wd_update_window(rect); } /* update_matching_window: * Updates a portion of the window when the color depths match. */ static void update_matching_window(RECT *rect) { HWND allegro_wnd = win_get_window(); union { POINT p; RECT r; } dest_rect; _enter_gfx_critical(); if (!gfx_directx_forefront_bitmap) { _exit_gfx_critical(); return; } if (rect) dest_rect.r = *rect; else { dest_rect.r.left = 0; dest_rect.r.right = gfx_directx_win.w; dest_rect.r.top = 0; dest_rect.r.bottom = gfx_directx_win.h; } ClientToScreen(allegro_wnd, &dest_rect.p); ClientToScreen(allegro_wnd, &dest_rect.p + 1); /* blit offscreen backbuffer to the window */ IDirectDrawSurface2_Blt(gfx_directx_primary_surface->id, &dest_rect.r, offscreen_surface->id, rect, 0, NULL); _exit_gfx_critical(); } /* is_contained: * Helper to find the relative position of two rectangles. */ static INLINE int is_contained(RECT *rect1, RECT *rect2) { if ((rect1->left >= rect2->left) && (rect1->top >= rect2->top) && (rect1->right <= rect2->right) && (rect1->bottom <= rect2->bottom)) return TRUE; else return FALSE; } /* ddsurf_blit_ex: * Extended blit function performing color conversion. */ static int ddsurf_blit_ex(LPDIRECTDRAWSURFACE2 dest_surf, RECT *dest_rect, LPDIRECTDRAWSURFACE2 src_surf, RECT *src_rect) { DDSURFACEDESC src_desc, dest_desc; GRAPHICS_RECT src_gfx_rect, dest_gfx_rect; HRESULT hr; src_desc.dwSize = sizeof(src_desc); src_desc.dwFlags = 0; dest_desc.dwSize = sizeof(dest_desc); dest_desc.dwFlags = 0; hr = IDirectDrawSurface2_Lock(dest_surf, dest_rect, &dest_desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); if (FAILED(hr)) return -1; hr = IDirectDrawSurface2_Lock(src_surf, src_rect, &src_desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); if (FAILED(hr)) { IDirectDrawSurface2_Unlock(dest_surf, NULL); return -1; } /* fill in source graphics rectangle description */ src_gfx_rect.width = src_rect->right - src_rect->left; src_gfx_rect.height = src_rect->bottom - src_rect->top; src_gfx_rect.pitch = src_desc.lPitch; src_gfx_rect.data = src_desc.lpSurface; /* fill in destination graphics rectangle description */ dest_gfx_rect.pitch = dest_desc.lPitch; dest_gfx_rect.data = dest_desc.lpSurface; /* function doing the hard work */ colorconv_blit(&src_gfx_rect, &dest_gfx_rect); IDirectDrawSurface2_Unlock(src_surf, NULL); IDirectDrawSurface2_Unlock(dest_surf, NULL); return 0; } /* update_colorconv_window: * Updates a portion of the window when the color depths don't match. */ static void update_colorconv_window(RECT *rect) { RECT src_rect; union { POINT p; RECT r; } dest_rect; HDC src_dc, dest_dc; HRESULT hr; int direct; HWND allegro_wnd = win_get_window(); _enter_gfx_critical(); if (!gfx_directx_forefront_bitmap) { _exit_gfx_critical(); return; } if (rect) { #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH src_rect.left = rect->left & 0xfffffffc; src_rect.right = (rect->right+3) & 0xfffffffc; #else src_rect.left = rect->left; src_rect.right = rect->right; #endif src_rect.top = rect->top; src_rect.bottom = rect->bottom; } else { src_rect.left = 0; src_rect.right = gfx_directx_win.w; src_rect.top = 0; src_rect.bottom = gfx_directx_win.h; } dest_rect.r = src_rect; ClientToScreen(allegro_wnd, &dest_rect.p); ClientToScreen(allegro_wnd, &dest_rect.p + 1); direct = (direct_updating_mode_on && is_contained(&dest_rect.r, &working_area) && GetForegroundWindow() == allegro_wnd); if (direct) { /* blit directly to the primary surface without clipping */ ddsurf_blit_ex(gfx_directx_primary_surface->id, &dest_rect.r, offscreen_surface->id, &src_rect); } else { /* blit to the window using GDI */ hr = IDirectDrawSurface2_GetDC(offscreen_surface->id, &src_dc); if (FAILED(hr)) goto End; dest_dc = GetDC(allegro_wnd); if (!dest_dc) { IDirectDrawSurface2_ReleaseDC(offscreen_surface->id, src_dc); goto End; } BitBlt(dest_dc, src_rect.left, src_rect.top, src_rect.right - src_rect.left, src_rect.bottom - src_rect.top, src_dc, src_rect.left, src_rect.top, SRCCOPY); ReleaseDC(allegro_wnd, dest_dc); IDirectDrawSurface2_ReleaseDC(offscreen_surface->id, src_dc); } End: _exit_gfx_critical(); } /* gfx_directx_create_video_bitmap_win: */ static BITMAP *gfx_directx_create_video_bitmap_win(int width, int height) { DDRAW_SURFACE *surf; BITMAP *bmp; /* try to detect page flipping and triple buffering patterns */ if ((width == gfx_directx_forefront_bitmap->w) && (height == gfx_directx_forefront_bitmap->h) && (!reused_offscreen_surface)) { /* recycle the offscreen surface as a video bitmap */ bmp = gfx_directx_make_bitmap_from_surface(offscreen_surface, width, height, BMP_ID_VIDEO); if (bmp) { bmp->vtable = &_special_vtable; bmp->write_bank = gfx_directx_write_bank_win; offscreen_surface->parent_bmp = bmp; reused_offscreen_surface = TRUE; } return bmp; } /* create the DirectDraw surface */ if (colorconv_blit) { surf = gfx_directx_create_surface(width, height, ddpixel_format, DDRAW_SURFACE_SYSTEM); } else { surf = gfx_directx_create_surface(width, height, NULL, DDRAW_SURFACE_VIDEO); if (!surf) surf = gfx_directx_create_surface(width, height, NULL, DDRAW_SURFACE_SYSTEM); } if (!surf) return NULL; /* create the bitmap that wraps up the surface */ bmp = gfx_directx_make_bitmap_from_surface(surf, width, height, BMP_ID_VIDEO); if (!bmp) { gfx_directx_destroy_surface(surf); return NULL; } surf->parent_bmp = bmp; return bmp; } /* gfx_directx_destroy_video_bitmap_win: */ static void gfx_directx_destroy_video_bitmap_win(BITMAP *bmp) { DDRAW_SURFACE *surf; surf = DDRAW_SURFACE_OF(bmp); if (surf == offscreen_surface) { reused_offscreen_surface = FALSE; } else { /* destroy the surface */ gfx_directx_destroy_surface(surf); } _AL_FREE(bmp); } /* gfx_directx_show_video_bitmap_win: * Makes the specified video bitmap visible. */ static int gfx_directx_show_video_bitmap_win(BITMAP *bmp) { DDRAW_SURFACE *surf; BITMAP *former_visible_bmp; /* guard against show_video_bitmap(screen); */ surf = DDRAW_SURFACE_OF(bmp); if (surf == offscreen_surface) return 0; former_visible_bmp = offscreen_surface->parent_bmp; /* manually flip the offscreen surface */ gfx_directx_forefront_bitmap->extra = surf; offscreen_surface = surf; /* restore regular methods for video bitmaps */ former_visible_bmp->vtable->release = gfx_directx_unlock; former_visible_bmp->vtable->unwrite_bank = gfx_directx_unwrite_bank; former_visible_bmp->write_bank = gfx_directx_write_bank; /* set special methods for the forefront bitmap */ bmp->vtable->release = gfx_directx_unlock_win; bmp->vtable->unwrite_bank = gfx_directx_unwrite_bank_win; bmp->write_bank = gfx_directx_write_bank_win; /* display the new contents */ if (_wait_for_vsync) gfx_directx_sync(); _al_wd_update_window(NULL); return 0; } /* gfx_directx_set_palette_win_8: * Updates the palette for color conversion from 8-bit to 8-bit. */ static void gfx_directx_set_palette_win_8(AL_CONST struct RGB *p, int from, int to, int vsync) { unsigned char *cmap; int n; cmap = _get_colorconv_map(); for (n = from; n <= to; n++) cmap[n] = _win_desktop_rgb_map.data[p[n].r>>1][p[n].g>>1][p[n].b>>1]; _al_wd_update_window(NULL); } /* gfx_directx_set_palette_win: * Updates the palette for color conversion from 8-bit to hi/true color. */ static void gfx_directx_set_palette_win(AL_CONST struct RGB *p, int from, int to, int vsync) { /* for the normal updating mode */ gfx_directx_set_palette(p, from, to, FALSE); /* for the direct updating mode */ _set_colorconv_palette(p, from, to); _al_wd_update_window(NULL); } /* wnd_set_windowed_coop: * Sets the DirectDraw cooperative level. */ static int wnd_set_windowed_coop(void) { HRESULT hr; HWND allegro_wnd = win_get_window(); hr = IDirectDraw2_SetCooperativeLevel(directdraw, allegro_wnd, DDSCL_NORMAL); if (FAILED(hr)) { _TRACE(PREFIX_E "SetCooperative level = %s (%x), hwnd = %x\n", win_err_str(hr), hr, allegro_wnd); return -1; } return 0; } /* verify_color_depth: * Compares the requested color depth with the desktop color depth. */ static int verify_color_depth (int color_depth) { AL_CONST char *ddu; char tmp1[64], tmp2[128]; int i; if ((gfx_directx_compare_color_depth(color_depth) == 0) && (color_depth != 8)) { /* the color depths match */ _al_wd_update_window = update_matching_window; } else { /* disallow cross-conversion between 15-bit and 16-bit colors */ if ((BYTES_PER_PIXEL(color_depth) == 2) && (BYTES_PER_PIXEL(_win_desktop_depth) == 2)) return -1; /* the color depths don't match, need color conversion */ colorconv_blit = _get_colorconv_blitter(color_depth, _win_desktop_depth); if (!colorconv_blit) return -1; _al_wd_update_window = update_colorconv_window; /* read direct updating configuration variable */ ddu = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("disable_direct_updating", tmp2), NULL); if ((ddu) && ((i = ugetc(ddu)) != 0) && ((i == 'y') || (i == 'Y') || (i == '1'))) direct_updating_mode_enabled = FALSE; else direct_updating_mode_enabled = TRUE; direct_updating_mode_on = direct_updating_mode_enabled; } return 0; } /* create_offscreen: * Creates the offscreen surface. */ static int create_offscreen(int w, int h, int color_depth) { if (colorconv_blit) { /* create offscreen surface in system memory */ offscreen_surface = gfx_directx_create_surface(w, h, ddpixel_format, DDRAW_SURFACE_SYSTEM); } else { /* create offscreen surface in video memory */ offscreen_surface = gfx_directx_create_surface(w, h, NULL, DDRAW_SURFACE_VIDEO); if (!offscreen_surface) { _TRACE(PREFIX_E "Can't create offscreen surface in video memory.\n"); /* create offscreen surface in system memory */ offscreen_surface = gfx_directx_create_surface(w, h, NULL, DDRAW_SURFACE_SYSTEM); } } if (!offscreen_surface) { _TRACE(PREFIX_E "Can't create offscreen surface.\n"); return -1; } return 0; } /* gfx_directx_setup_driver_desc: * Sets the driver description string. */ static void gfx_directx_setup_driver_desc(void) { char tmp1[128], tmp2[128]; uszprintf(gfx_driver_desc, sizeof(gfx_driver_desc), uconvert_ascii("DirectDraw, in %s, %d bpp window", tmp1), uconvert_ascii((colorconv_blit ? "color conversion" : "matching"), tmp2), _win_desktop_depth); gfx_directx_win.desc = gfx_driver_desc; } /* init_directx_win: * Initializes the driver. */ static struct BITMAP *init_directx_win(int w, int h, int v_w, int v_h, int color_depth) { unsigned char *cmap; HRESULT hr; int i; HWND allegro_wnd = win_get_window(); /* flipping is impossible in windowed mode */ if ((v_w != w && v_w != 0) || (v_h != h && v_h != 0)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH if (w%4) return NULL; #endif _enter_critical(); /* init DirectX */ if (init_directx() != 0) goto Error; if (verify_color_depth(color_depth)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); goto Error; } if (wnd_call_proc(wnd_set_windowed_coop) != 0) goto Error; if (finalize_directx_init() != 0) goto Error; if (adjust_window(w, h) != 0) { _TRACE(PREFIX_E "window size not supported.\n"); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto Error; } /* get the working area */ get_working_area(&working_area); /* create primary surface */ if (gfx_directx_create_primary() != 0) goto Error; /* create clipper */ if (gfx_directx_create_clipper(allegro_wnd) != 0) goto Error; hr = IDirectDrawSurface_SetClipper(gfx_directx_primary_surface->id, ddclipper); if (FAILED(hr)) goto Error; /* create offscreen backbuffer */ if (create_offscreen(w, h, color_depth) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Windowed mode not supported")); goto Error; } /* setup color management */ if (_win_desktop_depth == 8) { build_desktop_rgb_map(); if (color_depth == 8) { gfx_directx_win.set_palette = gfx_directx_set_palette_win_8; } else { cmap = _get_colorconv_map(); for (i=0; i<4096; i++) cmap[i] = _win_desktop_rgb_map.data[((i&0xF00)>>7) | ((i&0x800)>>11)] [((i&0x0F0)>>3) | ((i&0x080)>>7)] [((i&0x00F)<<1) | ((i&0x008)>>3)]; if (gfx_directx_update_color_format(offscreen_surface, color_depth) != 0) goto Error; } } else { if (color_depth == 8) { gfx_directx_win.set_palette = gfx_directx_set_palette_win; if (gfx_directx_create_palette(offscreen_surface) != 0) goto Error; /* init the core library color conversion functions */ if (gfx_directx_update_color_format(gfx_directx_primary_surface, _win_desktop_depth) != 0) goto Error; } else { if (gfx_directx_update_color_format(offscreen_surface, color_depth) != 0) goto Error; } } /* setup Allegro gfx driver */ gfx_directx_setup_driver_desc(); if (gfx_directx_setup_driver(&gfx_directx_win, w, h, color_depth) != 0) goto Error; gfx_directx_forefront_bitmap = gfx_directx_make_bitmap_from_surface(offscreen_surface, w, h, BMP_ID_VIDEO); gfx_directx_enable_acceleration(&gfx_directx_win); memcpy(&_special_vtable, &_screen_vtable, sizeof (GFX_VTABLE)); _special_vtable.release = gfx_directx_unlock_win; _special_vtable.unwrite_bank = gfx_directx_unwrite_bank_win; gfx_directx_forefront_bitmap->vtable = &_special_vtable; gfx_directx_forefront_bitmap->write_bank = gfx_directx_write_bank_win; /* the last flag serves as end of loop delimiter */ _al_wd_dirty_lines = _AL_MALLOC_ATOMIC((h+1) * sizeof(char)); ASSERT(_al_wd_dirty_lines); memset(_al_wd_dirty_lines, 0, (h+1) * sizeof(char)); /* connect to the system driver */ win_gfx_driver = &win_gfx_driver_windowed; /* set default switching policy */ set_display_switch_mode(SWITCH_PAUSE); /* grab input devices */ win_grab_input(); _exit_critical(); return gfx_directx_forefront_bitmap; Error: _exit_critical(); /* release the DirectDraw object */ gfx_directx_win_exit(NULL); return NULL; } /* gfx_directx_win_exit: * Shuts down the driver. */ static void gfx_directx_win_exit(struct BITMAP *bmp) { _enter_gfx_critical(); if (bmp) { save_window_pos(); clear_bitmap(bmp); } /* disconnect from the system driver */ win_gfx_driver = NULL; /* destroy dirty lines array */ if (_al_wd_dirty_lines) { _AL_FREE(_al_wd_dirty_lines); _al_wd_dirty_lines = NULL; } /* destroy the offscreen backbuffer */ if (offscreen_surface) { gfx_directx_destroy_surface(offscreen_surface); offscreen_surface = NULL; reused_offscreen_surface = FALSE; gfx_directx_forefront_bitmap = NULL; } /* release the color conversion blitter */ if (colorconv_blit) { _release_colorconv_blitter(colorconv_blit); colorconv_blit = NULL; } gfx_directx_exit(NULL); _exit_gfx_critical(); } allegro-4.4.3.1/src/win/wjoydrv.c0000664000175000017500000000160413437077643015535 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of Windows joystick drivers, kept in a seperate file so that * they can be overriden by user programs. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif BEGIN_JOYSTICK_DRIVER_LIST JOYSTICK_DRIVER_DIRECTX JOYSTICK_DRIVER_WIN32 END_JOYSTICK_DRIVER_LIST allegro-4.4.3.1/src/win/wdsinput.c0000664000175000017500000004142213437077643015710 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectSound input driver. * * By Nick Kochakian. * * API compliance improvements, enhanced format detection * and bugfixes by Javier Gonzalez. * * See readme.txt for copyright information. */ #define DIRECTSOUND_VERSION 0x0500 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #include #ifdef ALLEGRO_MSVC #include #endif #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-dsinput INFO: " #define PREFIX_W "al-dsinput WARNING: " #define PREFIX_E "al-dsinput ERROR: " /* sound driver globals */ static LPDIRECTSOUNDCAPTURE ds_capture = NULL; static LPDIRECTSOUNDCAPTUREBUFFER ds_capture_buf = NULL; static WAVEFORMATEX dsc_buf_wfx; static unsigned long int ds_capture_buffer_size; static unsigned long int last_capture_pos, input_wave_bytes_read; static unsigned char *input_wave_data = NULL; /* ds_err: * Returns a DirectSound error string. */ #ifdef DEBUGMODE static char *ds_err(long err) { static char err_str[64]; switch (err) { case DS_OK: _al_sane_strncpy(err_str, "DS_OK", sizeof(err_str)); break; case DSERR_ALLOCATED: _al_sane_strncpy(err_str, "DSERR_ALLOCATED", sizeof(err_str)); break; case DSERR_BADFORMAT: _al_sane_strncpy(err_str, "DSERR_BADFORMAT", sizeof(err_str)); break; case DSERR_INVALIDPARAM: _al_sane_strncpy(err_str, "DSERR_INVALIDPARAM", sizeof(err_str)); break; case DSERR_NOAGGREGATION: _al_sane_strncpy(err_str, "DSERR_NOAGGREGATION", sizeof(err_str)); break; case DSERR_OUTOFMEMORY: _al_sane_strncpy(err_str, "DSERR_OUTOFMEMORY", sizeof(err_str)); break; case DSERR_UNINITIALIZED: _al_sane_strncpy(err_str, "DSERR_UNINITIALIZED", sizeof(err_str)); break; case DSERR_UNSUPPORTED: _al_sane_strncpy(err_str, "DSERR_UNSUPPORTED", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "DSERR_UNKNOWN", sizeof(err_str)); break; } return err_str; } #else #define ds_err(hr) "\0" #endif /* create_test_capture_buffer: * Helper function that tries to create a capture buffer with * the specified format and deletes it immediatly. */ static int create_test_capture_buffer(WAVEFORMATEX *wfx) { LPDIRECTSOUNDCAPTUREBUFFER dsc_trybuf; DSCBUFFERDESC dsc_trybuf_desc; HRESULT hr; /* create the capture buffer */ ZeroMemory(&dsc_trybuf_desc, sizeof(DSCBUFFERDESC)); dsc_trybuf_desc.dwSize = sizeof(DSCBUFFERDESC); dsc_trybuf_desc.dwFlags = 0; dsc_trybuf_desc.dwBufferBytes = 1024; dsc_trybuf_desc.dwReserved = 0; dsc_trybuf_desc.lpwfxFormat = wfx; hr = IDirectSoundCapture_CreateCaptureBuffer(ds_capture, &dsc_trybuf_desc, &dsc_trybuf, NULL); if (FAILED(hr)) return -1; IDirectSoundCaptureBuffer_Release(dsc_trybuf); return 0; } /* get_capture_format_support: * Helper function to see if the specified input device * can support a combination of capture settings. */ static int get_capture_format_support(int bits, int stereo, int rate, int autodetect, WAVEFORMATEX *wfx) { int i; DSCCAPS dsCaps; HRESULT hr; WAVEFORMATEX *test_wfx; struct { unsigned long int type; unsigned long int freq; unsigned char bits; unsigned char channels; BOOL stereo; } ds_formats[] = { { WAVE_FORMAT_4S16, 44100, 16, 2, TRUE }, { WAVE_FORMAT_2S16, 22050, 16, 2, TRUE }, { WAVE_FORMAT_1S16, 11025, 16, 2, TRUE }, { WAVE_FORMAT_4M16, 44100, 16, 1, FALSE }, { WAVE_FORMAT_2M16, 22050, 16, 1, FALSE }, { WAVE_FORMAT_1M16, 11025, 16, 1, FALSE }, { WAVE_FORMAT_4S08, 44100, 8, 2, TRUE }, { WAVE_FORMAT_2S08, 22050, 8, 2, TRUE }, { WAVE_FORMAT_1S08, 11025, 8, 2, TRUE }, { WAVE_FORMAT_4M08, 44100, 8, 1, FALSE }, { WAVE_FORMAT_2M08, 22050, 8, 1, FALSE }, { WAVE_FORMAT_1M08, 11025, 8, 1, FALSE }, { WAVE_INVALIDFORMAT, 0, 0, 0, FALSE } }; if (!ds_capture) return -1; /* if we have already a capture buffer working * we return its format as the only valid one */ if (ds_capture_buf) { if (!autodetect) { /* we must check that everything that cares is * the same as in the capture buffer settings */ if (((bits > 0) && (dsc_buf_wfx.wBitsPerSample != bits)) || ( stereo && (dsc_buf_wfx.nChannels != 2)) || (!stereo && (dsc_buf_wfx.nChannels != 1)) || ((rate > 0) && (dsc_buf_wfx.nSamplesPerSec != (unsigned int) rate))) return -1; } /* return the actual capture buffer settings */ if (wfx) memcpy(wfx, &dsc_buf_wfx, sizeof(WAVEFORMATEX)); return 0; } /* we use a two-level checking process: * - the normal check of exposed capabilities, * - the actual creation of the capture buffer, * because of the single frequency limitation on some * sound cards (e.g SB16 ISA) in full duplex mode. */ dsCaps.dwSize = sizeof(DSCCAPS); hr = IDirectSoundCapture_GetCaps(ds_capture, &dsCaps); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get input device caps (%s).\n", ds_err(hr)); return -1; } if (wfx) test_wfx = wfx; else test_wfx = _AL_MALLOC(sizeof(WAVEFORMATEX)); for (i=0; ds_formats[i].type != WAVE_INVALIDFORMAT; i++) /* if the current format is supported */ if (dsCaps.dwFormats & ds_formats[i].type) { if (!autodetect) { /* we must check that everything that cares is * the same as in the capture buffer settings */ if (((bits > 0) && (ds_formats[i].bits != bits)) || (stereo && !ds_formats[i].stereo) || (!stereo && ds_formats[i].stereo) || ((rate > 0) && (ds_formats[i].freq != (unsigned int) rate))) continue; /* go to next format */ } test_wfx->wFormatTag = WAVE_FORMAT_PCM; test_wfx->nChannels = ds_formats[i].channels; test_wfx->nSamplesPerSec = ds_formats[i].freq; test_wfx->wBitsPerSample = ds_formats[i].bits; test_wfx->nBlockAlign = test_wfx->nChannels * (test_wfx->wBitsPerSample / 8); test_wfx->nAvgBytesPerSec = test_wfx->nSamplesPerSec * test_wfx->nBlockAlign; test_wfx->cbSize = 0; if (create_test_capture_buffer(test_wfx) == 0) { if (!wfx) _AL_FREE(test_wfx); return 0; } } if (!wfx) _AL_FREE(test_wfx); _TRACE(PREFIX_W "No valid recording formats found.\n"); return -1; } /* digi_directsound_capture_init: */ int digi_directsound_capture_init(LPGUID guid) { DSCCAPS dsCaps; WAVEFORMATEX wfx; HRESULT hr; LPVOID temp; /* the DirectSoundCapture interface is not part of DirectX 3 */ if (_dx_ver < 0x0500) return -1; /* create the device: * we use CoCreateInstance() instead of DirectSoundCaptureCreate() to avoid * the dll loader blocking the start of Allegro under DirectX 3. */ hr = CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSoundCapture, &temp); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't create DirectSoundCapture interface (%s).\n", ds_err(hr)); goto Error; } ds_capture = temp; /* initialize the device */ hr = IDirectSoundCapture_Initialize(ds_capture, guid); if (FAILED(hr)) { hr = IDirectSoundCapture_Initialize(ds_capture, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't initialize DirectSoundCapture interface (%s).\n", ds_err(hr)); goto Error; } } /* get the device caps */ dsCaps.dwSize = sizeof(DSCCAPS); hr = IDirectSoundCapture_GetCaps(ds_capture, &dsCaps); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get input device caps (%s).\n", ds_err(hr)); goto Error; } /* cool little 'autodetection' process :) */ if (get_capture_format_support(0, FALSE, 0, TRUE, &wfx) != 0) { _TRACE(PREFIX_E "The DirectSound hardware doesn't support any capture types.\n"); goto Error; } /* set capabilities */ digi_input_driver->rec_cap_bits = wfx.wBitsPerSample; digi_input_driver->rec_cap_stereo = (wfx.nChannels == 2) ? 1 : 0; return 0; Error: /* shutdown DirectSoundCapture */ digi_directsound_capture_exit(); return -1; } /* digi_directsound_capture_exit: */ void digi_directsound_capture_exit(void) { /* destroy capture buffer */ digi_directsound_rec_stop(); /* shutdown DirectSoundCapture */ if (ds_capture) { IDirectSoundCapture_Release(ds_capture); ds_capture = NULL; } } /* digi_directsound_capture_detect: */ int digi_directsound_capture_detect(LPGUID guid) { HRESULT hr; LPVOID temp; /* the DirectSoundCapture interface is not part of DirectX 3 */ if (_dx_ver < 0x500) return 0; if (!ds_capture) { /* create the device: * we use CoCreateInstance() instead of DirectSoundCaptureCreate() to avoid * the dll loader blocking the start of Allegro under DirectX 3. */ hr = CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSoundCapture, &temp); if (FAILED(hr)) { _TRACE(PREFIX_E "DirectSoundCapture interface creation failed during detect (%s).\n", ds_err(hr)); return 0; } ds_capture = temp; /* initialize the device */ hr = IDirectSoundCapture_Initialize(ds_capture, guid); if (FAILED(hr)) { hr = IDirectSoundCapture_Initialize(ds_capture, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "DirectSoundCapture interface initialization failed during detect (%s).\n", ds_err(hr)); return 0; } } _TRACE(PREFIX_I "DirectSoundCapture interface successfully created.\n"); /* release DirectSoundCapture interface */ IDirectSoundCapture_Release(ds_capture); ds_capture = NULL; } return 1; } /* digi_directsound_rec_cap_rate: * Gets the maximum input frequency for the specified parameters. */ int digi_directsound_rec_cap_rate(int bits, int stereo) { WAVEFORMATEX wfx; if (get_capture_format_support(bits, stereo, 0, FALSE, &wfx) != 0) return 0; return wfx.nSamplesPerSec; } /* digi_directsound_rec_cap_param: * Determines if the combination of provided parameters can be * used for recording. */ int digi_directsound_rec_cap_param(int rate, int bits, int stereo) { if (get_capture_format_support(bits, stereo, rate, FALSE, NULL) == 0) return 2; if (get_capture_format_support(bits, stereo, 44100, FALSE, NULL) == 0) return -44100; if (get_capture_format_support(bits, stereo, 22050, FALSE, NULL) == 0) return -22050; if (get_capture_format_support(bits, stereo, 11025, FALSE, NULL) == 0) return -11025; return 0; } /* digi_directsound_rec_source: * Sets the source for the audio recording. */ int digi_directsound_rec_source(int source) { /* since DirectSoundCapture doesn't allow us to * select a input source manually, we return -1 */ return -1; } /* digi_directsound_rec_start: * Start recording with the specified parameters. */ int digi_directsound_rec_start(int rate, int bits, int stereo) { DSCBUFFERDESC dscBufDesc; HRESULT hr; if (!ds_capture || ds_capture_buf) return 0; /* check if we support the desired format */ if ((bits <= 0) || (rate <= 0)) return 0; if (get_capture_format_support(bits, stereo, rate, FALSE, &dsc_buf_wfx) != 0) return 0; digi_driver->rec_cap_bits = dsc_buf_wfx.wBitsPerSample; digi_driver->rec_cap_stereo = (dsc_buf_wfx.nChannels == 2) ? 1 : 0; /* create the capture buffer */ ZeroMemory(&dscBufDesc, sizeof(DSCBUFFERDESC)); dscBufDesc.dwSize = sizeof(DSCBUFFERDESC); dscBufDesc.dwFlags = 0; dscBufDesc.dwBufferBytes = dsc_buf_wfx.nAvgBytesPerSec; dscBufDesc.dwReserved = 0; dscBufDesc.lpwfxFormat = &dsc_buf_wfx; ds_capture_buffer_size = dscBufDesc.dwBufferBytes; hr = IDirectSoundCapture_CreateCaptureBuffer(ds_capture, &dscBufDesc, &ds_capture_buf, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't create the DirectSound capture buffer (%s).\n", ds_err(hr)); return 0; } hr = IDirectSoundCaptureBuffer_Start(ds_capture_buf, DSCBSTART_LOOPING); if (FAILED(hr)) { IDirectSoundCaptureBuffer_Release(ds_capture_buf); ds_capture_buf = NULL; _TRACE(PREFIX_E "Can't start the DirectSound capture buffer (%s).\n", ds_err(hr)); return 0; } last_capture_pos = 0; input_wave_data = _AL_MALLOC(ds_capture_buffer_size); input_wave_bytes_read = 0; return ds_capture_buffer_size; } /* digi_directsound_rec_stop: * Stops recording. */ void digi_directsound_rec_stop(void) { if (ds_capture_buf) { IDirectSoundCaptureBuffer_Stop(ds_capture_buf); IDirectSoundCaptureBuffer_Release(ds_capture_buf); ds_capture_buf = NULL; } if (input_wave_data) { _AL_FREE(input_wave_data); input_wave_data = NULL; } } /* digi_directsound_rec_read: * Reads the input buffer. */ int digi_directsound_rec_read(void *buf) { unsigned char *input_ptr1, *input_ptr2, *linear_input_ptr; unsigned long int input_bytes1, input_bytes2, bytes_to_lock; unsigned long int capture_pos; HRESULT hr; BOOL buffer_filled = FALSE; LPVOID temp1, temp2; if (!ds_capture || !ds_capture_buf || !input_wave_data) return 0; IDirectSoundCaptureBuffer_GetCurrentPosition(ds_capture_buf, &capture_pos, NULL); /* check if we are not still in the same capture position */ if (last_capture_pos == capture_pos) return 0; /* check how many bytes we need to lock since last check */ if (capture_pos > last_capture_pos) { bytes_to_lock = capture_pos - last_capture_pos; } else { bytes_to_lock = ds_capture_buffer_size - last_capture_pos; bytes_to_lock += capture_pos; } hr = IDirectSoundCaptureBuffer_Lock(ds_capture_buf, last_capture_pos, bytes_to_lock, &temp1, &input_bytes1, &temp2, &input_bytes2, 0); if (FAILED(hr)) return 0; input_ptr1 = temp1; input_ptr2 = temp2; /* let's get the data aligned linearly */ linear_input_ptr = _AL_MALLOC(bytes_to_lock); memcpy(linear_input_ptr, input_ptr1, input_bytes1); if (input_ptr2) memcpy(linear_input_ptr + input_bytes1, input_ptr2, input_bytes2); IDirectSoundCaptureBuffer_Unlock(ds_capture_buf, input_ptr1, input_bytes1, input_ptr2, input_bytes2); if ((input_wave_bytes_read + bytes_to_lock) >= ds_capture_buffer_size) { /* we fill the buffer */ long int bytes_left_to_fill = ds_capture_buffer_size - input_wave_bytes_read; long int bytes_to_internal = bytes_to_lock - bytes_left_to_fill; /* copy old buffer to user buffer */ memcpy((char*)buf, input_wave_data, input_wave_bytes_read); /* and the rest of bytes we would need to fill in the buffer */ memcpy((char*)buf + input_wave_bytes_read, linear_input_ptr, bytes_left_to_fill); /* and the rest of the data to the internal buffer */ input_wave_bytes_read = bytes_to_internal; memcpy(input_wave_data, linear_input_ptr + bytes_left_to_fill, bytes_to_internal); buffer_filled = TRUE; /* if we are using 16-bit data, we need to convert it to unsigned format */ if (digi_driver->rec_cap_bits == 16) { unsigned int i; unsigned short *buf16 = (unsigned short *)buf; for (i = 0; i < ds_capture_buffer_size/2; i++) buf16[i] ^= 0x8000; } } else { /* we won't fill the buffer */ memcpy(input_wave_data + input_wave_bytes_read, linear_input_ptr, bytes_to_lock); input_wave_bytes_read += bytes_to_lock; } _AL_FREE(linear_input_ptr); last_capture_pos = capture_pos; if (buffer_filled) return 1; else return 0; } allegro-4.4.3.1/src/win/wsystem.c0000664000175000017500000003572713437077643015561 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main system driver for the Windows library. * * By Stefan Schimanski. * * Window close button support by Javier Gonzalez. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif /* DMC requires a DllMain() function, or else the DLL hangs. */ #if !defined(ALLEGRO_STATICLINK) && defined(ALLEGRO_DMC) BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason, LPVOID lpReserved) { return TRUE; } #endif static int sys_directx_init(void); static void sys_directx_exit(void); static void sys_directx_get_executable_name(char *output, int size); static void sys_directx_set_window_title(AL_CONST char *name); static int sys_directx_set_close_button_callback(void (*proc)(void)); static void sys_directx_message(AL_CONST char *msg); static void sys_directx_assert(AL_CONST char *msg); static void sys_directx_save_console_state(void); static void sys_directx_restore_console_state(void); static int sys_directx_desktop_color_depth(void); static int sys_directx_get_desktop_resolution(int *width, int *height); static void sys_directx_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); static void sys_directx_yield_timeslice(void); static int sys_directx_trace_handler(AL_CONST char *msg); /* the main system driver for running under DirectX */ SYSTEM_DRIVER system_directx = { SYSTEM_DIRECTX, empty_string, /* char *name; */ empty_string, /* char *desc; */ "DirectX", sys_directx_init, sys_directx_exit, sys_directx_get_executable_name, NULL, /* AL_METHOD(int, find_resource, (char *dest, char *resource, int size)); */ sys_directx_set_window_title, sys_directx_set_close_button_callback, sys_directx_message, sys_directx_assert, sys_directx_save_console_state, sys_directx_restore_console_state, NULL, /* AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); */ NULL, /* AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); */ NULL, /* AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); */ NULL, /* AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp)); */ NULL, /* AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(void, read_hardware_palette, (void)); */ NULL, /* AL_METHOD(void, set_palette_range, (PALETTE p, int from, int to, int vsync)); */ NULL, /* AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); */ sys_directx_set_display_switch_mode, NULL, /* AL_METHOD(void, display_switch_lock, (int lock)); */ sys_directx_desktop_color_depth, sys_directx_get_desktop_resolution, sys_directx_get_gfx_safe_mode, sys_directx_yield_timeslice, sys_directx_create_mutex, sys_directx_destroy_mutex, sys_directx_lock_mutex, sys_directx_unlock_mutex, NULL, /* AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); */ _get_win_digi_driver_list, /* AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); */ _get_win_midi_driver_list, /* AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); */ NULL /* AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); */ }; static char sys_directx_desc[64] = EMPTY_STRING; _DRIVER_INFO _system_driver_list[] = { {SYSTEM_DIRECTX, &system_directx, TRUE}, {SYSTEM_NONE, &system_none, FALSE}, {0, NULL, 0} }; /* general vars */ HINSTANCE allegro_inst = NULL; HANDLE allegro_thread = NULL; CRITICAL_SECTION allegro_critical_section; int _dx_ver; /* internals */ static RECT wnd_rect; /* sys_directx_init: * Top level system driver wakeup call. */ static int sys_directx_init(void) { char tmp[64]; unsigned long win_ver; HANDLE current_thread; HANDLE current_process; /* init thread */ _win_thread_init(); allegro_inst = GetModuleHandle(NULL); /* get allegro thread handle */ current_thread = GetCurrentThread(); current_process = GetCurrentProcess(); DuplicateHandle(current_process, current_thread, current_process, &allegro_thread, 0, FALSE, DUPLICATE_SAME_ACCESS); /* get versions */ win_ver = GetVersion(); os_version = win_ver & 0xFF; os_revision = (win_ver & 0xFF00) >> 8; os_multitasking = TRUE; if (win_ver < 0x80000000) { /* Since doesn't exist os_version == 7 or greater yet, these will be detected as Vista instead of NT. */ if (os_version >= 6) { /* If in the future a os_revision == 2 or greater comes, it will be detected as Windows 7 instead of Vista. */ if (os_revision >= 1) os_type = OSTYPE_WIN7; else os_type = OSTYPE_WINVISTA; } else if (os_version == 5) { /* If in the future a os_revision == 3 or greater comes, it will be detected as Win2003 instead of Win2000. */ if (os_revision >= 2) os_type = OSTYPE_WIN2003; else if (os_revision == 1) os_type = OSTYPE_WINXP; else os_type = OSTYPE_WIN2000; } else os_type = OSTYPE_WINNT; } else if (os_version == 4) { if (os_revision == 90) os_type = OSTYPE_WINME; else if (os_revision == 10) os_type = OSTYPE_WIN98; else os_type = OSTYPE_WIN95; } else os_type = OSTYPE_WIN3; _dx_ver = get_dx_ver(); uszprintf(sys_directx_desc, sizeof(sys_directx_desc), uconvert_ascii("DirectX %u.%x", tmp), _dx_ver >> 8, _dx_ver & 0xff); system_directx.desc = sys_directx_desc; /* setup general critical section */ InitializeCriticalSection(&allegro_critical_section); /* install a Windows specific trace handler */ if (!_al_trace_handler) register_trace_handler(sys_directx_trace_handler); /* setup the display switch system */ sys_directx_display_switch_init(); /* either use a user window or create a new window */ if (init_directx_window() != 0) goto Error; return 0; Error: sys_directx_exit(); return -1; } /* sys_directx_exit: * The end of the world... */ static void sys_directx_exit(void) { /* free allocated resources */ _free_win_digi_driver_list(); _free_win_midi_driver_list(); /* unhook or close window */ exit_directx_window(); /* shutdown display switch system */ sys_directx_display_switch_exit(); /* remove resources */ DeleteCriticalSection(&allegro_critical_section); /* shutdown thread */ _win_thread_exit(); allegro_inst = NULL; } /* sys_directx_get_executable_name: * Returns full path to the current executable. */ static void sys_directx_get_executable_name(char *output, int size) { char *temp = _AL_MALLOC_ATOMIC(size); if (GetModuleFileName(allegro_inst, temp, size)) do_uconvert(temp, U_ASCII, output, U_CURRENT, size); else usetc(output, 0); _AL_FREE(temp); } /* sys_directx_set_window_title: * Alters the application title. */ static void sys_directx_set_window_title(AL_CONST char *name) { HWND allegro_wnd = win_get_window(); do_uconvert(name, U_CURRENT, wnd_title, U_ASCII, WND_TITLE_SIZE); SetWindowText(allegro_wnd, wnd_title); } /* sys_directx_set_close_button_callback: * Sets the close button callback function. */ static int sys_directx_set_close_button_callback(void (*proc)(void)) { DWORD class_style; HMENU sys_menu; HWND allegro_wnd = win_get_window(); user_close_proc = proc; /* get the old class style */ class_style = GetClassLong(allegro_wnd, GCL_STYLE); /* and the system menu handle */ sys_menu = GetSystemMenu(allegro_wnd, FALSE); /* enable or disable the no_close_button flag and the close menu option */ if (proc) { class_style &= ~CS_NOCLOSE; EnableMenuItem(sys_menu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED); } else { class_style |= CS_NOCLOSE; EnableMenuItem(sys_menu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); } /* change the class to the new style */ SetClassLong(allegro_wnd, GCL_STYLE, class_style); /* Redraw the whole window to display the changes of the button. * (we use this because UpdateWindow() only works for the client area) */ RedrawWindow(allegro_wnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); return 0; } /* sys_directx_message: * Displays a message. */ static void sys_directx_message(AL_CONST char *msg) { char *tmp1 = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE); char tmp2[WND_TITLE_SIZE*2]; HWND allegro_wnd = win_get_window(); while ((ugetc(msg) == '\r') || (ugetc(msg) == '\n')) msg += uwidth(msg); MessageBoxW(allegro_wnd, (unsigned short *)uconvert(msg, U_CURRENT, tmp1, U_UNICODE, ALLEGRO_MESSAGE_SIZE), (unsigned short *)uconvert(wnd_title, U_ASCII, tmp2, U_UNICODE, sizeof(tmp2)), MB_OK); _AL_FREE(tmp1); } /* sys_directx_assert * Handles assertions. */ static void sys_directx_assert(AL_CONST char *msg) { OutputDebugString(msg); /* thread safe */ abort(); } /* sys_directx_save_console_state: * Saves console window size and position. */ static void sys_directx_save_console_state(void) { HWND allegro_wnd = win_get_window(); GetWindowRect(allegro_wnd, &wnd_rect); } /* sys_directx_restore_console_state: * Restores console window size and position. */ static void sys_directx_restore_console_state(void) { HWND allegro_wnd = win_get_window(); /* unacquire input devices */ wnd_schedule_proc(key_dinput_unacquire); wnd_schedule_proc(mouse_dinput_unacquire); wnd_schedule_proc(joystick_dinput_unacquire); /* reset switch mode */ _win_reset_switch_mode(); /* re-size and hide window */ SetWindowPos(allegro_wnd, HWND_TOP, wnd_rect.left, wnd_rect.top, wnd_rect.right - wnd_rect.left, wnd_rect.bottom - wnd_rect.top, SWP_NOCOPYBITS); ShowWindow(allegro_wnd, SW_SHOW); } /* sys_directx_desktop_color_depth: * Returns the current desktop color depth. */ static int sys_directx_desktop_color_depth(void) { /* The regular way of retrieving the desktop * color depth is broken under Windows 95: * * DEVMODE display_mode; * * display_mode.dmSize = sizeof(DEVMODE); * display_mode.dmDriverExtra = 0; * if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &display_mode) == 0) * return 0; * * return display_mode.dmBitsPerPel; */ HDC dc; int depth; dc = GetDC(NULL); depth = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(NULL, dc); return depth; } /* sys_directx_get_desktop_resolution: * Returns the current desktop resolution. */ static int sys_directx_get_desktop_resolution(int *width, int *height) { /* same thing for the desktop resolution: * * DEVMODE display_mode; * * display_mode.dmSize = sizeof(DEVMODE); * display_mode.dmDriverExtra = 0; * if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &display_mode) == 0) * return -1; * * *width = display_mode.dmPelsWidth; * *height = display_mode.dmPelsHeight; * * return 0; */ HDC dc; dc = GetDC(NULL); *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES); ReleaseDC(NULL, dc); return 0; } /* sys_directx_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void sys_directx_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_GDI; mode->width = 320; mode->height = 200; mode->bpp = 8; } /* sys_directx_yield_timeslice: * Yields remaining timeslice portion to the system. */ static void sys_directx_yield_timeslice(void) { Sleep(0); } /* sys_directx_trace_handler * Handles trace output. */ static int sys_directx_trace_handler(AL_CONST char *msg) { OutputDebugString(msg); /* thread safe */ return 0; } /* _WinMain: * Entry point for Windows GUI programs, hooked by a macro in alwin.h, * which makes it look as if the application can still have a normal * main() function. */ int _WinMain(void *_main, void *hInst, void *hPrev, char *Cmd, int nShow) { int (*mainfunc) (int argc, char *argv[]) = (int (*)(int, char *[]))_main; char *argbuf; char *cmdline; char **argv; int argc; int argc_max; int i, q; /* can't use parameter because it doesn't include the executable name */ cmdline = GetCommandLine(); i = (int)strlen(cmdline) + 1; argbuf = _AL_MALLOC(i); memcpy(argbuf, cmdline, i); argc = 0; argc_max = 64; argv = _AL_MALLOC(sizeof(char *) * argc_max); if (!argv) { _AL_FREE(argbuf); return 1; } i = 0; /* parse commandline into argc/argv format */ while (argbuf[i]) { while ((argbuf[i]) && (uisspace(argbuf[i]))) i++; if (argbuf[i]) { if ((argbuf[i] == '\'') || (argbuf[i] == '"')) { q = argbuf[i++]; if (!argbuf[i]) break; } else q = 0; argv[argc++] = &argbuf[i]; if (argc >= argc_max) { argc_max += 64; argv = _AL_REALLOC(argv, sizeof(char *) * argc_max); if (!argv) { _AL_FREE(argbuf); return 1; } } while ((argbuf[i]) && ((q) ? (argbuf[i] != q) : (!uisspace(argbuf[i])))) i++; if (argbuf[i]) { argbuf[i] = 0; i++; } } } argv[argc] = NULL; /* call the application entry point */ i = mainfunc(argc, argv); _AL_FREE(argv); _AL_FREE(argbuf); return i; } /* win_err_str: * Returns a error string for a window error. */ char *win_err_str(long err) { static char msg[256]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&msg, 0, NULL); return msg; } /* thread_safe_trace: * Outputs internal trace message. */ void thread_safe_trace(char *msg,...) { char buf[256]; va_list ap; /* todo, some day: use vsnprintf (C99) */ va_start(ap, msg); vsprintf(buf, msg, ap); va_end(ap); OutputDebugString(buf); /* thread safe */ } allegro-4.4.3.1/src/win/wjoyhelp.c0000664000175000017500000001754313437077643015703 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows joystick high-level helper functions. * * By Eric Botcazou. * * Based on code by Stefan Schimanski. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif static char name_x[] = "X"; static char name_y[] = "Y"; static char name_stick[] = "stick"; static char name_throttle[] = "throttle"; static char name_rudder[] = "rudder"; static char name_slider[] = "slider"; static char name_hat[] = "hat"; static char *name_b[MAX_JOYSTICK_BUTTONS] = { "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15", "B16", "B17", "B18", "B19", "B20", "B21", "B22", "B23", "B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31", "B32" }; #define JOY_POVFORWARD_WRAP 36000 /* win_update_joystick_status: * Updates the specified joystick info structure by translating * Windows joystick status into Allegro joystick status. */ int win_update_joystick_status(int n, WINDOWS_JOYSTICK_INFO *win_joy) { int n_stick, n_axis, n_but, max_stick, win_axis, p; if (n >= num_joysticks) return -1; /* sticks */ n_stick = 0; win_axis = 0; /* skip hat at this point, it will be handled later */ if (win_joy->caps & JOYCAPS_HASPOV) max_stick = joy[n].num_sticks - 1; else max_stick = joy[n].num_sticks; for (n_stick = 0; n_stick < max_stick; n_stick++) { for (n_axis = 0; n_axis < joy[n].stick[n_stick].num_axis; n_axis++) { p = win_joy->axis[win_axis]; /* set pos of analog stick */ if (joy[n].stick[n_stick].flags & JOYFLAG_ANALOGUE) { if (joy[n].stick[n_stick].flags & JOYFLAG_SIGNED) joy[n].stick[n_stick].axis[n_axis].pos = p - 128; else joy[n].stick[n_stick].axis[n_axis].pos = p; } /* set pos of digital stick */ if (joy[n].stick[n_stick].flags & JOYFLAG_DIGITAL) { if (p < 64) joy[n].stick[n_stick].axis[n_axis].d1 = TRUE; else joy[n].stick[n_stick].axis[n_axis].d1 = FALSE; if (p > 192) joy[n].stick[n_stick].axis[n_axis].d2 = TRUE; else joy[n].stick[n_stick].axis[n_axis].d2 = FALSE; } win_axis++; } } /* hat */ if (win_joy->caps & JOYCAPS_HASPOV) { /* emulate analog joystick */ joy[n].stick[n_stick].axis[0].pos = 0; joy[n].stick[n_stick].axis[1].pos = 0; /* left */ if ((win_joy->hat > JOY_POVBACKWARD) && (win_joy->hat < JOY_POVFORWARD_WRAP)) { joy[n].stick[n_stick].axis[0].d1 = TRUE; joy[n].stick[n_stick].axis[0].pos = -128; } else { joy[n].stick[n_stick].axis[0].d1 = FALSE; } /* right */ if ((win_joy->hat > JOY_POVFORWARD) && (win_joy->hat < JOY_POVBACKWARD)) { joy[n].stick[n_stick].axis[0].d2 = TRUE; joy[n].stick[n_stick].axis[0].pos = +128; } else { joy[n].stick[n_stick].axis[0].d2 = FALSE; } /* forward */ if (((win_joy->hat > JOY_POVLEFT) && (win_joy->hat <= JOY_POVFORWARD_WRAP)) || ((win_joy->hat >= JOY_POVFORWARD) && (win_joy->hat < JOY_POVRIGHT))) { joy[n].stick[n_stick].axis[1].d1 = TRUE; joy[n].stick[n_stick].axis[1].pos = -128; } else { joy[n].stick[n_stick].axis[1].d1 = FALSE; } /* backward */ if ((win_joy->hat > JOY_POVRIGHT) && (win_joy->hat < JOY_POVLEFT)) { joy[n].stick[n_stick].axis[1].d2 = TRUE; joy[n].stick[n_stick].axis[1].pos = +128; } else { joy[n].stick[n_stick].axis[1].d2 = FALSE; } } /* buttons */ for (n_but = 0; n_but < win_joy->num_buttons; n_but++) joy[n].button[n_but].b = win_joy->button[n_but]; return 0; } /* win_add_joystick: * Adds a new joystick (fills in a new joystick info structure). */ int win_add_joystick(WINDOWS_JOYSTICK_INFO *win_joy) { int n_stick, n_but, max_stick, win_axis; if (num_joysticks == MAX_JOYSTICKS-1) return -1; joy[num_joysticks].flags = JOYFLAG_ANALOGUE | JOYFLAG_DIGITAL; /* how many sticks ? */ n_stick = 0; if (win_joy->num_axes > 0) { win_axis = 0; /* main analogue stick */ if (win_joy->num_axes > 1) { joy[num_joysticks].stick[n_stick].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[num_joysticks].stick[n_stick].axis[0].name = (win_joy->axis_name[0] ? win_joy->axis_name[0] : name_x); joy[num_joysticks].stick[n_stick].axis[1].name = (win_joy->axis_name[1] ? win_joy->axis_name[1] : name_y); joy[num_joysticks].stick[n_stick].name = name_stick; /* Z-axis: throttle */ if (win_joy->caps & JOYCAPS_HASZ) { joy[num_joysticks].stick[n_stick].num_axis = 3; joy[num_joysticks].stick[n_stick].axis[2].name = (win_joy->axis_name[2] ? win_joy->axis_name[2] : name_throttle); win_axis += 3; } else { joy[num_joysticks].stick[n_stick].num_axis = 2; win_axis += 2; } n_stick++; } /* first 1-axis stick: rudder */ if (win_joy->caps & JOYCAPS_HASR) { joy[num_joysticks].stick[n_stick].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; joy[num_joysticks].stick[n_stick].num_axis = 1; joy[num_joysticks].stick[n_stick].axis[0].name = ""; joy[num_joysticks].stick[n_stick].name = (win_joy->axis_name[win_axis] ? win_joy->axis_name[win_axis] : name_rudder); win_axis++; n_stick++; } max_stick = (win_joy->caps & JOYCAPS_HASPOV ? MAX_JOYSTICK_STICKS-1 : MAX_JOYSTICK_STICKS); /* other 1-axis sticks: sliders */ while ((win_axis < win_joy->num_axes) && (n_stick < max_stick)) { joy[num_joysticks].stick[n_stick].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; joy[num_joysticks].stick[n_stick].num_axis = 1; joy[num_joysticks].stick[n_stick].axis[0].name = ""; joy[num_joysticks].stick[n_stick].name = (win_joy->axis_name[win_axis] ? win_joy->axis_name[win_axis] : name_slider); win_axis++; n_stick++; } /* hat */ if (win_joy->caps & JOYCAPS_HASPOV) { joy[num_joysticks].stick[n_stick].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[num_joysticks].stick[n_stick].num_axis = 2; joy[num_joysticks].stick[n_stick].axis[0].name = "left/right"; joy[num_joysticks].stick[n_stick].axis[1].name = "up/down"; joy[num_joysticks].stick[n_stick].name = (win_joy->hat_name ? win_joy->hat_name : name_hat); n_stick++; } } joy[num_joysticks].num_sticks = n_stick; /* how many buttons ? */ joy[num_joysticks].num_buttons = win_joy->num_buttons; /* fill in the button names */ for (n_but = 0; n_but < joy[num_joysticks].num_buttons; n_but++) joy[num_joysticks].button[n_but].name = (win_joy->button_name[n_but] ? win_joy->button_name[n_but] : name_b[n_but]); num_joysticks++; return 0; } /* win_remove_all_joysticks: * Removes all registered joysticks. */ void win_remove_all_joysticks(void) { num_joysticks = 0; } allegro-4.4.3.1/src/win/gdi.c0000664000175000017500000003744313437077643014606 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Functions for drawing to GDI without using DirectX. * * By Marian Dvorsky. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif static HPALETTE current_hpalette = NULL; /* set_gdi_color_format: * Sets right values for pixel color format to work with GDI. */ void set_gdi_color_format(void) { _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; } /* destroy_current_hpalette: * Destroys the current Windows PALETTE. */ static void destroy_current_hpalette(void) { if (current_hpalette) { DeleteObject(current_hpalette); current_hpalette = NULL; } _remove_exit_func(destroy_current_hpalette); } /* set_palette_to_hdc: * Selects and realizes an Allegro PALETTE to a Windows DC. */ void set_palette_to_hdc(HDC dc, PALETTE pal) { PALETTEENTRY palPalEntry[256]; int i; if (current_hpalette) { for (i = 0; i < 256; i++) { palPalEntry[i].peRed = _rgb_scale_6[pal[i].r]; palPalEntry[i].peGreen = _rgb_scale_6[pal[i].g]; palPalEntry[i].peBlue = _rgb_scale_6[pal[i].b]; palPalEntry[i].peFlags = 0; } SetPaletteEntries(current_hpalette, 0, 256, (LPPALETTEENTRY) & palPalEntry); } else { current_hpalette = convert_palette_to_hpalette(pal); _add_exit_func(destroy_current_hpalette, "destroy_current_hpalette"); } SelectPalette(dc, current_hpalette, FALSE); RealizePalette(dc); select_palette(pal); } /* convert_palette_to_hpalette: * Converts an Allegro PALETTE to a Windows PALETTE. */ HPALETTE convert_palette_to_hpalette(PALETTE pal) { HPALETTE hpal; LOGPALETTE *lp; int i; lp = (LOGPALETTE *) _AL_MALLOC(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256); if (!lp) return NULL; lp->palNumEntries = 256; lp->palVersion = 0x300; for (i = 0; i < 256; i++) { lp->palPalEntry[i].peRed = _rgb_scale_6[pal[i].r]; lp->palPalEntry[i].peGreen = _rgb_scale_6[pal[i].g]; lp->palPalEntry[i].peBlue = _rgb_scale_6[pal[i].b]; lp->palPalEntry[i].peFlags = 0; } hpal = CreatePalette(lp); _AL_FREE(lp); return hpal; } /* convert_hpalette_to_palette: * Converts a Windows PALETTE to an Allegro PALETTE. */ void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal) { PALETTEENTRY lp[256]; int i; GetPaletteEntries(hpal, 0, 256, (LPPALETTEENTRY) & lp); for (i = 0; i < 256; i++) { pal[i].r = lp[i].peRed >> 2; pal[i].g = lp[i].peGreen >> 2; pal[i].b = lp[i].peBlue >> 2; } } /* get_bitmap_info: * Returns a BITMAPINFO structure suited to an Allegro BITMAP. * You have to free the memory allocated by this function. */ static BITMAPINFO *get_bitmap_info(BITMAP *bitmap, PALETTE pal) { BITMAPINFO *bi; int bpp, i; bi = (BITMAPINFO *) _AL_MALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256); bpp = bitmap_color_depth(bitmap); if (bpp == 15) bpp = 16; ZeroMemory(&bi->bmiHeader, sizeof(BITMAPINFOHEADER)); bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi->bmiHeader.biBitCount = bpp; bi->bmiHeader.biPlanes = 1; bi->bmiHeader.biWidth = bitmap->w; bi->bmiHeader.biHeight = -bitmap->h; bi->bmiHeader.biClrUsed = 256; bi->bmiHeader.biCompression = BI_RGB; if (pal) { for (i = 0; i < 256; i++) { bi->bmiColors[i].rgbRed = _rgb_scale_6[pal[i].r]; bi->bmiColors[i].rgbGreen = _rgb_scale_6[pal[i].g]; bi->bmiColors[i].rgbBlue = _rgb_scale_6[pal[i].b]; bi->bmiColors[i].rgbReserved = 0; } } return bi; } /* get_dib_from_bitmap: * Creates a Windows device-independent bitmap (DIB) from an Allegro BITMAP. * You have to free the memory allocated by this function. */ static BYTE *get_dib_from_bitmap(BITMAP *bitmap) { int bpp; int x, y; int pitch; int col; BYTE *pixels; BYTE *src, *dst; bpp = bitmap_color_depth(bitmap); pitch = bitmap->w * BYTES_PER_PIXEL(bpp); pitch = (pitch + 3) & ~3; /* align on dword */ pixels = (BYTE *) _AL_MALLOC_ATOMIC(bitmap->h * pitch); if (!pixels) return NULL; switch (bpp) { case 8: for (y = 0; y < bitmap->h; y++) { memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w); } break; case 15: if ((_rgb_r_shift_15 == 10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == 0)) { for (y = 0; y < bitmap->h; y++) memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 2); } else { for (y = 0; y < bitmap->h; y++) { src = bitmap->line[y]; dst = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { col = *(WORD *) (src); *((WORD *) (dst)) = (WORD) ((getb15(col) >> 3) | ((getg15(col) >> 3) << 5) | ((getr15(col) >> 3) << 10)); src += 2; dst += 2; } } } break; case 16: /* the format of a 16-bit DIB is 5-5-5 as above */ for (y = 0; y < bitmap->h; y++) { src = bitmap->line[y]; dst = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { col = *(WORD *) (src); *((WORD *) (dst)) = (WORD) ((getb16(col) >> 3) | ((getg16(col) >> 3) << 5) | ((getr16(col) >> 3) << 10)); src += 2; dst += 2; } } break; case 24: if ((_rgb_r_shift_24 == 16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == 0)) { for (y = 0; y < bitmap->h; y++) memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 3); } else { for (y = 0; y < bitmap->h; y++) { src = bitmap->line[y]; dst = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { col = *(DWORD *) (src); src += 3; *(dst++) = getb24(col); *(dst++) = getg24(col); *(dst++) = getr24(col); } } } break; case 32: if ((_rgb_r_shift_32 == 16) && (_rgb_g_shift_32 == 8) && (_rgb_b_shift_32 == 0)) { for (y = 0; y < bitmap->h; y++) memcpy(pixels + y * pitch, bitmap->line[y], bitmap->w * 4); } else { for (y = 0; y < bitmap->h; y++) { src = bitmap->line[y]; dst = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { col = *(DWORD *) (src); src += 4; *(dst++) = getb32(col); *(dst++) = getg32(col); *(dst++) = getr32(col); dst++; } } } break; } return pixels; } /* get_dib_from_hbitmap: * Creates a Windows device-independent bitmap (DIB) from a Windows BITMAP. * You have to free the memory allocated by this function. */ static BYTE *get_dib_from_hbitmap(int bpp, HBITMAP hbitmap) { BITMAPINFOHEADER bi; BITMAPINFO *binfo; HDC hdc; HPALETTE hpal, holdpal; int col; WINDOWS_BITMAP bm; int pitch; BYTE *pixels; BYTE *ptr; int x, y; if (!hbitmap) return NULL; if (bpp == 15) bpp = 16; if (!GetObject(hbitmap, sizeof(bm), (LPSTR) & bm)) return NULL; pitch = bm.bmWidth * BYTES_PER_PIXEL(bpp); pitch = (pitch + 3) & ~3; /* align on dword */ pixels = (BYTE *) _AL_MALLOC_ATOMIC(bm.bmHeight * pitch); if (!pixels) return NULL; ZeroMemory(&bi, sizeof(BITMAPINFOHEADER)); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biBitCount = bpp; bi.biPlanes = 1; bi.biWidth = bm.bmWidth; bi.biHeight = -abs(bm.bmHeight); bi.biClrUsed = 256; bi.biCompression = BI_RGB; binfo = _AL_MALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256); binfo->bmiHeader = bi; hdc = GetDC(NULL); hpal = convert_palette_to_hpalette(_current_palette); holdpal = SelectPalette(hdc, hpal, TRUE); RealizePalette(hdc); GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pixels, binfo, DIB_RGB_COLORS); ptr = pixels; /* This never occurs, because if screen or memory bitmap is 8-bit, * we ask Windows to convert it to truecolor. It is safer, but a little * bit slower. */ if (bpp == 8) { for (y = 0; y < bm.bmWidth; y++) { for (x = 0; x < bm.bmHeight; x++) { col = *ptr; if ((col < 10) || (col >= 246)) { /* we have to remap colors from system palette */ *(ptr++) = makecol8(binfo->bmiColors[col].rgbRed, binfo->bmiColors[col].rgbGreen, binfo->bmiColors[col].rgbBlue); } else { /* our palette is shifted by 10 */ *(ptr++) = col - 10; } } } } _AL_FREE(binfo); SelectPalette(hdc, holdpal, TRUE); DeleteObject(hpal); ReleaseDC(NULL, hdc); return pixels; } /* get_bitmap_from_dib: * Creates an Allegro BITMAP from a Windows device-independent bitmap (DIB). */ static BITMAP *get_bitmap_from_dib(int bpp, int w, int h, BYTE *pixels) { int x, y; int pitch; int col; int b, g, r; BYTE *src, *dst; BITMAP *bitmap; bitmap = create_bitmap_ex(bpp, w, h); pitch = bitmap->w * BYTES_PER_PIXEL(bpp); pitch = (pitch + 3) & ~3; /* align on dword */ switch (bpp) { case 8: for (y = 0; y < bitmap->h; y++) { memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w); } break; case 15: if ((_rgb_r_shift_15 == 10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == 0)) { for (y = 0; y < bitmap->h; y++) memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 2); } else { for (y = 0; y < bitmap->h; y++) { dst = bitmap->line[y]; src = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { col = *(WORD *) (src); *((WORD *) (dst)) = makecol15(_rgb_scale_5[(col >> 10) & 0x1F], _rgb_scale_5[(col >> 5) & 0x1F], _rgb_scale_5[col & 0x1F]); src += 2; dst += 2; } } } break; case 16: /* the format of a 16-bit DIB is 5-5-5 as above */ for (y = 0; y < bitmap->h; y++) { dst = bitmap->line[y]; src = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { col = *(WORD *) (src); *((WORD *) (dst)) = makecol16(_rgb_scale_5[(col >> 10) & 0x1F], _rgb_scale_5[(col >> 5) & 0x1F], _rgb_scale_5[col & 0x1F]); src += 2; dst += 2; } } break; case 24: if ((_rgb_r_shift_24 == 16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == 0)) { for (y = 0; y < bitmap->h; y++) memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 3); } else { for (y = 0; y < bitmap->h; y++) { dst = bitmap->line[y]; src = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { r = *(src++); g = *(src++); b = *(src++); col = makecol24(r, g, b); *((WORD *) dst) = (col & 0xFFFF); dst += 2; *(dst++) = (col >> 16); } } } break; case 32: if ((_rgb_r_shift_32 == 16) && (_rgb_g_shift_32 == 8) && (_rgb_b_shift_32 == 0)) { for (y = 0; y < bitmap->h; y++) memcpy(bitmap->line[y], pixels + y * pitch, bitmap->w * 4); } else { for (y = 0; y < bitmap->h; y++) { dst = bitmap->line[y]; src = pixels + y * pitch; for (x = 0; x < bitmap->w; x++) { b = *(src++); g = *(src++); r = *(src++); col = makecol32(r, g, b); src++; *((DWORD *) dst) = col; dst += 4; } } } break; } return bitmap; } /* convert_bitmap_to_hbitmap: * Converts an Allegro BITMAP to a Windows BITMAP. */ HBITMAP convert_bitmap_to_hbitmap(BITMAP *bitmap) { HDC hdc; HBITMAP hbmp; BITMAPINFO *bi; HPALETTE hpal, holdpal; BYTE *pixels; /* get the DIB first */ bi = get_bitmap_info(bitmap, NULL); pixels = get_dib_from_bitmap(bitmap); hpal = convert_palette_to_hpalette(_current_palette); /* now that we have the DIB, convert it to a DDB */ hdc = GetDC(NULL); holdpal = SelectPalette(hdc, hpal, TRUE); RealizePalette(hdc); hbmp = CreateDIBitmap(hdc, &bi->bmiHeader, CBM_INIT, pixels, bi, DIB_RGB_COLORS); ReleaseDC(NULL, hdc); SelectPalette(hdc, holdpal, TRUE); DeleteObject(hpal); _AL_FREE(pixels); _AL_FREE(bi); return hbmp; } /* convert_hbitmap_to_bitmap: * Converts a Windows BITMAP to an Allegro BITMAP. */ BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap) { BYTE *pixels; BITMAP *bmp; WINDOWS_BITMAP bm; int bpp; if (!GetObject(bitmap, sizeof(bm), (LPSTR) & bm)) return NULL; if (bm.bmBitsPixel == 8) { /* ask windows to save truecolor image, then convert to our format */ bpp = 24; } else bpp = bm.bmBitsPixel; /* get the DIB first */ pixels = get_dib_from_hbitmap(bpp, bitmap); /* now that we have the DIB, convert it to a BITMAP */ bmp = get_bitmap_from_dib(bpp, bm.bmWidth, bm.bmHeight, pixels); _AL_FREE(pixels); return bmp; } /* draw_to_hdc: * Draws an entire Allegro BITMAP to a Windows DC. Has a syntax similar to draw_sprite(). */ void draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y) { stretch_blit_to_hdc(bitmap, dc, 0, 0, bitmap->w, bitmap->h, x, y, bitmap->w, bitmap->h); } /* blit_to_hdc: * Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to blit(). */ void blit_to_hdc(BITMAP *bitmap, HDC dc, int src_x, int src_y, int dest_x, int dest_y, int w, int h) { stretch_blit_to_hdc(bitmap, dc, src_x, src_y, w, h, dest_x, dest_y, w, h); } /* stretch_blit_to_hdc: * Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to stretch_blit(). */ void stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h) { AL_CONST int bottom_up_src_y = bitmap->h - src_y - src_h; BYTE *pixels; BITMAPINFO *bi; bi = get_bitmap_info(bitmap, _current_palette); pixels = get_dib_from_bitmap(bitmap); /* Windows treats all source bitmaps as bottom-up when using StretchDIBits * unless the source (x,y) is (0,0). To work around this buggy behavior, we * can use negative heights to reverse the direction of the blits. * * See for a detailed explanation. */ if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap->h) { StretchDIBits(dc, dest_x, dest_h+dest_y-1, dest_w, -dest_h, src_x, bitmap->h-src_y+1, src_w, -src_h, pixels, bi, DIB_RGB_COLORS, SRCCOPY); } else { StretchDIBits(dc, dest_x, dest_y, dest_w, dest_h, src_x, bottom_up_src_y, src_w, src_h, pixels, bi, DIB_RGB_COLORS, SRCCOPY); } _AL_FREE(pixels); _AL_FREE(bi); } /* blit_from_hdc: * Blits from a Windows DC to an Allegro BITMAP. Has a syntax similar to blit(). */ void blit_from_hdc(HDC dc, BITMAP *bitmap, int src_x, int src_y, int dest_x, int dest_y, int w, int h) { stretch_blit_from_hdc(dc, bitmap, src_x, src_y, w, h, dest_x, dest_y, w, h); } /* stretch_blit_from_hdc: * Blits from a Windows DC to an Allegro BITMAP. Has a syntax similar to stretch_blit(). */ void stretch_blit_from_hdc(HDC dc, BITMAP *bitmap, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h) { HBITMAP hbmp, holdbmp; HDC hmemdc; BITMAP *newbmp; hmemdc = CreateCompatibleDC(dc); hbmp = CreateCompatibleBitmap(dc, dest_w, dest_h); holdbmp = SelectObject(hmemdc, hbmp); StretchBlt(hmemdc, 0, 0, dest_w, dest_h, dc, src_x, src_y, src_w, src_h, SRCCOPY); SelectObject(hmemdc, holdbmp); newbmp = convert_hbitmap_to_bitmap(hbmp); blit(newbmp, bitmap, 0, 0, dest_x, dest_y, dest_w, dest_h); destroy_bitmap(newbmp); DeleteObject(hbmp); DeleteDC(hmemdc); } allegro-4.4.3.1/src/win/wthread.c0000664000175000017500000000644313437077643015475 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Thread management. * * By Stefan Schimanski. * * Synchronization functions added by Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif /* COINIT_MULTITHREADED is not defined in objbase.h for MSVC */ #define _COINIT_MULTITHREADED 0 typedef HRESULT(CALLBACK * _CoInitializeEx_ptr) (LPVOID, DWORD); static _CoInitializeEx_ptr _CoInitializeEx = NULL; static int first_call = 1; /* _win_thread_init: * Initializes COM interface for the calling thread. * Attempts to use Distributed COM if available (installed by default * on every 32-bit Windows starting with Win98 and Win NT4). */ void _win_thread_init(void) { HMODULE ole32 = NULL; HWND allegro_wnd = win_get_window(); if (first_call) { first_call = 0; ole32 = GetModuleHandle("OLE32.DLL"); if (ole32 != NULL) { _CoInitializeEx = (_CoInitializeEx_ptr) GetProcAddress( ole32, "CoInitializeEx"); } else { MessageBox(allegro_wnd, "OLE32.DLL can't be loaded.", "Warning", MB_ICONWARNING + MB_OK); } if (_CoInitializeEx == NULL) { MessageBox(allegro_wnd, "Microsoft Distributed COM is not installed on this system. If you have problems " "with this application, please install the DCOM update. You can find it on the " "Microsoft homepage.", "DCOM not found", MB_ICONWARNING + MB_OK); } } if (_CoInitializeEx != NULL) _CoInitializeEx(NULL, _COINIT_MULTITHREADED); else CoInitialize(NULL); } /* _win_thread_exit: * Shuts down COM interface for the calling thread. */ void _win_thread_exit(void) { CoUninitialize(); } /* sys_directx_create_mutex: * Creates a mutex and returns a pointer to it. * Uses Critical Sections because Allegro mutexes are * inner-process synchronization objects only. */ void *sys_directx_create_mutex(void) { CRITICAL_SECTION *cs; cs = _AL_MALLOC(sizeof(CRITICAL_SECTION)); if (!cs) { *allegro_errno = ENOMEM; return NULL; } InitializeCriticalSection(cs); return (void *)cs; } /* sys_directx_destroy_mutex: * Destroys a mutex. */ void sys_directx_destroy_mutex(void *handle) { CRITICAL_SECTION *cs = (CRITICAL_SECTION *)handle; DeleteCriticalSection(cs); _AL_FREE(cs); } /* sys_directx_lock_mutex: * Locks a mutex. */ void sys_directx_lock_mutex(void *handle) { CRITICAL_SECTION *cs = (CRITICAL_SECTION *)handle; EnterCriticalSection(cs); } /* sys_directx_unlock_mutex: * Unlocks a mutex. */ void sys_directx_unlock_mutex(void *handle) { CRITICAL_SECTION *cs = (CRITICAL_SECTION *)handle; LeaveCriticalSection(cs); } allegro-4.4.3.1/src/win/wddovl.c0000664000175000017500000003210313437077643015326 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw overlay gfx driver. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddovl INFO: " #define PREFIX_W "al-wddovl WARNING: " #define PREFIX_E "al-wddovl ERROR: " static int gfx_directx_show_video_bitmap_ovl(struct BITMAP *bitmap); static int gfx_directx_request_video_bitmap_ovl(struct BITMAP *bitmap); static struct BITMAP *init_directx_ovl(int w, int h, int v_w, int v_h, int color_depth); static void gfx_directx_ovl_exit(struct BITMAP *b); GFX_DRIVER gfx_directx_ovl = { GFX_DIRECTX_OVL, empty_string, empty_string, "DirectDraw overlay", init_directx_ovl, gfx_directx_ovl_exit, NULL, // AL_METHOD(int, scroll, (int x, int y)); gfx_directx_sync, gfx_directx_set_palette, NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // gfx_directx_poll_scroll, NULL, // AL_METHOD(void, enable_triple_buffer, (void)); gfx_directx_create_video_bitmap, gfx_directx_destroy_video_bitmap, gfx_directx_show_video_bitmap_ovl, gfx_directx_request_video_bitmap_ovl, gfx_directx_create_system_bitmap, gfx_directx_destroy_system_bitmap, NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_video_state, (void*)); NULL, // AL_METHOD(void, restore_video_state, (void*)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, // AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; /* physical (not virtual!) screen size */ TRUE, // int linear; /* true if video memory is linear */ 0, // long bank_size; /* bank size, in bytes */ 0, // long bank_gran; /* bank granularity, in bytes */ 0, // long vid_mem; /* video memory size, in bytes */ 0, // long vid_phys_base; /* physical address of video memory */ TRUE // int windowed; /* true if driver runs windowed */ }; static void switch_in_overlay(void); static void show_overlay(void); static void move_overlay(int, int, int, int); static void hide_overlay(void); static void paint_overlay(RECT *); static WIN_GFX_DRIVER win_gfx_driver_overlay = { TRUE, switch_in_overlay, NULL, // AL_METHOD(void, switch_out, (void)); NULL, // AL_METHOD(void, enter_sysmode, (void)); NULL, // AL_METHOD(void, exit_sysmode, (void)); move_overlay, hide_overlay, paint_overlay }; static char gfx_driver_desc[256] = EMPTY_STRING; static DDRAW_SURFACE *overlay_surface = NULL; static BOOL overlay_visible = FALSE; static HBRUSH overlay_brush; /* switch_in_overlay: * Handles window switched in. */ static void switch_in_overlay(void) { restore_all_ddraw_surfaces(); show_overlay(); } /* update_overlay: * Moves and resizes the overlay surface to make it fit * into the specified area. */ static int update_overlay(int x, int y, int w, int h) { HRESULT hr; RECT dest_rect; dest_rect.left = x; dest_rect.top = y; dest_rect.right = x + w; dest_rect.bottom = y + h; /* show the overlay surface */ hr = IDirectDrawSurface2_UpdateOverlay(overlay_surface->id, NULL, gfx_directx_primary_surface->id, &dest_rect, DDOVER_SHOW | DDOVER_KEYDEST, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't display overlay (%x)\n", hr); IDirectDrawSurface2_UpdateOverlay(overlay_surface->id, NULL, gfx_directx_primary_surface->id, NULL, DDOVER_HIDE, NULL); return -1; } return 0; } /* show_overlay: * Makes the overlay surface visible on the primary surface. */ static void show_overlay(void) { if (overlay_surface) { overlay_visible = TRUE; update_overlay(wnd_x, wnd_y, wnd_width, wnd_height); } } /* move_overlay: * Moves the overlay surface. */ static void move_overlay(int x, int y, int w, int h) { RECT window_rect; HWND allegro_wnd = win_get_window(); int xmod; /* handle hardware limitations */ if ((ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && (xmod = x%ddcaps.dwAlignBoundaryDest)) { GetWindowRect(allegro_wnd, &window_rect); SetWindowPos(allegro_wnd, 0, window_rect.left + xmod, window_rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } else if (overlay_visible) update_overlay(x, y, w, h); } /* hide_overlay: * Makes the overlay surface invisible on the primary surface. */ static void hide_overlay(void) { if (overlay_visible) { overlay_visible = FALSE; IDirectDrawSurface2_UpdateOverlay(overlay_surface->id, NULL, gfx_directx_primary_surface->id, NULL, DDOVER_HIDE, NULL); } } /* paint_overlay: * Handles window paint events. */ static void paint_overlay(RECT *rect) { /* We may have lost the DirectDraw surfaces, for example * after the monitor has gone to low power. */ if (IDirectDrawSurface2_IsLost(gfx_directx_primary_surface->id)) switch_in_overlay(); } /* wnd_set_windowed_coop: * Sets the DirectDraw cooperative level to normal. */ static int wnd_set_windowed_coop(void) { HRESULT hr; HWND allegro_wnd = win_get_window(); hr = IDirectDraw2_SetCooperativeLevel(directdraw, allegro_wnd, DDSCL_NORMAL); if (FAILED(hr)) { _TRACE(PREFIX_E "SetCooperative level = %s (%x), hwnd = %x\n", win_err_str(hr), hr, allegro_wnd); return -1; } return 0; } /* gfx_directx_setup_driver_desc: * Sets up the driver description string. */ static void gfx_directx_setup_driver_desc(void) { char tmp[256]; uszprintf(gfx_driver_desc, sizeof(gfx_driver_desc), uconvert_ascii("DirectDraw, in matching, %d bpp overlay", tmp), _win_desktop_depth); gfx_directx_ovl.desc = gfx_driver_desc; } /* gfx_directx_show_video_bitmap_ovl: */ static int gfx_directx_show_video_bitmap_ovl(struct BITMAP *bitmap) { if (gfx_directx_show_video_bitmap(bitmap) != 0) { return -1; } else { if (overlay_visible) update_overlay(wnd_x, wnd_y, wnd_width, wnd_height); return 0; } } /* gfx_directx_request_video_bitmap_ovl: */ static int gfx_directx_request_video_bitmap_ovl(struct BITMAP *bitmap) { if (gfx_directx_request_video_bitmap(bitmap) != 0) { return -1; } else { if (overlay_visible) update_overlay(wnd_x, wnd_y, wnd_width, wnd_height); return 0; } } /* create_overlay: * Creates the overlay surface. */ static int create_overlay(int w, int h, int color_depth) { overlay_surface = gfx_directx_create_surface(w, h, ddpixel_format, DDRAW_SURFACE_OVERLAY); if (!overlay_surface) { _TRACE(PREFIX_E "Can't create overlay surface.\n"); return -1; } return 0; } /* init_directx_ovl: * Initializes the driver. */ static struct BITMAP *init_directx_ovl(int w, int h, int v_w, int v_h, int color_depth) { HRESULT hr; DDCOLORKEY key; HWND allegro_wnd = win_get_window(); /* overlay would allow scrolling on some cards, but it isn't implemented yet */ if ((v_w != w && v_w != 0) || (v_h != h && v_h != 0)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } _enter_critical(); /* init DirectX */ if (init_directx() != 0) goto Error; if ((ddcaps.dwCaps & DDCAPS_OVERLAY) == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Overlays not supported")); goto Error; } if (gfx_directx_compare_color_depth(color_depth) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); goto Error; } if (wnd_call_proc(wnd_set_windowed_coop) != 0) goto Error; if (finalize_directx_init() != 0) goto Error; /* Paint window background with overlay color key. */ overlay_brush = CreateSolidBrush(MASK_COLOR_32); SetClassLongPtr(allegro_wnd, GCLP_HBRBACKGROUND, (LONG_PTR)overlay_brush); if (adjust_window(w, h) != 0) { _TRACE(PREFIX_E "window size not supported.\n"); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto Error; } /* create surfaces */ if (gfx_directx_create_primary() != 0) goto Error; if (create_overlay(w, h, color_depth) != 0) goto Error; /* Handle hardware limitations: according to the DirectX SDK, "these restrictions * can vary depending on the pixel formats of the overlay and primary surface", so * we handle them after creating the surfaces. */ ddcaps.dwSize = sizeof(ddcaps); hr = IDirectDraw2_GetCaps(directdraw, &ddcaps, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get driver caps\n"); goto Error; } if (ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC) { if (w%ddcaps.dwAlignSizeSrc) { _TRACE(PREFIX_E "Alignment requirement not met: source size %d\n", ddcaps.dwAlignSizeSrc); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto Error; } } else if (ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST) { if (w%ddcaps.dwAlignSizeDest) { _TRACE(PREFIX_E "Alignment requirement not met: dest size %d\n", ddcaps.dwAlignSizeDest); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto Error; } } /* set color format */ if (color_depth == 8) { if (gfx_directx_create_palette(overlay_surface) != 0) goto Error; } else { if (gfx_directx_update_color_format(overlay_surface, color_depth) != 0) goto Error; } /* set up Allegro gfx driver */ gfx_directx_setup_driver_desc(); if (gfx_directx_setup_driver(&gfx_directx_ovl, w, h, color_depth) != 0) goto Error; gfx_directx_forefront_bitmap = gfx_directx_make_bitmap_from_surface(overlay_surface, w, h, BMP_ID_VIDEO); if (!gfx_directx_forefront_bitmap) { _TRACE(PREFIX_E "Can't make a bitmap from the surface\n"); goto Error; } /* set the overlay color key */ key.dwColorSpaceLowValue = gfx_directx_forefront_bitmap->vtable->mask_color; key.dwColorSpaceHighValue = gfx_directx_forefront_bitmap->vtable->mask_color; hr = IDirectDrawSurface2_SetColorKey(gfx_directx_primary_surface->id, DDCKEY_DESTOVERLAY, &key); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't set overlay dest color key\n"); goto Error; } /* display the overlay surface */ show_overlay(); /* use hardware accelerated primitives */ gfx_directx_enable_acceleration(&gfx_directx_ovl); /* use triple buffering */ gfx_directx_enable_triple_buffering(&gfx_directx_ovl); /* connect to the system driver */ win_gfx_driver = &win_gfx_driver_overlay; /* set default switching policy */ set_display_switch_mode(SWITCH_PAUSE); /* grab input devices */ win_grab_input(); _exit_critical(); return gfx_directx_forefront_bitmap; Error: _exit_critical(); /* release the DirectDraw object */ gfx_directx_ovl_exit(NULL); return NULL; } /* gfx_directx_ovl_exit: * Shuts down the driver. */ static void gfx_directx_ovl_exit(struct BITMAP *bmp) { HWND allegro_wnd = win_get_window(); _enter_gfx_critical(); if (bmp) { save_window_pos(); clear_bitmap(bmp); } /* disconnect from the system driver */ win_gfx_driver = NULL; /* destroy the overlay surface */ if (overlay_surface) { hide_overlay(); SetClassLongPtr(allegro_wnd, GCLP_HBRBACKGROUND, (LONG_PTR)NULL); DeleteObject(overlay_brush); gfx_directx_destroy_surface(overlay_surface); overlay_surface = NULL; gfx_directx_forefront_bitmap = NULL; } gfx_directx_exit(NULL); _exit_gfx_critical(); } allegro-4.4.3.1/src/win/wddlock.c0000664000175000017500000002263113437077643015463 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw bitmap locking. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddlock INFO: " #define PREFIX_W "al-wddlock WARNING: " #define PREFIX_E "al-wddlock ERROR: " /* If custom (asm) calling conversions are used, then the code in asmlock.s is * used instead. */ #if defined(ALLEGRO_NO_ASM) static void update_dirty_lines(BITMAP *bmp) { RECT rect; int i; /* The width is always the full bitmap width, because we have no * mechanism for measuring the X range of the update. */ rect.left = 0; rect.right = bmp->w; for (i = 0; i < bmp->h; i++) { if (_al_wd_dirty_lines[i]) { int j = i+1; rect.top = i; /* consecutive dirty lines are combined into ranges of Y values */ while (_al_wd_dirty_lines[j]) j++; rect.bottom = j; _al_wd_update_window(&rect); i = j+1; } } } uintptr_t gfx_directx_write_bank(BITMAP *bmp, int line) { if (!(bmp->id & BMP_ID_LOCKED)) gfx_directx_autolock(bmp); return (uintptr_t) bmp->line[line]; } void gfx_directx_unwrite_bank(BITMAP *bmp) { if (!(bmp->id & BMP_ID_AUTOLOCK)) return; gfx_directx_unlock(bmp); bmp->id &= ~ BMP_ID_AUTOLOCK; } uintptr_t gfx_directx_write_bank_win(BITMAP *bmp, int line) { _al_wd_dirty_lines[bmp->y_ofs+line] = 1; if (!(bmp->id & BMP_ID_LOCKED)) gfx_directx_autolock(bmp); return (uintptr_t) bmp->line[line]; } void gfx_directx_unwrite_bank_win(BITMAP *bmp) { if (!(bmp->id & BMP_ID_AUTOLOCK)) return; gfx_directx_unlock(bmp); bmp->id &= ~BMP_ID_AUTOLOCK; /* Update dirty lines: this is safe because autolocking is guaranteed to * be the only level of locking. (Or at least, that's what it says in * asmlock.s) */ update_dirty_lines(gfx_directx_forefront_bitmap); } void gfx_directx_unlock_win(BITMAP *bmp) { gfx_directx_unlock(bmp); /* forefront_bitmap may still be locked in case of nested locking */ if (!(gfx_directx_forefront_bitmap->id & BMP_ID_LOCKED)) update_dirty_lines(gfx_directx_forefront_bitmap); } #else /* !defined(ALLEGRO_NO_ASM) */ /* asmlock.s requires these two variables */ void (*ptr_gfx_directx_autolock) (BITMAP* bmp) = gfx_directx_autolock; void (*ptr_gfx_directx_unlock) (BITMAP* bmp) = gfx_directx_unlock; #endif /* !defined(ALLEGRO_NO_ASM) */ /* gfx_directx_switch_out: * Arranges for drawing requests to pause when we are in the background. */ static void gfx_directx_switch_out(void) { _exit_gfx_critical(); if (GFX_CRITICAL_RELEASED) _win_thread_switch_out(); _enter_gfx_critical(); } /* gfx_directx_lock: * Locks the surface and prepares the lines array of the bitmap. */ void gfx_directx_lock(BITMAP *bmp) { DDRAW_SURFACE *surf; BITMAP *parent; HRESULT hr; DDSURFACEDESC ddsurf_desc; int pitch; unsigned char *data; int y; if (bmp->id & BMP_ID_SUB) { /* if it's a sub-bitmap, start by locking our parent */ parent = (BITMAP *)bmp->extra; gfx_directx_lock(parent); bmp->id |= BMP_ID_LOCKED; /* update the line array if our parent has moved */ pitch = (long)parent->line[1] - (long)parent->line[0]; data = parent->line[0] + (bmp->y_ofs - parent->y_ofs) * pitch + (bmp->x_ofs - parent->x_ofs) * BYTES_PER_PIXEL(bitmap_color_depth(bmp)); if (data != bmp->line[0]) { for (y = 0; y < bmp->h; y++) { bmp->line[y] = data; data += pitch; } } } else { /* require exclusive ownership of the bitmap */ _enter_gfx_critical(); /* handle display switch */ if (!_win_app_foreground) gfx_directx_switch_out(); /* this is a real bitmap, so can be locked directly */ surf = DDRAW_SURFACE_OF(bmp); surf->lock_nesting++; if (!(bmp->id & BMP_ID_LOCKED)) { /* try to lock surface */ bmp->id |= BMP_ID_LOCKED; surf->flags &= ~DDRAW_SURFACE_LOST; ddsurf_desc.dwSize = sizeof(DDSURFACEDESC); ddsurf_desc.dwFlags = 0; hr = IDirectDrawSurface2_Lock(surf->id, NULL, &ddsurf_desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to lock the surface. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) { ddsurf_desc.dwSize = sizeof(DDSURFACEDESC); ddsurf_desc.dwFlags = 0; hr = IDirectDrawSurface2_Lock(surf->id, NULL, &ddsurf_desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); } } if (FAILED(hr)) { _TRACE(PREFIX_E "Can't lock surface (%x)\n", hr); /* lock failed, use pseudo surface memory */ surf->flags |= DDRAW_SURFACE_LOST; data = pseudo_surf_mem; pitch = 0; } else { data = ddsurf_desc.lpSurface; pitch = ddsurf_desc.lPitch; } /* prepare line array */ if (data != bmp->line[0]) { for (y = 0; y < bmp->h; y++) { bmp->line[y] = data; data += pitch; } } } } } /* gfx_directx_autolock: * Locks the surface and prepares the lines array of the bitmap. * This version is used directly by the bank switch functions, ie. * it handles the autolocking mode, rather than being called directly. */ void gfx_directx_autolock(BITMAP *bmp) { DDRAW_SURFACE *surf; BITMAP *parent; int pitch; unsigned char *data; int y; if (bmp->id & BMP_ID_SUB) { /* if it's a sub-bitmap, start by locking our parent */ parent = (BITMAP *)bmp->extra; gfx_directx_autolock(parent); bmp->id |= BMP_ID_LOCKED; if (parent->id & BMP_ID_AUTOLOCK) { bmp->id |= BMP_ID_AUTOLOCK; parent->id &= ~BMP_ID_AUTOLOCK; } /* update the line array if our parent has moved */ pitch = (long)parent->line[1] - (long)parent->line[0]; data = parent->line[0] + (bmp->y_ofs - parent->y_ofs) * pitch + (bmp->x_ofs - parent->x_ofs) * BYTES_PER_PIXEL(bitmap_color_depth(bmp)); if (data != bmp->line[0]) { for (y = 0; y < bmp->h; y++) { bmp->line[y] = data; data += pitch; } } } else { /* this is a real bitmap, so can be locked directly */ surf = DDRAW_SURFACE_OF(bmp); if (surf->lock_nesting) { /* re-locking after a hwaccel, so don't change nesting state */ gfx_directx_lock(bmp); surf->lock_nesting--; _exit_gfx_critical(); } else { /* locking for the first time */ gfx_directx_lock(bmp); bmp->id |= BMP_ID_AUTOLOCK; } } } /* gfx_directx_unlock: * Unlocks the surface. */ void gfx_directx_unlock(BITMAP *bmp) { DDRAW_SURFACE *surf; BITMAP *parent; HRESULT hr; if (bmp->id & BMP_ID_SUB) { /* recurse when unlocking sub-bitmaps */ parent = (BITMAP *)bmp->extra; gfx_directx_unlock(parent); if (!(parent->id & BMP_ID_LOCKED)) bmp->id &= ~BMP_ID_LOCKED; } else { /* regular bitmaps can be unlocked directly */ surf = DDRAW_SURFACE_OF(bmp); if (surf->lock_nesting > 0) { surf->lock_nesting--; if ((!surf->lock_nesting) && (bmp->id & BMP_ID_LOCKED)) { if (!(surf->flags & DDRAW_SURFACE_LOST)) { /* only unlock if it doesn't use pseudo video memory */ hr = IDirectDrawSurface2_Unlock(surf->id, NULL); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to unlock the surface. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_Unlock(surf->id, NULL); } if (FAILED(hr)) _TRACE(PREFIX_E "Can't unlock surface (%x)\n", hr); } bmp->id &= ~BMP_ID_LOCKED; } /* release bitmap for other threads */ _exit_gfx_critical(); } } } /* gfx_directx_release_lock: * Releases the surface lock, for hardware accelerated drawing. */ void gfx_directx_release_lock(BITMAP *bmp) { DDRAW_SURFACE *surf; HRESULT hr; /* handle display switch */ if (!_win_app_foreground) gfx_directx_switch_out(); /* find parent */ while (bmp->id & BMP_ID_SUB) { bmp->id &= ~BMP_ID_LOCKED; bmp = (BITMAP *)bmp->extra; } if (bmp->id & BMP_ID_LOCKED) { surf = DDRAW_SURFACE_OF(bmp); if (!(surf->flags & DDRAW_SURFACE_LOST)) { /* only unlock if it doesn't use pseudo video memory */ hr = IDirectDrawSurface2_Unlock(surf->id, NULL); /* If the surface has been lost, try to restore all surfaces * and, on success, try again to unlock the surface. */ if (hr == DDERR_SURFACELOST) { if (restore_all_ddraw_surfaces() == 0) hr = IDirectDrawSurface2_Unlock(surf->id, NULL); } if (FAILED(hr)) _TRACE(PREFIX_E "Can't release lock (%x)\n", hr); } bmp->id &= ~BMP_ID_LOCKED; } } allegro-4.4.3.1/src/win/wgfxdrv.c0000664000175000017500000000153713437077643015525 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of Windows graphics drivers, kept in a seperate file so that * they can be overriden by user programs. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif BEGIN_GFX_DRIVER_LIST GFX_DRIVER_DIRECTX END_GFX_DRIVER_LIST allegro-4.4.3.1/src/win/wwnd.c0000664000175000017500000005054013437077643015013 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main window creation and management. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #include "wddraw.h" #ifndef SCAN_DEPEND #include #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wwnd INFO: " #define PREFIX_W "al-wwnd WARNING: " #define PREFIX_E "al-wwnd ERROR: " /* general */ static HWND allegro_wnd = NULL; char wnd_title[WND_TITLE_SIZE]; /* ASCII string */ int wnd_x = 0; int wnd_y = 0; int wnd_width = 0; int wnd_height = 0; int wnd_sysmenu = FALSE; static int last_wnd_x = -1; static int last_wnd_y = -1; static int window_is_initialized = FALSE; /* graphics */ WIN_GFX_DRIVER *win_gfx_driver; CRITICAL_SECTION gfx_crit_sect; int gfx_crit_sect_nesting = 0; /* close button user hook */ void (*user_close_proc)(void) = NULL; /* window thread internals */ #define ALLEGRO_WND_CLASS "AllegroWindow" static HWND user_wnd = NULL; static WNDPROC user_wnd_proc = NULL; static HANDLE wnd_thread = NULL; static HWND (*wnd_create_proc)(WNDPROC) = NULL; static int old_style = 0; static int (*wnd_msg_pre_proc)(HWND, UINT, WPARAM, LPARAM, int *) = NULL; /* custom window msgs */ #define SWITCH_TIMER 1 static UINT msg_call_proc = 0; static UINT msg_suicide = 0; /* window modules management */ struct WINDOW_MODULES { int keyboard; int mouse; int joystick; int joy_type; int sound; int digi_card; int midi_card; int sound_input; int digi_input_card; int midi_input_card; }; /* Used in adjust_window(). */ #ifndef CCHILDREN_TITLEBAR #define CCHILDREN_TITLEBAR 5 typedef struct { DWORD cbSize; RECT rcTitleBar; DWORD rgstate[CCHILDREN_TITLEBAR + 1]; } TITLEBARINFO, *PTITLEBARINFO, *LPTITLEBARINFO; #endif /* ifndef CCHILDREN_TITLEBAR */ /* init_window_modules: * Initialises the modules that are specified by the WM argument. */ static int init_window_modules(struct WINDOW_MODULES *wm) { if (wm->keyboard) install_keyboard(); if (wm->mouse) install_mouse(); if (wm->joystick) install_joystick(wm->joy_type); if (wm->sound) install_sound(wm->digi_card, wm->midi_card, NULL); if (wm->sound_input) install_sound_input(wm->digi_input_card, wm->midi_input_card); return 0; } /* exit_window_modules: * Removes the modules that depend upon the main window: * - keyboard (DirectInput), * - mouse (DirectInput), * - joystick (DirectInput), * - sound (DirectSound), * - sound input (DirectSoundCapture). * If WM is not NULL, record which modules are really removed. */ static void exit_window_modules(struct WINDOW_MODULES *wm) { if (wm) memset(wm, 0, sizeof(*wm)); if (_keyboard_installed) { if (wm) wm->keyboard = TRUE; remove_keyboard(); } if (_mouse_installed) { if (wm) wm->mouse = TRUE; remove_mouse(); } if (_joystick_installed) { if (wm) { wm->joystick = TRUE; wm->joy_type = _joy_type; } remove_joystick(); } if (_sound_installed) { if (wm) { wm->sound = TRUE; wm->digi_card = digi_card; wm->midi_card = midi_card; } remove_sound(); } if (_sound_input_installed) { if (wm) { wm->sound_input = TRUE; wm->digi_input_card = digi_input_card; wm->midi_input_card = midi_input_card; } remove_sound_input(); } } /* wnd_call_proc: * Instructs the window thread to call the specified procedure and * waits until the procedure has returned. */ int wnd_call_proc(int (*proc) (void)) { return SendMessage(allegro_wnd, msg_call_proc, (WPARAM)proc, (LPARAM)0); } /* wnd_schedule_proc: * Instructs the window thread to call the specified procedure but * doesn't wait until the procedure has returned. */ void wnd_schedule_proc(int (*proc) (void)) { PostMessage(allegro_wnd, msg_call_proc, (WPARAM)proc, (LPARAM)0); } /* directx_wnd_proc: * Window procedure for the Allegro window class. */ static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { PAINTSTRUCT ps; if (message == msg_call_proc) return ( ( LRESULT(*)( void ) )wparam ) ( ); if (message == msg_suicide) { DestroyWindow(wnd); return 0; } /* Call user callback if available */ if (wnd_msg_pre_proc){ int retval = 0; if (wnd_msg_pre_proc(wnd, message, wparam, lparam, &retval) == 0) return (LRESULT)retval; } /* See get_reverse_mapping() in wkeybd.c to see what this is for. */ if (FALSE && (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)) { static char name[256]; TCHAR str[256]; WCHAR wstr[256]; GetKeyNameText(lparam, str, sizeof str); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr); uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name); _TRACE(PREFIX_I" key[%s] = 0x%08lx;\n", name, lparam & 0x1ff0000); } switch (message) { case WM_CREATE: if (!user_wnd_proc) allegro_wnd = wnd; break; case WM_DESTROY: if (user_wnd_proc) { exit_window_modules(NULL); _win_reset_switch_mode(); } else { PostQuitMessage(0); } allegro_wnd = NULL; break; case WM_SETCURSOR: if (!user_wnd_proc || _mouse_installed) { mouse_set_syscursor(); return 1; /* not TRUE */ } break; case WM_ACTIVATE: if (LOWORD(wparam) == WA_INACTIVE) { _win_switch_out(); } else { /* Ignore the WM_ACTIVATE event if the window is minimized. */ if (HIWORD(wparam)) break; if (gfx_driver && !gfx_driver->windowed) { /* 1.2s delay to let Windows complete the switch in fullscreen mode */ SetTimer(allegro_wnd, SWITCH_TIMER, 1200, NULL); } else { /* no delay in windowed mode */ _win_switch_in(); } } break; case WM_TIMER: if (wparam == SWITCH_TIMER) { KillTimer(allegro_wnd, SWITCH_TIMER); _win_switch_in(); return 0; } break; case WM_ENTERSIZEMOVE: if (win_gfx_driver && win_gfx_driver->enter_sysmode) win_gfx_driver->enter_sysmode(); break; case WM_EXITSIZEMOVE: if (win_gfx_driver && win_gfx_driver->exit_sysmode) win_gfx_driver->exit_sysmode(); break; case WM_MOVE: if (GetActiveWindow() == allegro_wnd) { if (!IsIconic(allegro_wnd)) { wnd_x = (short) LOWORD(lparam); wnd_y = (short) HIWORD(lparam); if (win_gfx_driver && win_gfx_driver->move) win_gfx_driver->move(wnd_x, wnd_y, wnd_width, wnd_height); } else if (win_gfx_driver && win_gfx_driver->iconify) { win_gfx_driver->iconify(); } } break; case WM_SIZE: wnd_width = LOWORD(lparam); wnd_height = HIWORD(lparam); break; case WM_PAINT: if (!user_wnd_proc || win_gfx_driver) { BeginPaint(wnd, &ps); if (win_gfx_driver && win_gfx_driver->paint) win_gfx_driver->paint(&ps.rcPaint); EndPaint(wnd, &ps); return 0; } break; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: /* Disable the default message-based key handler * in order to prevent conflicts on NT kernels. */ if (!user_wnd_proc || _keyboard_installed) return 0; break; case WM_SYSCOMMAND: if (wparam == SC_MONITORPOWER || wparam == SC_SCREENSAVE) { if (_screensaver_policy == ALWAYS_DISABLED || (_screensaver_policy == FULLSCREEN_DISABLED && gfx_driver && !gfx_driver->windowed)) return 0; } break; case WM_INITMENUPOPUP: wnd_sysmenu = TRUE; mouse_set_sysmenu(TRUE); if (win_gfx_driver && win_gfx_driver->enter_sysmode) win_gfx_driver->enter_sysmode(); break; case WM_MENUSELECT: if ((HIWORD(wparam) == 0xFFFF) && (!lparam)) { wnd_sysmenu = FALSE; mouse_set_sysmenu(FALSE); if (win_gfx_driver && win_gfx_driver->exit_sysmode) win_gfx_driver->exit_sysmode(); } break; case WM_MENUCHAR : return (MNC_CLOSE<<16)|(wparam&0xffff); case WM_CLOSE: if (!user_wnd_proc) { if (user_close_proc) (*user_close_proc)(); return 0; } break; case WM_QUERYNEWPALETTE: case WM_PALETTECHANGED: if ((HWND)wparam != wnd && gfx_directx_primary_surface) { IDirectDrawSurface2_SetPalette(gfx_directx_primary_surface->id, ddpalette); InvalidateRect(wnd, NULL, 1); return 1; } break; } /* pass message to default window proc */ if (user_wnd_proc) return CallWindowProc(user_wnd_proc, wnd, message, wparam, lparam); else return DefWindowProc(wnd, message, wparam, lparam); } /* create_directx_window: * Creates the Allegro window. */ static HWND create_directx_window(void) { static int first = 1; WNDCLASS wnd_class; char fname[1024]; HWND wnd; if (first) { /* setup the window class */ wnd_class.style = CS_HREDRAW | CS_VREDRAW; wnd_class.lpfnWndProc = directx_wnd_proc; wnd_class.cbClsExtra = 0; wnd_class.cbWndExtra = 0; wnd_class.hInstance = allegro_inst; wnd_class.hIcon = LoadIcon(allegro_inst, "allegro_icon"); if (!wnd_class.hIcon) wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW); wnd_class.hbrBackground = NULL; wnd_class.lpszMenuName = NULL; wnd_class.lpszClassName = ALLEGRO_WND_CLASS; RegisterClass(&wnd_class); /* what are we called? */ get_executable_name(fname, sizeof(fname)); ustrlwr(fname); usetc(get_extension(fname), 0); if (ugetat(fname, -1) == '.') usetat(fname, -1, 0); do_uconvert(get_filename(fname), U_CURRENT, wnd_title, U_ASCII, WND_TITLE_SIZE); first = 0; } /* create the window now */ wnd = CreateWindowEx(WS_EX_APPWINDOW, ALLEGRO_WND_CLASS, wnd_title, WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, -100, -100, 0, 0, NULL, NULL, allegro_inst, NULL); if (!wnd) { _TRACE(PREFIX_E "CreateWindowEx() failed (%s)\n", win_err_str(GetLastError())); return NULL; } SetSystemPaletteUse(GetDC(wnd), SYSPAL_NOSTATIC256); ShowWindow(wnd, SW_SHOWNORMAL); SetForegroundWindow(wnd); UpdateWindow(wnd); return wnd; } /* wnd_thread_proc: * Thread function that handles the messages of the directx window. */ static void wnd_thread_proc(HANDLE setup_event) { DWORD result; MSG msg; _win_thread_init(); _TRACE(PREFIX_I "window thread starts\n"); /* setup window */ if (wnd_create_proc) allegro_wnd = wnd_create_proc(directx_wnd_proc); else allegro_wnd = create_directx_window(); if (!allegro_wnd) goto End; /* now the thread it running successfully, let's acknowledge */ SetEvent(setup_event); /* message loop */ while (TRUE) { result = MsgWaitForMultipleObjects(_win_input_events, _win_input_event_id, FALSE, INFINITE, QS_ALLINPUT); if ((result >= WAIT_OBJECT_0) && (result < (int)(WAIT_OBJECT_0 + _win_input_events))) { /* one of the registered events is in signaled state */ (*_win_input_event_handler[result - WAIT_OBJECT_0])(); } else if (result == WAIT_OBJECT_0 + _win_input_events) { /* messages are waiting in the queue */ while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { DispatchMessage(&msg); } else { goto End; } } } } End: _TRACE(PREFIX_I "window thread exits\n"); _win_thread_exit(); } /* init_directx_window: * If the user called win_set_window, the user window will be hooked to receive * messages from Allegro. Otherwise a thread is created to own the new window. */ int init_directx_window(void) { union { POINT p; RECT r; } win_rect; HANDLE events[2]; long result; /* setup globals */ msg_call_proc = RegisterWindowMessage("Allegro call proc"); msg_suicide = RegisterWindowMessage("Allegro window suicide"); /* initialize gfx critical section */ InitializeCriticalSection(&gfx_crit_sect); if (user_wnd) { /* initializes input module and requests dedicated thread */ _win_input_init(TRUE); /* hook the user window */ user_wnd_proc = (WNDPROC) SetWindowLongPtr(user_wnd, GWLP_WNDPROC, (LONG_PTR)directx_wnd_proc); if (!user_wnd_proc) return -1; allegro_wnd = user_wnd; /* retrieve the window dimensions */ GetWindowRect(allegro_wnd, &win_rect.r); ClientToScreen(allegro_wnd, &win_rect.p); ClientToScreen(allegro_wnd, &win_rect.p + 1); wnd_x = win_rect.r.left; wnd_y = win_rect.r.top; wnd_width = win_rect.r.right - win_rect.r.left; wnd_height = win_rect.r.bottom - win_rect.r.top; } else { /* initializes input module without dedicated thread */ _win_input_init(FALSE); /* create window thread */ events[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* acknowledges that thread is up */ events[1] = (HANDLE) _beginthread(wnd_thread_proc, 0, events[0]); result = WaitForMultipleObjects(2, events, FALSE, INFINITE); CloseHandle(events[0]); switch (result) { case WAIT_OBJECT_0: /* window was created successfully */ wnd_thread = events[1]; SetThreadPriority(wnd_thread, THREAD_PRIORITY_ABOVE_NORMAL); break; default: /* thread failed to create window */ return -1; } } /* save window style */ old_style = GetWindowLong(allegro_wnd, GWL_STYLE); return 0; } /* exit_directx_window: * If a user window was hooked, the old window proc is set. Otherwise * the window thread is destroyed. */ void exit_directx_window(void) { if (user_wnd) { /* restore old window proc */ SetWindowLongPtr(user_wnd, GWLP_WNDPROC, (LONG_PTR)user_wnd_proc); user_wnd_proc = NULL; user_wnd = NULL; allegro_wnd = NULL; } else { /* Destroy the window: we cannot directly use DestroyWindow() because * we are not running in the same thread as that of the window. */ PostMessage(allegro_wnd, msg_suicide, 0, 0); /* wait until the window thread ends */ WaitForSingleObject(wnd_thread, INFINITE); wnd_thread = NULL; } DeleteCriticalSection(&gfx_crit_sect); _win_input_exit(); window_is_initialized = FALSE; } /* restore_window_style: * Restores the previous style of the window. */ void restore_window_style(void) { SetWindowLong(allegro_wnd, GWL_STYLE, old_style); SetWindowPos(allegro_wnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); } /* adjust_window: * Moves and resizes the window if we have full control over it. */ int adjust_window(int w, int h) { RECT working_area, win_size; TITLEBARINFO tb_info; HMODULE user32_handle; typedef BOOL (WINAPI *func)(HWND, PTITLEBARINFO); func get_title_bar_info = NULL; int tb_height = 0; static int last_w=-1, last_h=-1; if (!user_wnd) { SystemParametersInfo(SPI_GETWORKAREA, 0, &working_area, 0); if ((last_w == -1) && (last_h == -1)) { /* first window placement: try to center it */ last_wnd_x = (working_area.left + working_area.right - w)/2; last_wnd_y = (working_area.top + working_area.bottom - h)/2; } else { /* try to get the height of the window's title bar */ user32_handle = GetModuleHandle("user32"); if (user32_handle) { get_title_bar_info = (func)GetProcAddress(user32_handle, "GetTitleBarInfo"); if (get_title_bar_info) { tb_info.cbSize = sizeof(TITLEBARINFO); if (get_title_bar_info(allegro_wnd, &tb_info)) tb_height = tb_info.rcTitleBar.bottom - tb_info.rcTitleBar.top; } } if (!user32_handle || !get_title_bar_info) tb_height = GetSystemMetrics(SM_CYSIZE); /* try to center the window relative to its last position */ last_wnd_x += (last_w - w)/2; last_wnd_y += (last_h - h)/2; if (last_wnd_x + w >= working_area.right) last_wnd_x = working_area.right - w; if (last_wnd_y + h >= working_area.bottom) last_wnd_y = working_area.bottom - h; if (last_wnd_x < working_area.left) last_wnd_x = working_area.left; if (last_wnd_y - tb_height < working_area.top) last_wnd_y = working_area.top + tb_height; } #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH last_wnd_x &= 0xfffffffc; #endif win_size.left = last_wnd_x; win_size.top = last_wnd_y; win_size.right = last_wnd_x+w; win_size.bottom = last_wnd_y+h; last_w = w; last_h = h; /* retrieve the size of the decorated window */ AdjustWindowRect(&win_size, GetWindowLong(allegro_wnd, GWL_STYLE), FALSE); /* display the window */ MoveWindow(allegro_wnd, win_size.left, win_size.top, win_size.right - win_size.left, win_size.bottom - win_size.top, TRUE); /* check that the actual window size is the one requested */ GetClientRect(allegro_wnd, &win_size); if (((win_size.right - win_size.left) != w) || ((win_size.bottom - win_size.top) != h)) return -1; wnd_x = last_wnd_x; wnd_y = last_wnd_y; wnd_width = w; wnd_height = h; } return 0; } /* save_window_pos: * Stores the position of the current window before closing it so that * it can be used as the initial position for the next window. */ void save_window_pos(void) { last_wnd_x = wnd_x; last_wnd_y = wnd_y; } /* win_set_window: * Selects an user-defined window for Allegro or * the built-in window if NULL is passed. */ void win_set_window(HWND wnd) { static int (*saved_scbc)(void (*proc)(void)) = NULL; struct WINDOW_MODULES wm; if (window_is_initialized || !wnd) { exit_window_modules(&wm); exit_directx_window(); } user_wnd = wnd; /* The user retains full control over the close button if he registers a user-defined window. */ if (user_wnd) { if (!saved_scbc) saved_scbc = system_directx.set_close_button_callback; system_directx.set_close_button_callback = NULL; } else { if (saved_scbc) system_directx.set_close_button_callback = saved_scbc; } if (window_is_initialized || !wnd) { init_directx_window(); init_window_modules(&wm); } window_is_initialized = TRUE; } /* win_get_window: * Returns the Allegro window handle. */ HWND win_get_window(void) { return allegro_wnd; } void win_set_msg_pre_proc(int (*proc)(HWND, UINT, WPARAM, LPARAM, int *)) { wnd_msg_pre_proc = proc; } /* win_set_wnd_create_proc: * Sets a custom window creation proc. */ void win_set_wnd_create_proc(HWND (*proc)(WNDPROC)) { wnd_create_proc = proc; } /* win_grab_input: * Grabs the input devices. */ void win_grab_input(void) { wnd_schedule_proc(key_dinput_acquire); wnd_schedule_proc(mouse_dinput_grab); wnd_schedule_proc(joystick_dinput_acquire); } allegro-4.4.3.1/src/win/wmouse.c0000664000175000017500000005202413437077643015352 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows mouse driver. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #define DIRECTINPUT_VERSION 0x0300 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wmouse INFO: " #define PREFIX_W "al-wmouse WARNING: " #define PREFIX_E "al-wmouse ERROR: " static MOUSE_DRIVER mouse_directx; _DRIVER_INFO _mouse_driver_list[] = { {MOUSE_DIRECTX, &mouse_directx, TRUE}, {MOUSEDRV_NONE, &mousedrv_none, TRUE}, {0, NULL, 0} }; static int mouse_directx_init(void); static void mouse_directx_exit(void); static void mouse_directx_position(int x, int y); static void mouse_directx_set_range(int x1, int y1, int x2, int y2); static void mouse_directx_set_speed(int xspeed, int yspeed); static void mouse_directx_get_mickeys(int *mickeyx, int *mickeyy); static void mouse_directx_enable_hardware_cursor(int mode); static int mouse_directx_select_system_cursor(int cursor); static MOUSE_DRIVER mouse_directx = { MOUSE_DIRECTX, empty_string, empty_string, "DirectInput mouse", mouse_directx_init, mouse_directx_exit, NULL, // AL_METHOD(void, poll, (void)); NULL, // AL_METHOD(void, timer_poll, (void)); mouse_directx_position, mouse_directx_set_range, mouse_directx_set_speed, mouse_directx_get_mickeys, NULL, // AL_METHOD(int, analyse_data, (AL_CONST char *buffer, int size)); mouse_directx_enable_hardware_cursor, mouse_directx_select_system_cursor }; HCURSOR _win_hcursor = NULL; /* Hardware cursor to display */ #define DINPUT_BUFFERSIZE 256 static HANDLE mouse_input_event = NULL; static LPDIRECTINPUT mouse_dinput = NULL; static LPDIRECTINPUTDEVICE mouse_dinput_device = NULL; static int dinput_buttons = 0; static int dinput_wheel = FALSE; static int mouse_swap_button = FALSE; /* TRUE means buttons 1 and 2 are swapped */ static int dinput_x = 0; /* tracked dinput positon */ static int dinput_y = 0; static int mouse_mx = 0; /* internal position, in mickeys */ static int mouse_my = 0; static int mouse_sx = 2; /* mickey -> pixel scaling factor */ static int mouse_sy = 2; #define MAF_DEFAULT 1 /* mouse acceleration parameters */ static int mouse_accel_fact = MAF_DEFAULT; static int mouse_accel_mult = MAF_DEFAULT; static int mouse_accel_thr1 = 5 * 5; static int mouse_accel_thr2 = 16 * 16; static int mouse_minx = 0; /* mouse range */ static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int mymickey_x = 0; /* for get_mouse_mickeys() */ static int mymickey_y = 0; static int mymickey_ox = 0; static int mymickey_oy = 0; #define MICKEY_TO_COORD_X(n) ((n) / mouse_sx) #define MICKEY_TO_COORD_Y(n) ((n) / mouse_sy) #define COORD_TO_MICKEY_X(n) ((n) * mouse_sx) #define COORD_TO_MICKEY_Y(n) ((n) * mouse_sy) #define CLEAR_MICKEYS() \ { \ if (gfx_driver && gfx_driver->windowed) { \ POINT p; \ \ GetCursorPos(&p); \ \ p.x -= wnd_x; \ p.y -= wnd_y; \ \ mymickey_ox = p.x; \ mymickey_oy = p.y; \ } \ else { \ dinput_x = 0; \ dinput_y = 0; \ mymickey_ox = 0; \ mymickey_oy = 0; \ } \ } #define READ_CURSOR_POS(p) \ { \ GetCursorPos(&p); \ \ p.x -= wnd_x; \ p.y -= wnd_y; \ \ if ((p.x < mouse_minx) || (p.x > mouse_maxx) || \ (p.y < mouse_miny) || (p.y > mouse_maxy)) { \ if (_mouse_on) { \ _mouse_on = FALSE; \ wnd_schedule_proc(mouse_set_syscursor); \ } \ } \ else { \ if (!_mouse_on) { \ _mouse_on = TRUE; \ wnd_schedule_proc(mouse_set_syscursor); \ } \ _mouse_x = p.x; \ _mouse_y = p.y; \ } \ } /* dinput_err_str: * Returns a DirectInput error string. */ #ifdef DEBUGMODE static char* dinput_err_str(long err) { static char err_str[64]; switch (err) { case DIERR_ACQUIRED: _al_sane_strncpy(err_str, "the device is acquired", sizeof(err_str)); break; case DIERR_NOTACQUIRED: _al_sane_strncpy(err_str, "the device is not acquired", sizeof(err_str)); break; case DIERR_INPUTLOST: _al_sane_strncpy(err_str, "access to the device was not granted", sizeof(err_str)); break; case DIERR_INVALIDPARAM: _al_sane_strncpy(err_str, "the device does not have a selected data format", sizeof(err_str)); break; #ifdef DIERR_OTHERAPPHASPRIO /* this is not a legacy DirectX 3 error code */ case DIERR_OTHERAPPHASPRIO: _al_sane_strncpy(err_str, "can't acquire the device in background", sizeof(err_str)); break; #endif default: _al_sane_strncpy(err_str, "unknown error", sizeof(err_str)); } return err_str; } #else #define dinput_err_str(hr) "\0" #endif /* mouse_dinput_handle_event: [input thread] * Handles a single event. */ static void mouse_dinput_handle_event(int ofs, int data) { static int last_data_x = 0; static int last_data_y = 0; static int last_was_x = 0; int mag; switch (ofs) { case DIMOFS_X: if (!gfx_driver || !gfx_driver->windowed) { if (last_was_x) last_data_y = 0; last_data_x = data; last_was_x = 1; if (mouse_accel_mult) { mag = last_data_x*last_data_x + last_data_y*last_data_y; if (mag >= mouse_accel_thr2) data *= (mouse_accel_mult<<1); else if (mag >= mouse_accel_thr1) data *= mouse_accel_mult; } dinput_x += data; } break; case DIMOFS_Y: if (!gfx_driver || !gfx_driver->windowed) { if (!last_was_x) last_data_x = 0; last_data_y = data; last_was_x = 0; if (mouse_accel_mult) { mag = last_data_x*last_data_x + last_data_y*last_data_y; if (mag >= mouse_accel_thr2) data *= (mouse_accel_mult<<1); else if (mag >= mouse_accel_thr1) data *= mouse_accel_mult; } dinput_y += data; } break; case DIMOFS_Z: if (dinput_wheel && _mouse_on) _mouse_z += data/120; break; case DIMOFS_BUTTON0: if (data & 0x80) { if (_mouse_on) _mouse_b |= (mouse_swap_button ? 2 : 1); } else _mouse_b &= ~(mouse_swap_button ? 2 : 1); break; case DIMOFS_BUTTON1: if (data & 0x80) { if (_mouse_on) _mouse_b |= (mouse_swap_button ? 1 : 2); } else _mouse_b &= ~(mouse_swap_button ? 1 : 2); break; case DIMOFS_BUTTON2: if (data & 0x80) { if (_mouse_on) _mouse_b |= 4; } else _mouse_b &= ~4; break; case DIMOFS_BUTTON3: if (data & 0x80) { if (_mouse_on) _mouse_b |= 8; } else _mouse_b &= ~8; break; } } /* mouse_dinput_handle: [input thread] * Handles queued mouse input. */ static void mouse_dinput_handle(void) { static DIDEVICEOBJECTDATA message_buffer[DINPUT_BUFFERSIZE]; unsigned long int waiting_messages; HRESULT hr; unsigned long int i; /* the whole buffer is free */ waiting_messages = DINPUT_BUFFERSIZE; /* fill the buffer */ hr = IDirectInputDevice_GetDeviceData(mouse_dinput_device, sizeof(DIDEVICEOBJECTDATA), message_buffer, &waiting_messages, 0); /* was device lost ? */ if ((hr == DIERR_NOTACQUIRED) || (hr == DIERR_INPUTLOST)) { /* reacquire device */ _TRACE(PREFIX_W "mouse device not acquired or lost\n"); wnd_schedule_proc(mouse_dinput_acquire); } else if (FAILED(hr)) { /* other error? */ _TRACE(PREFIX_E "unexpected error while filling mouse message buffer\n"); } else { /* normally only this case should happen */ for (i = 0; i < waiting_messages; i++) { mouse_dinput_handle_event(message_buffer[i].dwOfs, message_buffer[i].dwData); } if (gfx_driver && gfx_driver->windowed) { /* windowed input mode */ if (!wnd_sysmenu) { POINT p; READ_CURSOR_POS(p); mymickey_x += p.x - mymickey_ox; mymickey_y += p.y - mymickey_oy; mymickey_ox = p.x; mymickey_oy = p.y; _handle_mouse_input(); } } else { /* fullscreen input mode */ mymickey_x += dinput_x - mymickey_ox; mymickey_y += dinput_y - mymickey_oy; mymickey_ox = dinput_x; mymickey_oy = dinput_y; _mouse_x = MICKEY_TO_COORD_X(mouse_mx + dinput_x); _mouse_y = MICKEY_TO_COORD_Y(mouse_my + dinput_y); if ((_mouse_x < mouse_minx) || (_mouse_x > mouse_maxx) || (_mouse_y < mouse_miny) || (_mouse_y > mouse_maxy)) { _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); CLEAR_MICKEYS(); } if (!_mouse_on) { _mouse_on = TRUE; wnd_schedule_proc(mouse_set_syscursor); } _handle_mouse_input(); } } } /* mouse_dinput_acquire: [window thread] * Acquires the mouse device. */ int mouse_dinput_acquire(void) { HRESULT hr; if (mouse_dinput_device) { _mouse_b = 0; hr = IDirectInputDevice_Acquire(mouse_dinput_device); if (FAILED(hr)) { _TRACE(PREFIX_E "acquire mouse failed: %s\n", dinput_err_str(hr)); return -1; } /* The cursor may not be in the client area * so we don't set _mouse_on here. */ return 0; } else { return -1; } } /* mouse_dinput_unacquire: [window thread] * Unacquires the mouse device. */ int mouse_dinput_unacquire(void) { if (mouse_dinput_device) { IDirectInputDevice_Unacquire(mouse_dinput_device); _mouse_b = 0; _mouse_on = FALSE; return 0; } else { return -1; } } /* mouse_dinput_grab: [window thread] * Grabs the mouse device. */ int mouse_dinput_grab(void) { HRESULT hr; DWORD level; HWND allegro_wnd = win_get_window(); if (mouse_dinput_device) { /* necessary in order to set the cooperative level */ mouse_dinput_unacquire(); if (gfx_driver && !gfx_driver->windowed) { level = DISCL_FOREGROUND | DISCL_EXCLUSIVE; _TRACE(PREFIX_I "foreground exclusive cooperative level requested for mouse\n"); } else { level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE; _TRACE(PREFIX_I "foreground non-exclusive cooperative level requested for mouse\n"); } /* set cooperative level */ hr = IDirectInputDevice_SetCooperativeLevel(mouse_dinput_device, allegro_wnd, level); if (FAILED(hr)) { _TRACE(PREFIX_E "set cooperative level failed: %s\n", dinput_err_str(hr)); return -1; } mouse_dinput_acquire(); /* update the system cursor */ mouse_set_syscursor(); return 0; } else { /* update the system cursor */ mouse_set_syscursor(); return -1; } } /* mouse_set_syscursor: [window thread] * Selects whatever system cursor we should display. */ int mouse_set_syscursor(void) { HWND allegro_wnd = win_get_window(); if ((mouse_dinput_device && _mouse_on) || (gfx_driver && !gfx_driver->windowed)) { SetCursor(_win_hcursor); /* Make sure the cursor is removed by the system. */ PostMessage(allegro_wnd, WM_MOUSEMOVE, 0, 0); } else SetCursor(LoadCursor(NULL, IDC_ARROW)); return 0; } /* mouse_set_sysmenu: [window thread] * Changes the state of the mouse when going to/from sysmenu mode. */ int mouse_set_sysmenu(int state) { POINT p; if (mouse_dinput_device) { if (state == TRUE) { if (_mouse_on) { _mouse_on = FALSE; mouse_set_syscursor(); } } else { READ_CURSOR_POS(p); } _handle_mouse_input(); } return 0; } /* mouse_dinput_exit: [primary thread] * Shuts down the DirectInput mouse device. */ static int mouse_dinput_exit(void) { if (mouse_dinput_device) { /* unregister event handler first */ _win_input_unregister_event(mouse_input_event); /* unacquire device */ wnd_call_proc(mouse_dinput_unacquire); /* now it can be released */ IDirectInputDevice_Release(mouse_dinput_device); mouse_dinput_device = NULL; } /* release DirectInput interface */ if (mouse_dinput) { IDirectInput_Release(mouse_dinput); mouse_dinput = NULL; } /* close event handle */ if (mouse_input_event) { CloseHandle(mouse_input_event); mouse_input_event = NULL; } /* update the system cursor */ wnd_schedule_proc(mouse_set_syscursor); return 0; } /* mouse_enum_callback: [primary thread] * Helper function for finding out how many buttons we have. */ static BOOL CALLBACK mouse_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { if (memcmp(&lpddoi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0) dinput_wheel = TRUE; else if (memcmp(&lpddoi->guidType, &GUID_Button, sizeof(GUID)) == 0) dinput_buttons++; return DIENUM_CONTINUE; } /* mouse_dinput_init: [primary thread] * Sets up the DirectInput mouse device. */ static int mouse_dinput_init(void) { HRESULT hr; DIPROPDWORD property_buf_size = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ DINPUT_BUFFERSIZE, // dwData }; /* Get DirectInput interface */ hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput, (void**)&mouse_dinput); if (FAILED(hr)) goto Error; hr = IDirectInput_Initialize(mouse_dinput, allegro_inst, DIRECTINPUT_VERSION); if (FAILED(hr)) goto Error; /* Create the mouse device */ hr = IDirectInput_CreateDevice(mouse_dinput, &GUID_SysMouseEm2, &mouse_dinput_device, NULL); if (FAILED(hr)) goto Error; /* Find how many buttons */ dinput_buttons = 0; dinput_wheel = FALSE; hr = IDirectInputDevice_EnumObjects(mouse_dinput_device, mouse_enum_callback, NULL, DIDFT_PSHBUTTON | DIDFT_AXIS); if (FAILED(hr)) goto Error; /* Check to see if the buttons are swapped (left-hand) */ mouse_swap_button = GetSystemMetrics(SM_SWAPBUTTON); /* Set data format */ hr = IDirectInputDevice_SetDataFormat(mouse_dinput_device, &c_dfDIMouse); if (FAILED(hr)) goto Error; /* Set buffer size */ hr = IDirectInputDevice_SetProperty(mouse_dinput_device, DIPROP_BUFFERSIZE, &property_buf_size.diph); if (FAILED(hr)) goto Error; /* Enable event notification */ mouse_input_event = CreateEvent(NULL, FALSE, FALSE, NULL); hr = IDirectInputDevice_SetEventNotification(mouse_dinput_device, mouse_input_event); if (FAILED(hr)) goto Error; /* Register event handler */ if (_win_input_register_event(mouse_input_event, mouse_dinput_handle) != 0) goto Error; /* Grab the device */ _mouse_on = TRUE; wnd_call_proc(mouse_dinput_grab); return 0; Error: mouse_dinput_exit(); return -1; } /* mouse_directx_init: [primary thread] */ static int mouse_directx_init(void) { char tmp1[64], tmp2[128]; /* get user acceleration factor */ mouse_accel_fact = get_config_int(uconvert_ascii("mouse", tmp1), uconvert_ascii("mouse_accel_factor", tmp2), MAF_DEFAULT); if (mouse_dinput_init() != 0) { /* something has gone wrong */ _TRACE(PREFIX_E "mouse handler init failed\n"); return -1; } /* the mouse handler has successfully set up */ _TRACE(PREFIX_I "mouse handler starts\n"); return dinput_buttons; } /* mouse_directx_exit: [primary thread] */ static void mouse_directx_exit(void) { if (mouse_dinput_device) { /* command mouse handler shutdown */ _TRACE(PREFIX_I "mouse handler exits\n"); mouse_dinput_exit(); } } /* mouse_directx_position: [primary thread] */ static void mouse_directx_position(int x, int y) { _enter_critical(); _mouse_x = x; _mouse_y = y; mouse_mx = COORD_TO_MICKEY_X(x); mouse_my = COORD_TO_MICKEY_Y(y); if (gfx_driver && gfx_driver->windowed) SetCursorPos(x+wnd_x, y+wnd_y); CLEAR_MICKEYS(); mymickey_x = mymickey_y = 0; /* force mouse update */ SetEvent(mouse_input_event); _exit_critical(); } /* mouse_directx_set_range: [primary thread] */ static void mouse_directx_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; _enter_critical(); _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); CLEAR_MICKEYS(); _exit_critical(); /* scale up the acceleration multiplier to the range */ mouse_accel_mult = mouse_accel_fact * MAX(x2-x1+1, y2-y1+1)/320; } /* mouse_directx_set_speed: [primary thread] */ static void mouse_directx_set_speed(int xspeed, int yspeed) { _enter_critical(); mouse_sx = MAX(1, xspeed); mouse_sy = MAX(1, yspeed); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); CLEAR_MICKEYS(); _exit_critical(); } /* mouse_directx_get_mickeys: [primary thread] */ static void mouse_directx_get_mickeys(int *mickeyx, int *mickeyy) { int temp_x = mymickey_x; int temp_y = mymickey_y; mymickey_x -= temp_x; mymickey_y -= temp_y; *mickeyx = temp_x; *mickeyy = temp_y; } /* mouse_directx_enable_hardware_cursor: * enable the hardware cursor; actually a no-op in Windows, but we need to * put something in the vtable. */ static void mouse_directx_enable_hardware_cursor(int mode) { /* Do nothing */ (void)mode; } /* mouse_directx_select_system_cursor: * Select an OS native cursor */ static int mouse_directx_select_system_cursor (int cursor) { HCURSOR wc; HWND allegro_wnd = win_get_window(); wc = NULL; switch(cursor) { case MOUSE_CURSOR_ARROW: wc = LoadCursor(NULL, IDC_ARROW); break; case MOUSE_CURSOR_BUSY: wc = LoadCursor(NULL, IDC_WAIT); break; case MOUSE_CURSOR_QUESTION: wc = LoadCursor(NULL, IDC_HELP); break; case MOUSE_CURSOR_EDIT: wc = LoadCursor(NULL, IDC_IBEAM); break; default: return 0; } _win_hcursor = wc; SetCursor(_win_hcursor); PostMessage(allegro_wnd, WM_MOUSEMOVE, 0, 0); return cursor; } allegro-4.4.3.1/src/win/wddmode.c0000664000175000017500000002664213437077643015465 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw video mode setting. * * By Stefan Schimanski. * * Unified setup code and refresh rate support by Eric Botcazou. * * Graphics mode list fetching code by Henrik Stokseth. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddmode INFO: " #define PREFIX_W "al-wddmode WARNING: " #define PREFIX_E "al-wddmode ERROR: " int _win_desktop_depth; RGB_MAP _win_desktop_rgb_map; /* for 8-bit desktops */ int mode_supported; static int pixel_realdepth[] = {8, 15, 15, 16, 16, 24, 24, 32, 32, 0}; static DDPIXELFORMAT pixel_format[] = { /* 8-bit */ {sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0, {8}, {0}, {0}, {0}, {0}}, /* 16-bit RGB 5:5:5 */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0x7C00}, {0x03e0}, {0x001F}, {0}}, /* 16-bit BGR 5:5:5 */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0x001F}, {0x03e0}, {0x7C00}, {0}}, /* 16-bit RGB 5:6:5 */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0xF800}, {0x07e0}, {0x001F}, {0}}, /* 16-bit BGR 5:6:5 */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0x001F}, {0x07e0}, {0xF800}, {0}}, /* 24-bit RGB */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {24}, {0xFF0000}, {0x00FF00}, {0x0000FF}, {0}}, /* 24-bit BGR */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {24}, {0x0000FF}, {0x00FF00}, {0xFF0000}, {0}}, /* 32-bit RGB */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {32}, {0xFF0000}, {0x00FF00}, {0x0000FF}, {0}}, /* 32-bit BGR */ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {32}, {0x0000FF}, {0x00FF00}, {0xFF0000}, {0}} }; /* window thread callback parameters */ static int _wnd_width, _wnd_height, _wnd_depth, _wnd_refresh_rate, _wnd_flags; /* wnd_set_video_mode: * Called by window thread to set a gfx mode; this is needed because DirectDraw can only * change the mode in the thread that handles the window. */ static int wnd_set_video_mode(void) { HRESULT hr; HWND allegro_wnd = win_get_window(); /* set the cooperative level to allow fullscreen access */ hr = IDirectDraw2_SetCooperativeLevel(directdraw, allegro_wnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); if (FAILED(hr)) { _TRACE(PREFIX_E "SetCooperativeLevel() failed (%x)\n", hr); return -1; } /* switch to fullscreen mode */ hr = IDirectDraw2_SetDisplayMode(directdraw, _wnd_width, _wnd_height, _wnd_depth, _wnd_refresh_rate, _wnd_flags); if (FAILED(hr)) { _TRACE(PREFIX_E "SetDisplayMode(%u, %u, %u, %u, %u) failed (%x)\n", _wnd_width, _wnd_height, _wnd_depth, _wnd_refresh_rate, _wnd_flags, hr); return -1; } return 0; } /* shift_gamma: * Helper function for changing a 8-bit gamma value into * a fake 6-bit gamma value (shifted 5-bit gamma value). */ static INLINE int shift_gamma(int gamma) { if (gamma<128) return (gamma+7)>>2; else return (gamma-7)>>2; } /* build_desktop_rgb_map: * Builds the RGB map corresponding to the desktop palette. */ void build_desktop_rgb_map(void) { PALETTE pal; PALETTEENTRY system_palette[PAL_SIZE]; HDC dc; int i; /* retrieve Windows system palette */ dc = GetDC(NULL); GetSystemPaletteEntries(dc, 0, PAL_SIZE, system_palette); ReleaseDC(NULL, dc); for (i=0; i>1][pal[0].g>>1][pal[0].b>>1] = 0; } /* get_color_shift: * Returns shift value for color mask. */ static int get_color_shift(int mask) { int n; for (n = 0; ((mask & 1) == 0) && (mask != 0); n++) mask >>= 1; return n; } /* get_color_bits: * Returns used bits in color mask. */ static int get_color_bits(int mask) { int n; int num = 0; for (n = 0; n < 32; n++) { num += (mask & 1); mask >>= 1; } return num; } /* gfx_directx_compare_color_depth: * Compares the requested color depth with the desktop depth and find * the best pixel format for color conversion if they don't match. * Returns 0 if the depths match, -1 if they don't. */ int gfx_directx_compare_color_depth(int color_depth) { DDSURFACEDESC surf_desc; HRESULT hr; int i; /* get current video mode */ surf_desc.dwSize = sizeof(surf_desc); hr = IDirectDraw2_GetDisplayMode(directdraw, &surf_desc); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get color format.\n"); return -1; } /* get the *real* color depth of the desktop */ _win_desktop_depth = surf_desc.ddpfPixelFormat.dwRGBBitCount; if (_win_desktop_depth == 16) /* sure? */ _win_desktop_depth = get_color_bits(surf_desc.ddpfPixelFormat.dwRBitMask) + get_color_bits(surf_desc.ddpfPixelFormat.dwGBitMask) + get_color_bits(surf_desc.ddpfPixelFormat.dwBBitMask); if (color_depth == _win_desktop_depth) { ddpixel_format = NULL; return 0; } else { /* test for the same depth and RGB order */ for (i=0 ; pixel_realdepth[i] ; i++) { if ((pixel_realdepth[i] == color_depth) && ((surf_desc.ddpfPixelFormat.dwRBitMask & pixel_format[i].dwRBitMask) || (surf_desc.ddpfPixelFormat.dwBBitMask & pixel_format[i].dwBBitMask) || (_win_desktop_depth == 8) || (color_depth == 8))) { ddpixel_format = &pixel_format[i]; break; } } return -1; } } /* gfx_directx_update_color_format: * Sets the _rgb* variables for correct color format. */ int gfx_directx_update_color_format(DDRAW_SURFACE *surf, int color_depth) { DDPIXELFORMAT pixel_format; HRESULT hr; int shift_r, shift_g, shift_b; /* get pixel format */ pixel_format.dwSize = sizeof(DDPIXELFORMAT); hr = IDirectDrawSurface2_GetPixelFormat(surf->id, &pixel_format); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get color format.\n"); return -1; } /* pass color format */ shift_r = get_color_shift(pixel_format.dwRBitMask); shift_g = get_color_shift(pixel_format.dwGBitMask); shift_b = get_color_shift(pixel_format.dwBBitMask); /* set correct shift values */ switch (color_depth) { case 15: _rgb_r_shift_15 = shift_r; _rgb_g_shift_15 = shift_g; _rgb_b_shift_15 = shift_b; break; case 16: _rgb_r_shift_16 = shift_r; _rgb_g_shift_16 = shift_g; _rgb_b_shift_16 = shift_b; break; case 24: _rgb_r_shift_24 = shift_r; _rgb_g_shift_24 = shift_g; _rgb_b_shift_24 = shift_b; break; case 32: _rgb_r_shift_32 = shift_r; _rgb_g_shift_32 = shift_g; _rgb_b_shift_32 = shift_b; break; } return 0; } /* EnumModesCallback: * Callback function for enumerating the graphics modes. */ static HRESULT CALLBACK EnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID gfx_mode_list_ptr) { GFX_MODE_LIST *gfx_mode_list = (GFX_MODE_LIST *)gfx_mode_list_ptr; /* build gfx mode-list */ gfx_mode_list->mode = _al_sane_realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1)); if (!gfx_mode_list->mode) return DDENUMRET_CANCEL; gfx_mode_list->mode[gfx_mode_list->num_modes].width = lpDDSurfaceDesc->dwWidth; gfx_mode_list->mode[gfx_mode_list->num_modes].height = lpDDSurfaceDesc->dwHeight; gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount; /* check if 16 bpp mode is 16 bpp or 15 bpp */ if (gfx_mode_list->mode[gfx_mode_list->num_modes].bpp == 16) { gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = get_color_bits(lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask) + get_color_bits(lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask) + get_color_bits(lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask); } gfx_mode_list->num_modes++; return DDENUMRET_OK; } /* gfx_directx_fetch_mode_list: * Creates a list of available video modes. * Returns the list on success, NULL on failure. */ GFX_MODE_LIST *gfx_directx_fetch_mode_list(void) { GFX_MODE_LIST *gfx_mode_list; int enum_flags, dx_was_off; HRESULT hr; /* enumerate VGA Mode 13h under DirectX 5 or greater */ if (_dx_ver >= 0x500) enum_flags = DDEDM_STANDARDVGAMODES; else enum_flags = 0; if (!directdraw) { init_directx(); dx_was_off = TRUE; } else { dx_was_off = FALSE; } /* start enumeration */ gfx_mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!gfx_mode_list) goto Error; gfx_mode_list->num_modes = 0; gfx_mode_list->mode = NULL; hr = IDirectDraw2_EnumDisplayModes(directdraw, enum_flags, NULL, gfx_mode_list, EnumModesCallback); if (FAILED(hr)) { _AL_FREE(gfx_mode_list); goto Error; } /* terminate mode list */ gfx_mode_list->mode = _al_sane_realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1)); if (!gfx_mode_list->mode) goto Error; gfx_mode_list->mode[gfx_mode_list->num_modes].width = 0; gfx_mode_list->mode[gfx_mode_list->num_modes].height = 0; gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = 0; if (dx_was_off) exit_directx(); return gfx_mode_list; Error: if (dx_was_off) exit_directx(); return NULL; } /* set_video_mode: * Sets the requested fullscreen video mode. */ int set_video_mode(int w, int h, int v_w, int v_h, int color_depth) { HWND allegro_wnd = win_get_window(); _wnd_width = w; _wnd_height = h; _wnd_depth = (color_depth == 15 ? 16 : color_depth); _wnd_refresh_rate = _refresh_rate_request; /* use VGA Mode 13h under DirectX 5 or greater */ if ((w == 320) && (h == 200) && (color_depth == 8) && (_dx_ver >= 0x500)) _wnd_flags = DDSDM_STANDARDVGAMODE; else _wnd_flags = 0; while (TRUE) { /* let the window thread do the hard work */ _TRACE(PREFIX_I "setting display mode(%u, %u, %u, %u)\n", _wnd_width, _wnd_height, _wnd_depth, _wnd_refresh_rate); if (wnd_call_proc(wnd_set_video_mode) == 0) { /* check that the requested mode was properly set by the driver */ if (gfx_directx_compare_color_depth(color_depth) == 0) goto Done; } /* try with no refresh rate request */ if (_wnd_refresh_rate > 0) _wnd_refresh_rate = 0; else break; } _TRACE(PREFIX_E "Unable to set any display mode.\n"); return -1; Done: /* remove the window controls */ SetWindowLong(allegro_wnd, GWL_STYLE, WS_POPUP); /* maximize the window */ ShowWindow(allegro_wnd, SW_MAXIMIZE); /* put it in the foreground */ SetForegroundWindow(allegro_wnd); return 0; } allegro-4.4.3.1/src/win/asmlock.s0000664000175000017500000001461013437077643015503 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Asm functions for Windows bitmap locking. * * By Isaac Cruz. * * Improved dirty rectangles mechanism by Eric Botcazou. * * See readme.txt for copyright information. */ #include "src/i386/asmdefs.inc" .text #if !defined(ALLEGRO_NO_ASM) /* gfx_directx_write_bank: * edx = bitmap * eax = line */ FUNC (gfx_directx_write_bank) /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked /* lock the surface */ pushl %ecx pushl %eax pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_directx_autolock) popl %edx popl %edx popl %eax popl %ecx Locked: /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* gfx_directx_unwrite_bank: * edx = bmp */ FUNC (gfx_directx_unwrite_bank) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock /* unlock surface */ pushl %ecx pushl %eax pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_directx_unlock) popl %edx popl %edx popl %eax popl %ecx /* clear the autolock flag */ andl $~BMP_ID_AUTOLOCK, BMP_ID(%edx) No_unlock: ret /* gfx_directx_write_bank_win: * edx = bitmap * eax = line */ FUNC (gfx_directx_write_bank_win) pushl %ecx /* clobber the line */ movl GLOBL(_al_wd_dirty_lines), %ecx addl BMP_YOFFSET(%edx), %ecx movb $1, (%ecx,%eax) /* _al_wd_dirty_lines[line] = 1; (line has changed) */ /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked_win /* lock the surface */ pushl %eax pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_directx_autolock) popl %edx popl %edx popl %eax Locked_win: popl %ecx /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* gfx_directx_unwrite_bank_win: * edx = bmp */ FUNC (gfx_directx_unwrite_bank_win) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock_win pushl %ecx pushl %eax /* unlock surface */ pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_directx_unlock) popl %edx popl %edx /* clear the autolock flag */ andl $~BMP_ID_AUTOLOCK, BMP_ID(%edx) /* update dirty lines: this is safe because autolocking * is guaranteed to be the only level of locking. */ movl GLOBL(gfx_directx_forefront_bitmap), %edx call update_dirty_lines popl %eax popl %ecx No_unlock_win: ret /* gfx_directx_unlock_win: * arg1 = bmp */ FUNC(gfx_directx_unlock_win) /* unlock surface */ movl 4(%esp), %edx pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_directx_unlock) popl %edx popl %edx /* forefront_bitmap may still be locked in case of nested locking */ movl GLOBL(gfx_directx_forefront_bitmap), %edx testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz No_update_win /* ok, we can safely update */ call update_dirty_lines No_update_win: ret /* update_dirty_lines * edx = dd_frontbuffer * clobbers: %eax, %ecx */ #define RECT_LEFT (%esp) #define RECT_TOP 4(%esp) #define RECT_RIGHT 8(%esp) #define RECT_BOTTOM 12(%esp) update_dirty_lines: pushl %ebx pushl %esi pushl %edi subl $16, %esp /* allocate a RECT structure */ movl $0, RECT_LEFT movl BMP_W(%edx), %ecx /* ecx = dd_frontbuffer->w */ movl %ecx, RECT_RIGHT movl GLOBL(_al_wd_dirty_lines), %ebx /* ebx = _al_wd_dirty_lines */ movl BMP_H(%edx), %esi /* esi = dd_frontbuffer->h */ movl $0, %edi _align_ next_line: movb (%ebx,%edi), %al /* al = _al_wd_dirty_lines[edi] */ testb %al, %al /* is dirty? */ jz test_end /* no ! */ movl %edi, RECT_TOP _align_ loop_dirty_lines: movb $0, (%ebx,%edi) /* _al_wd_dirty_lines[edi] = 0 */ incl %edi movb (%ebx,%edi), %al /* al = _al_wd_dirty_lines[edi] */ testb %al, %al /* is still dirty? */ jnz loop_dirty_lines /* yes ! */ movl %edi, RECT_BOTTOM leal RECT_LEFT, %eax pushl %eax call *GLOBL(_al_wd_update_window) popl %eax _align_ test_end: incl %edi cmpl %edi, %esi /* last line? */ jge next_line /* no ! */ addl $16, %esp popl %edi popl %esi popl %ebx ret /* gfx_gdi_write_bank: * edx = bitmap * eax = line */ FUNC (gfx_gdi_write_bank) pushl %ecx /* clobber the line */ movl GLOBL(gdi_dirty_lines), %ecx addl BMP_YOFFSET(%edx), %ecx movb $1, (%ecx,%eax) /* gdi_dirty_lines[line] = 1; (line has changed) */ /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked_gdi /* lock the surface */ pushl %eax pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_gdi_autolock) popl %edx popl %edx popl %eax Locked_gdi: popl %ecx /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* gfx_gdi_unwrite_bank: * edx = bmp */ FUNC (gfx_gdi_unwrite_bank) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock_gdi /* unlock surface */ pushl %ecx pushl %eax pushl %edx pushl %edx /* argument */ call *GLOBL(ptr_gfx_gdi_unlock) popl %edx popl %edx popl %eax popl %ecx /* clear the autolock flag */ andl $~BMP_ID_AUTOLOCK, BMP_ID(%edx) No_unlock_gdi: ret #endif /* !defined(ALLEGRO_NO_ASM) */ allegro-4.4.3.1/src/win/wdispsw.c0000664000175000017500000001072613437077643015536 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Display switch handling. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wdispsw INFO: " #define PREFIX_W "al-wdispsw WARNING: " #define PREFIX_E "al-wdispsw ERROR: " int _win_app_foreground = TRUE; static HANDLE foreground_event = NULL; static int allegro_thread_priority = THREAD_PRIORITY_NORMAL; /* _win_reset_switch_mode: * Resets the switch mode to its default state. */ void _win_reset_switch_mode(void) { /* The default state must be SWITCH_BACKGROUND so that the threads don't get blocked when the focus moves forth and back during window creation and destruction. This seems to be particularly relevant to WinXP. */ set_display_switch_mode(SWITCH_BACKGROUND); _win_app_foreground = TRUE; /* This has a nice side-effect: releasing the blocked threads. */ SetEvent(foreground_event); } /* sys_directx_display_switch_init: */ void sys_directx_display_switch_init(void) { foreground_event = CreateEvent(NULL, TRUE, TRUE, NULL); _win_reset_switch_mode(); } /* sys_directx_display_switch_exit: */ void sys_directx_display_switch_exit(void) { CloseHandle(foreground_event); } /* sys_directx_set_display_switch_mode: */ int sys_directx_set_display_switch_mode(int mode) { switch (mode) { case SWITCH_BACKGROUND: case SWITCH_PAUSE: if (win_gfx_driver && !win_gfx_driver->has_backing_store) return -1; break; case SWITCH_BACKAMNESIA: case SWITCH_AMNESIA: if (!win_gfx_driver || win_gfx_driver->has_backing_store) return -1; break; default: return -1; } return 0; } /* _win_switch_in: * Puts the library in the foreground. */ void _win_switch_in(void) { int mode; _TRACE(PREFIX_I "switch in\n"); _enter_gfx_critical(); _win_app_foreground = TRUE; key_dinput_acquire(); mouse_dinput_acquire(); joystick_dinput_acquire(); if (win_gfx_driver && win_gfx_driver->switch_in) win_gfx_driver->switch_in(); /* handle switch modes */ mode = get_display_switch_mode(); if ((mode == SWITCH_AMNESIA) || (mode == SWITCH_PAUSE)) { _TRACE(PREFIX_I "AMNESIA or PAUSE mode recovery\n"); SetEvent(foreground_event); /* restore old priority and wake up */ SetThreadPriority(allegro_thread, allegro_thread_priority); } _switch_in(); _exit_gfx_critical(); } /* _win_switch_out: * Puts the library in the background. */ void _win_switch_out(void) { int mode; _TRACE(PREFIX_I "switch out\n"); _enter_gfx_critical(); _switch_out(); _win_app_foreground = FALSE; key_dinput_unacquire(); mouse_dinput_unacquire(); joystick_dinput_unacquire(); midi_switch_out(); if (win_gfx_driver && win_gfx_driver->switch_out) win_gfx_driver->switch_out(); /* handle switch modes */ mode = get_display_switch_mode(); if ((mode == SWITCH_AMNESIA) || (mode == SWITCH_PAUSE)) { _TRACE(PREFIX_I "AMNESIA or PAUSE mode suspension\n"); ResetEvent(foreground_event); /* if the thread doesn't stop, lower its priority only if another window is active */ allegro_thread_priority = GetThreadPriority(allegro_thread); if ((HINSTANCE)GetWindowLongPtr(GetForegroundWindow(), GWLP_HINSTANCE) != allegro_inst) SetThreadPriority(allegro_thread, THREAD_PRIORITY_LOWEST); } _exit_gfx_critical(); } /* _win_thread_switch_out: * Handles a switch out event for the calling thread. * Returns TRUE if the thread was blocked, FALSE otherwise. */ int _win_thread_switch_out(void) { int mode = get_display_switch_mode(); if ((mode == SWITCH_AMNESIA) || (mode == SWITCH_PAUSE)) { WaitForSingleObject(foreground_event, INFINITE); return TRUE; } return FALSE; } allegro-4.4.3.1/src/win/wdxver.c0000664000175000017500000002364413437077643015360 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Get version of installed DirectX. * * By Stefan Schimanski. * * Modified get_dx_ver() from DirectX 7 SDK. * * See readme.txt for copyright information. */ /* Set DIRECTX_SDK_VERSION according to the installed SDK version. * Note that this file requires at least the SDK version 5 to compile, * so that DIRECTX_SDK_VERSION must be >= 0x500. */ #define DIRECTX_SDK_VERSION 0x500 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" /* needed by the SDK version 8 with MSVC 5 (SP3) */ #define DIRECTINPUT_VERSION 0x300 #ifndef SCAN_DEPEND #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif typedef HRESULT(WINAPI *DIRECTDRAWCREATE) (GUID *, LPDIRECTDRAW *, IUnknown *); typedef HRESULT(WINAPI *DIRECTINPUTCREATE) (HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *); typedef HRESULT(WINAPI *DSETUPCREATE)(DWORD*,DWORD*); /* get_dx_ver: * returns the DirectX dx_version number: * * 0 no DirectX installed * 0x100 DirectX 1 installed * 0x200 DirectX 2 installed * 0x300 DirectX 3 installed * 0x500 at least DirectX 5 installed * 0x600 at least DirectX 6 installed * 0x700 at least DirectX 7 installed */ int get_dx_ver(void) { HRESULT hr; HINSTANCE ddraw_hinst = NULL; HINSTANCE dinput_hinst = NULL; HINSTANCE dsetup_hinst = NULL; LPDIRECTDRAW directdraw = NULL; LPDIRECTDRAW2 directdraw2 = NULL; DIRECTDRAWCREATE DirectDrawCreate = NULL; DIRECTINPUTCREATE DirectInputCreate = NULL; DSETUPCREATE DSetupCreate = NULL; OSVERSIONINFO os_version; LPDIRECTDRAWSURFACE ddraw_surf = NULL; LPDIRECTDRAWSURFACE3 ddraw_surf3 = NULL; DWORD dsetup_revision; DWORD dsetup_version; INT dsetup_result; #if DIRECTX_SDK_VERSION >= 0x600 LPDIRECTDRAWSURFACE4 ddraw_surf4 = NULL; #if DIRECTX_SDK_VERSION >= 0x700 LPDIRECTDRAWSURFACE7 ddraw_surf7 = NULL; #endif #endif DDSURFACEDESC ddraw_surf_desc; LPVOID temp; int dx_version = 0; /* first get the Windows platform */ os_version.dwOSVersionInfoSize = sizeof(os_version); if (!GetVersionEx(&os_version)) return dx_version; if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT) { /* NT is easy... NT 4.0 is DX2, 4.0 SP3 is DX3, 5.0 is DX5 at least * and no DX on earlier versions */ if (os_version.dwMajorVersion < 4) { /* No DX on NT 3.51 or earlier */ return dx_version; } /* First check for DX 8 and 9 */ dsetup_hinst = LoadLibrary( "DSETUP.DLL" ); if ( dsetup_hinst ) { DSetupCreate = (DSETUPCREATE)GetProcAddress(dsetup_hinst, "DirectXSetupGetVersion"); if ( DSetupCreate ) { dsetup_result = DSetupCreate( &dsetup_version, &dsetup_revision ); // returns 0 on failure if ( dsetup_result ) { switch (dsetup_version) { case 0x00040005: dx_version = 0x500; break; case 0x00040006: dx_version = 0x600; break; case 0x00040007: dx_version = 0x700; break; case 0x00040008: /* v8.x */ dx_version = 0x800; switch (dsetup_revision) { case 0x0001032A: case 0x00010371: dx_version = 0x810; /* 8.1 */ dx_version = 0x810; /* 8.1 */ break; case 0x00010385: dx_version = 0x81a; /* 8.1a or b (stupid MS...) */ break; case 0x00020386: dx_version = 0x820; /* 8.2 */ break; default: dx_version = 0x800; /* 8.0 */ } /* switch (dsetup_revision) */ case 0x00040009: switch (dsetup_revision) { case 0x00000384: dx_version = 0x900; /* 9.0 */ break; case 0x00000385: dx_version = 0x90a; /* 9.0a */ break; case 0x00000386: dx_version = 0x90b; /* 9.0b */ break; case 0x00000387: dx_version = 0x90b; /* 9.0(b or c) */ break; case 0x00000388: dx_version = 0x90c; /* 9.0c */ break; default: dx_version = 0x900; } /* switch (dsetup_revision) */ } /* switch (dsetup_version) */ } } FreeLibrary( dsetup_hinst ); if ( dx_version ) return dx_version; } if (os_version.dwMajorVersion == 4) { /* NT4 up to SP2 is DX2, and SP3 onwards is DX3, so we are at least DX2 */ dx_version = 0x200; /* we are not supposed to be able to tell which SP we are on, so check for DInput */ dinput_hinst = LoadLibrary("DINPUT.DLL"); if (!dinput_hinst) { /* no DInput... must be DX2 on NT 4 pre-SP3 */ OutputDebugString("Couldn't LoadLibrary DInput\r\n"); return dx_version; } DirectInputCreate = (DIRECTINPUTCREATE) GetProcAddress(dinput_hinst, "DirectInputCreateA"); FreeLibrary(dinput_hinst); if (!DirectInputCreate) { /* no DInput... must DX2 on NT 4 pre-SP3 */ return dx_version; } /* DX3 on NT4 SP3 or higher */ dx_version = 0x300; return dx_version; } /* it's at least NT 5 and it's DX5a or higher: * drop through to Win9x tests for a test of DDraw */ } /* now we know we are in Windows 9x (or maybe 3.1), so anything's possible; * first see if DDRAW.DLL even exists. */ ddraw_hinst = LoadLibrary("DDRAW.DLL"); if (!ddraw_hinst) { dx_version = 0; goto End; } /* see if we can create the DirectDraw object */ DirectDrawCreate = (DIRECTDRAWCREATE) GetProcAddress(ddraw_hinst, "DirectDrawCreate"); if (!DirectDrawCreate) { dx_version = 0; goto End; } hr = DirectDrawCreate(NULL, &directdraw, NULL); if (FAILED(hr)) { dx_version = 0; goto End; } /* so DirectDraw exists, we are at least DX1 */ dx_version = 0x100; /* let's see if IDirectDraw2 exists */ hr = IDirectDraw_QueryInterface(directdraw, &IID_IDirectDraw2, &temp); if (FAILED(hr)) { /* no IDirectDraw2 exists... must be DX1 */ goto End; } directdraw2 = temp; /* IDirectDraw2 exists... must be at least DX2 */ IDirectDraw2_Release(directdraw2); dx_version = 0x200; /* see if we can create the DirectInput object */ dinput_hinst = LoadLibrary("DINPUT.DLL"); if (!dinput_hinst) { /* no DInput... must be DX2 */ goto End; } DirectInputCreate = (DIRECTINPUTCREATE) GetProcAddress(dinput_hinst, "DirectInputCreateA"); FreeLibrary(dinput_hinst); if (!DirectInputCreate) { /* no DInput... must be DX2 */ goto End; } /* DirectInputCreate exists; that's enough to tell us that we are at least DX3 */ dx_version = 0x300; /* we can tell if DX5 is present by checking for the existence of IDirectDrawSurface3; * first we need a surface to QI off of */ memset(&ddraw_surf_desc, 0, sizeof(ddraw_surf_desc)); ddraw_surf_desc.dwSize = sizeof(ddraw_surf_desc); ddraw_surf_desc.dwFlags = DDSD_CAPS; ddraw_surf_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; hr = IDirectDraw_SetCooperativeLevel(directdraw, NULL, DDSCL_NORMAL); if (FAILED(hr)) { /* failure: this means DDraw isn't properly installed */ dx_version = 0; goto End; } hr = IDirectDraw_CreateSurface(directdraw, &ddraw_surf_desc, &ddraw_surf, NULL); if (FAILED(hr)) { /* failure: this means DDraw isn't properly installed */ dx_version = 0; goto End; } /* try for the IDirectDrawSurface3 interface; if it works, we're on DX5 at least */ hr = IDirectDrawSurface_QueryInterface(ddraw_surf, &IID_IDirectDrawSurface3, &temp); if (FAILED(hr)) goto End; ddraw_surf3 = temp; /* QI for IDirectDrawSurface3 succeeded; we must be at least DX5 */ dx_version = 0x500; #if DIRECTX_SDK_VERSION >= 0x600 /* try for the IDirectDrawSurface4 interface; if it works, we're on DX6 at least */ hr = IDirectDrawSurface_QueryInterface(ddraw_surf, &IID_IDirectDrawSurface4, (LPVOID *) &ddraw_surf4); if (FAILED(hr)) goto End; /* QI for IDirectDrawSurface4 succeeded; we must be at least DX6 */ dx_version = 0x600; #if DIRECTX_SDK_VERSION >= 0x700 /* try for the IDirectDrawSurface7 interface; if it works, we're on DX7 at least */ hr = IDirectDrawSurface_QueryInterface(ddraw_surf, &IID_IDirectDrawSurface7, (LPVOID *) &ddraw_surf7); if (FAILED(hr)) goto End; /* QI for IDirectDrawSurface7 succeeded; we must be at least DX7 */ dx_version = 0x700; #endif #endif End: if (directdraw) IDirectDraw_Release(directdraw); if (ddraw_hinst) FreeLibrary(ddraw_hinst); return dx_version; } allegro-4.4.3.1/src/win/wkeybd.c0000664000175000017500000005460113437077643015323 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows keyboard driver. * * By Stefan Schimanski, hacked up by Peter Wang and Elias Pschernig. * * See readme.txt for copyright information. */ #define DIRECTINPUT_VERSION 0x0300 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wkey INFO: " #define PREFIX_W "al-wkey WARNING: " #define PREFIX_E "al-wkey ERROR: " #define DINPUT_BUFFERSIZE 256 static HANDLE key_input_event = NULL; static HANDLE key_input_processed_event = NULL; static LPDIRECTINPUT key_dinput = NULL; static LPDIRECTINPUTDEVICE key_dinput_device = NULL; /* lookup table for converting DIK_* scancodes into Allegro KEY_* codes */ /* this table was from pckeys.c */ static const unsigned char hw_to_mycode[256] = { /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R, /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I, /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S, /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH, /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK, /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD, /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD, /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD, /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD, /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, /* 0x60 */ 0, 0, 0, 0, /* 0x64 */ 0, 0, 0, 0, /* 0x68 */ 0, 0, 0, 0, /* 0x6C */ 0, 0, 0, 0, /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1, /* 0x74 */ 0, 0, 0, 0, /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT, /* 0x7C */ 0, KEY_YEN, 0, 0, /* 0x80 */ 0, 0, 0, 0, /* 0x84 */ 0, 0, 0, 0, /* 0x88 */ 0, 0, 0, 0, /* 0x8C */ 0, 0, 0, 0, /* 0x90 */ 0, KEY_AT, KEY_COLON2, 0, /* 0x94 */ KEY_KANJI, 0, 0, 0, /* 0x98 */ 0, 0, 0, 0, /* 0x9C */ KEY_ENTER_PAD, KEY_RCONTROL, 0, 0, /* 0xA0 */ 0, 0, 0, 0, /* 0xA4 */ 0, 0, 0, 0, /* 0xA8 */ 0, 0, 0, 0, /* 0xAC */ 0, 0, 0, 0, /* 0xB0 */ 0, 0, 0, 0, /* 0xB4 */ 0, KEY_SLASH_PAD, 0, KEY_PRTSCR, /* 0xB8 */ KEY_ALTGR, 0, 0, 0, /* 0xBC */ 0, 0, 0, 0, /* 0xC0 */ 0, 0, 0, 0, /* 0xC4 */ 0, KEY_PAUSE, 0, KEY_HOME, /* 0xC8 */ KEY_UP, KEY_PGUP, 0, KEY_LEFT, /* 0xCC */ 0, KEY_RIGHT, 0, KEY_END, /* 0xD0 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL, /* 0xD4 */ 0, 0, 0, 0, /* 0xD8 */ 0, 0, 0, KEY_LWIN, /* 0xDC */ KEY_RWIN, KEY_MENU, 0, 0, /* 0xE0 */ 0, 0, 0, 0, /* 0xE4 */ 0, 0, 0, 0, /* 0xE8 */ 0, 0, 0, 0, /* 0xEC */ 0, 0, 0, 0, /* 0xF0 */ 0, 0, 0, 0, /* 0xF4 */ 0, 0, 0, 0, /* 0xF8 */ 0, 0, 0, 0, /* 0xFC */ 0, 0, 0, 0 }; /* Used in scancode_to_name. */ static LONG reverse_mapping[KEY_MAX]; /* dinput_err_str: * Returns a DirectInput error string. */ #ifdef DEBUGMODE static char* dinput_err_str(long err) { static char err_str[64]; switch (err) { case DIERR_NOTACQUIRED: _al_sane_strncpy(err_str, "the device is not acquired", sizeof(err_str)); break; case DIERR_INPUTLOST: _al_sane_strncpy(err_str, "access to the device was lost", sizeof(err_str)); break; case DIERR_INVALIDPARAM: _al_sane_strncpy(err_str, "the device does not have a selected data format", sizeof(err_str)); break; #ifdef DIERR_OTHERAPPHASPRIO /* this is not a legacy DirectX 3 error code */ case DIERR_OTHERAPPHASPRIO: _al_sane_strncpy(err_str, "can't acquire the device in background", sizeof(err_str)); break; #endif default: _al_sane_strncpy(err_str, "unknown error", sizeof(err_str)); } return err_str; } #else #define dinput_err_str(hr) "\0" #endif /* Update the key_shifts. */ static void update_shifts(BYTE * keystate) { /* TODO: There must be a more efficient way to maintain key_modifiers? */ /* Can't we just deprecate key_shifts, now that pckeys.c is gone? EP */ unsigned int modifiers = 0; if (GetAsyncKeyState(VK_SHIFT) & 0x8000) modifiers |= KB_SHIFT_FLAG; if (GetAsyncKeyState(VK_CONTROL) & 0x8000) modifiers |= KB_CTRL_FLAG; if (GetAsyncKeyState(VK_MENU) & 0x8000) modifiers |= KB_ALT_FLAG; if (keystate[VK_SCROLL] & 1) modifiers |= KB_SCROLOCK_FLAG; if (keystate[VK_NUMLOCK] & 1) modifiers |= KB_NUMLOCK_FLAG; if (keystate[VK_CAPITAL] & 1) modifiers |= KB_CAPSLOCK_FLAG; _key_shifts = modifiers; } /* handle_key_press: [input thread] * Does stuff when a key is pressed. */ static void handle_key_press(unsigned char scancode) { int mycode; int unicode; int n; UINT vkey; BYTE keystate[256]; WCHAR chars[16]; vkey = MapVirtualKey(scancode, 1); GetKeyboardState(keystate); update_shifts(keystate); /* TODO: shouldn't we base the mapping on vkey? */ mycode = hw_to_mycode[scancode]; if (mycode == 0) return; /* MapVirtualKey always returns the arrow key VKEY, so adjust it if num lock is on */ if (keystate[VK_NUMLOCK]) { switch (scancode) { case DIK_NUMPAD0: vkey = VK_NUMPAD0; break; case DIK_NUMPAD1: vkey = VK_NUMPAD1; break; case DIK_NUMPAD2: vkey = VK_NUMPAD2; break; case DIK_NUMPAD3: vkey = VK_NUMPAD3; break; case DIK_NUMPAD4: vkey = VK_NUMPAD4; break; case DIK_NUMPAD5: vkey = VK_NUMPAD5; break; case DIK_NUMPAD6: vkey = VK_NUMPAD6; break; case DIK_NUMPAD7: vkey = VK_NUMPAD7; break; case DIK_NUMPAD8: vkey = VK_NUMPAD8; break; case DIK_NUMPAD9: vkey = VK_NUMPAD9; break; case DIK_DECIMAL: vkey = VK_DECIMAL; break; } } /* what's life without a few special cases */ switch (scancode) { case DIK_DIVIDE: vkey = VK_DIVIDE; break; case DIK_MULTIPLY: vkey = VK_MULTIPLY; break; case DIK_SUBTRACT: vkey = VK_SUBTRACT; break; case DIK_ADD: vkey = VK_ADD; break; case DIK_NUMPADENTER: vkey = VK_RETURN; } /* TODO: is there an advantage using ToUnicode? maybe it would allow * Chinese and so on characters? For now, always ToAscii is used. */ //n = ToUnicode(vkey, scancode, keystate, chars, 16, 0); n = ToAscii(vkey, scancode, keystate, (WORD *)chars, 0); if (n == 1) { WCHAR wstr[2]; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)chars, n, wstr, 2); unicode = wstr[0]; } else { /* Don't generate key presses for modifier keys or dead keys */ if (mycode >= KEY_MODIFIERS || n != 0) unicode = -1; else unicode = 0; } /* When alt key is pressed, any key always must return ASCII 0 in Allegro. */ if (unicode > 0 && (keystate[VK_LMENU] & 0x80)) { unicode = 0; } _handle_key_press(unicode, mycode); } /* handle_key_release: [input thread] * Does stuff when a key is released. The keyboard event source * should be locked. */ static void handle_key_release(unsigned char scancode) { int mycode = hw_to_mycode[scancode]; if (mycode == 0) return; { BYTE keystate[256]; GetKeyboardState(keystate); update_shifts(keystate); } _handle_key_release(mycode); } /* key_dinput_handle_scancode: [input thread] * Handles a single scancode. */ static void key_dinput_handle_scancode(unsigned char scancode, int pressed) { HWND allegro_wnd = win_get_window(); static int ignore_three_finger_flag = FALSE; /* ignore special Windows keys (alt+tab, alt+space, (ctrl|alt)+esc) */ if (((scancode == DIK_TAB) && (_key_shifts & KB_ALT_FLAG)) || ((scancode == DIK_SPACE) && (_key_shifts & KB_ALT_FLAG)) || ((scancode == DIK_ESCAPE) && (_key_shifts & (KB_CTRL_FLAG | KB_ALT_FLAG)))) { /* force key release to make sure it does not get 'stuck' if held before ALT */ if (key[hw_to_mycode[scancode]]) handle_key_release(scancode); return; } /* alt+F4 triggers a WM_CLOSE under Windows */ if ((scancode == DIK_F4) && (_key_shifts & KB_ALT_FLAG)) { if (pressed) PostMessage(allegro_wnd, WM_CLOSE, 0, 0); return; } /* Special case KEY_PAUSE as flip-flop key. */ if (scancode == DIK_PAUSE) { if (!pressed) return; if (key[KEY_PAUSE]) pressed = 0; else pressed = 1; } /* if not foreground, filter out press codes and handle only release codes */ if (!wnd_sysmenu || !pressed) { /* three-finger salute for killing the program */ if (three_finger_flag && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG)) { if (scancode == 0x00) { /* when pressing CTRL-ALT-DEL, Windows launches CTRL-ALT-EVERYTHING */ ignore_three_finger_flag = TRUE; } else if (!ignore_three_finger_flag && (scancode == DIK_END || scancode == DIK_NUMPAD1)) { /* we can now safely assume the user hit CTRL-ALT-END as opposed to CTRL-ALT-DEL */ _TRACE(PREFIX_I "Terminating application\n"); abort(); } else if (ignore_three_finger_flag && scancode == 0xff) { /* Windows is finished with CTRL-ALT-EVERYTHING - lets return to normality */ ignore_three_finger_flag = FALSE; _key_shifts = 0; } } if (pressed) handle_key_press(scancode); else handle_key_release(scancode); } } /* key_dinput_handle: [input thread] * Handles queued keyboard input. */ static void key_dinput_handle(void) { static DIDEVICEOBJECTDATA scancode_buffer[DINPUT_BUFFERSIZE]; unsigned long int waiting_scancodes; HRESULT hr; unsigned long int i; /* the whole buffer is free */ waiting_scancodes = DINPUT_BUFFERSIZE; /* fill the buffer */ hr = IDirectInputDevice_GetDeviceData(key_dinput_device, sizeof(DIDEVICEOBJECTDATA), scancode_buffer, &waiting_scancodes, 0); /* was device lost ? */ if ((hr == DIERR_NOTACQUIRED) || (hr == DIERR_INPUTLOST)) { /* reacquire device */ _TRACE(PREFIX_W "keyboard device not acquired or lost\n"); wnd_schedule_proc(key_dinput_acquire); } else if (FAILED(hr)) { /* other error? */ _TRACE(PREFIX_E "unexpected error while filling keyboard scancode buffer\n"); } else { /* normally only this case should happen */ for (i = 0; i < waiting_scancodes; i++) { key_dinput_handle_scancode((unsigned char) scancode_buffer[i].dwOfs, scancode_buffer[i].dwData & 0x80); } } SetEvent(key_input_processed_event); } /* key_dinput_acquire: [window thread] * Acquires the keyboard device. This must be called after a * window switch for example if the device is in foreground * cooperative level. */ int key_dinput_acquire(void) { HRESULT hr; BYTE keystate[256]; if (key_dinput_device) { /* Read the current Windows keyboard state */ GetKeyboardState(keystate); update_shifts(keystate); hr = IDirectInputDevice_Acquire(key_dinput_device); if (FAILED(hr)) { _TRACE(PREFIX_E "acquire keyboard failed: %s\n", dinput_err_str(hr)); return -1; } /* Initialize keyboard state */ SetEvent(key_input_event); return 0; } else return -1; } /* key_dinput_unacquire: [window thread] * Unacquires the keyboard device. */ int key_dinput_unacquire(void) { int key; if (key_dinput_device) { IDirectInputDevice_Unacquire(key_dinput_device); /* release all keys */ for (key=0; key<256; key++) if (key != KEY_PAUSE) key_dinput_handle_scancode((unsigned char) key, FALSE); return 0; } else return -1; } /* key_dinput_exit: [primary thread] * Shuts down the DirectInput keyboard device. */ static int key_dinput_exit(void) { if (key_dinput_device) { /* unregister event handler first */ _win_input_unregister_event(key_input_event); /* unacquire device */ wnd_call_proc(key_dinput_unacquire); /* now it can be released */ IDirectInputDevice_Release(key_dinput_device); key_dinput_device = NULL; } /* release DirectInput interface */ if (key_dinput) { IDirectInput_Release(key_dinput); key_dinput = NULL; } /* close event handle */ if (key_input_event) { CloseHandle(key_input_event); key_input_event = NULL; } return 0; } /* get_reverse_mapping: * Build a table that maps Allegro "scancodes" to arguments to * GetKeyNameText() that will return the name of the key. * The format of the argument is given in the MSDN library, e.g. the * `lparam' argument for the WM_KEYDOWN message. Most importantly: * bits 16-23: * Specifies the scan code. * bit 24: * Specifies whether the key is an extended key, such as the right-hand * ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. * The value is 1 if it is an extended key; otherwise, it is 0. * * We used to attempt to derive this table from `hw_to_mycode' but it is not * straight forward. For example to get the name of the right Ctrl key we * need to pass the same scancode as for the left Ctrl key, but with the * extended key flag set. The values below come from printing out the * value of the `lparam' argument for each WM_KEYDOWN message received. * There is code in wwnd.c to help someone else do this for more keys. */ static void get_reverse_mapping(void) { #define REV reverse_mapping REV[KEY_A] = 0x01E0000; REV[KEY_B] = 0x0300000; REV[KEY_C] = 0x02E0000; REV[KEY_D] = 0x0200000; REV[KEY_E] = 0x0120000; REV[KEY_F] = 0x0210000; REV[KEY_G] = 0x0220000; REV[KEY_H] = 0x0230000; REV[KEY_I] = 0x0170000; REV[KEY_J] = 0x0240000; REV[KEY_K] = 0x0250000; REV[KEY_L] = 0x0260000; REV[KEY_M] = 0x0320000; REV[KEY_N] = 0x0310000; REV[KEY_O] = 0x0180000; REV[KEY_P] = 0x0190000; REV[KEY_Q] = 0x0100000; REV[KEY_R] = 0x0130000; REV[KEY_S] = 0x01F0000; REV[KEY_T] = 0x0140000; REV[KEY_U] = 0x0160000; REV[KEY_V] = 0x02F0000; REV[KEY_W] = 0x0110000; REV[KEY_X] = 0x02D0000; REV[KEY_Y] = 0x0150000; REV[KEY_Z] = 0x02C0000; REV[KEY_0] = 0x00B0000; REV[KEY_1] = 0x0020000; REV[KEY_2] = 0x0030000; REV[KEY_3] = 0x0040000; REV[KEY_4] = 0x0050000; REV[KEY_5] = 0x0060000; REV[KEY_6] = 0x0070000; REV[KEY_7] = 0x0080000; REV[KEY_8] = 0x0090000; REV[KEY_9] = 0x00A0000; REV[KEY_0_PAD] = 0x0520000; REV[KEY_1_PAD] = 0x04F0000; REV[KEY_2_PAD] = 0x0500000; REV[KEY_3_PAD] = 0x0510000; REV[KEY_4_PAD] = 0x04B0000; REV[KEY_5_PAD] = 0x04C0000; REV[KEY_6_PAD] = 0x04D0000; REV[KEY_7_PAD] = 0x0470000; REV[KEY_8_PAD] = 0x0480000; REV[KEY_9_PAD] = 0x0490000; REV[KEY_F1] = 0x03B0000; REV[KEY_F2] = 0x03C0000; REV[KEY_F3] = 0x03D0000; REV[KEY_F4] = 0x03E0000; REV[KEY_F5] = 0x03F0000; REV[KEY_F6] = 0x0400000; REV[KEY_F7] = 0x0410000; REV[KEY_F8] = 0x0420000; REV[KEY_F9] = 0x0430000; REV[KEY_F10] = 0x0440000; REV[KEY_F11] = 0x0570000; REV[KEY_F12] = 0x0580000; REV[KEY_ESC] = 0x0010000; REV[KEY_TILDE] = 0x0290000; REV[KEY_MINUS] = 0x00C0000; REV[KEY_EQUALS] = 0x00D0000; REV[KEY_BACKSPACE] = 0x00E0000; REV[KEY_TAB] = 0x00F0000; REV[KEY_OPENBRACE] = 0x01A0000; REV[KEY_CLOSEBRACE] = 0x01B0000; REV[KEY_ENTER] = 0x01C0000; REV[KEY_COLON] = 0x0270000; REV[KEY_QUOTE] = 0x0280000; REV[KEY_BACKSLASH] = 0x02B0000; /* KEY_BACKSLASH2 */ REV[KEY_COMMA] = 0x0330000; REV[KEY_STOP] = 0x0340000; REV[KEY_SLASH] = 0x0350000; REV[KEY_SPACE] = 0x0390000; REV[KEY_INSERT] = 0x1520000; REV[KEY_DEL] = 0x1530000; REV[KEY_HOME] = 0x1470000; REV[KEY_END] = 0x14F0000; REV[KEY_PGUP] = 0x1490000; REV[KEY_PGDN] = 0x1510000; REV[KEY_LEFT] = 0x14B0000; REV[KEY_RIGHT] = 0x14D0000; REV[KEY_UP] = 0x1480000; REV[KEY_DOWN] = 0x1500000; REV[KEY_SLASH_PAD] = 0x1350000; REV[KEY_ASTERISK] = 0x0370000; REV[KEY_MINUS_PAD] = 0x04A0000; REV[KEY_PLUS_PAD] = 0x04E0000; REV[KEY_DEL_PAD] = 0x0530000; REV[KEY_ENTER_PAD] = 0x11C0000; /* XXX doesn't work REV[KEY_PRTSCR] = 0x570000; */ REV[KEY_PAUSE] = 0x0450000; /* XXX Japanese keys missing REV[KEY_ABNT_C1] = REV[KEY_YEN] = REV[KEY_KANA] = REV[KEY_CONVERT] = REV[KEY_NOCONVERT] = REV[KEY_AT] = REV[KEY_CIRCUMFLEX] = REV[KEY_COLON2] = REV[KEY_KANJI] = */ REV[KEY_LSHIFT] = 0x02A0000; REV[KEY_RSHIFT] = 0x0360000; REV[KEY_LCONTROL] = 0x01D0000; REV[KEY_RCONTROL] = 0x11D0000; REV[KEY_ALT] = 0x0380000; REV[KEY_ALTGR] = 0x1380000; REV[KEY_LWIN] = 0x15B0000; REV[KEY_RWIN] = 0x15C0000; REV[KEY_MENU] = 0x15D0000; REV[KEY_SCRLOCK] = 0x0460000; REV[KEY_NUMLOCK] = 0x1450000; REV[KEY_CAPSLOCK] = 0x03A0000; #undef REV } /* key_dinput_init: [primary thread] * Sets up the DirectInput keyboard device. */ static int key_dinput_init(void) { HRESULT hr; HWND allegro_wnd = win_get_window(); DIPROPDWORD property_buf_size = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ DINPUT_BUFFERSIZE, // dwData }; /* Get DirectInput interface */ hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput, (void**)&key_dinput); if (FAILED(hr)) goto Error; hr = IDirectInput_Initialize(key_dinput, allegro_inst, DIRECTINPUT_VERSION); if (FAILED(hr)) goto Error; /* Create the keyboard device */ hr = IDirectInput_CreateDevice(key_dinput, &GUID_SysKeyboardEm2, &key_dinput_device, NULL); if (FAILED(hr)) goto Error; /* Set data format */ hr = IDirectInputDevice_SetDataFormat(key_dinput_device, &c_dfDIKeyboard); if (FAILED(hr)) goto Error; /* Set buffer size */ hr = IDirectInputDevice_SetProperty(key_dinput_device, DIPROP_BUFFERSIZE, &property_buf_size.diph); if (FAILED(hr)) goto Error; /* Set cooperative level */ hr = IDirectInputDevice_SetCooperativeLevel(key_dinput_device, allegro_wnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if (FAILED(hr)) goto Error; /* Enable event notification */ key_input_event = CreateEvent(NULL, FALSE, FALSE, NULL); hr = IDirectInputDevice_SetEventNotification(key_dinput_device, key_input_event); if (FAILED(hr)) goto Error; /* Register event handler */ if (_win_input_register_event(key_input_event, key_dinput_handle) != 0) goto Error; get_reverse_mapping(); /* Acquire the device */ wnd_call_proc(key_dinput_acquire); return 0; Error: key_dinput_exit(); return -1; } /* key_directx_init: [primary thread] */ static int key_directx_init(void) { /* keyboard input is handled by the window thread */ key_input_processed_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (key_dinput_init() != 0) { /* something has gone wrong */ _TRACE(PREFIX_E "keyboard handler init failed\n"); CloseHandle(key_input_processed_event); return -1; } /* the keyboard handler has successfully set up */ _TRACE(PREFIX_I "keyboard handler starts\n"); return 0; } /* key_directx_exit: [primary thread] */ static void key_directx_exit(void) { if (key_dinput_device) { /* command keyboard handler shutdown */ _TRACE(PREFIX_I "keyboard handler exits\n"); key_dinput_exit(); /* now we can free all resources */ CloseHandle(key_input_processed_event); } } /* key_directx_wait_for_input: [primary thread] */ static void key_directx_wait_for_input(void) { WaitForSingleObject(key_input_processed_event, INFINITE); } /* static void key_directx_stop_wait: [primary thread] */ static void key_directx_stop_wait(void) { SetEvent(key_input_processed_event); } /* scancode_to_name: * Converts the given scancode to a description of the key. */ static AL_CONST char *key_directx_scancode_to_name(const int scancode) { static char name[256]; TCHAR str[256]; WCHAR wstr[256]; ASSERT(scancode >= 0 && scancode < KEY_MAX); if (GetKeyNameText(reverse_mapping[scancode], str, sizeof str)) { /* let Windows translate from the current encoding into UTF16 */ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr); /* translate from utf16 to Allegro's current encoding */ uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name); /* why oh why doesn't everybody just use UTF8/16 */ return name; } else return _keyboard_common_names[scancode]; } static KEYBOARD_DRIVER keyboard_directx = { KEYBOARD_DIRECTX, 0, 0, "DirectInput keyboard", 1, key_directx_init, key_directx_exit, NULL, NULL, NULL, key_directx_wait_for_input, key_directx_stop_wait, NULL, key_directx_scancode_to_name }; _DRIVER_INFO _keyboard_driver_list[] = { {KEYBOARD_DIRECTX, &keyboard_directx, TRUE}, {0, NULL, 0} }; allegro-4.4.3.1/src/win/wdsound.c0000664000175000017500000010552513437077643015523 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectSound sound driver. * * By Stefan Schimanski. * * Various bugfixes by Patrick Hogan. * * Custom loop points support added by Eric Botcazou. * * Backward playing support, bidirectional looping support * and bugfixes by Javier Gonzalez. * * See readme.txt for copyright information. */ #define DIRECTSOUND_VERSION 0x0300 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #include #ifdef ALLEGRO_MSVC #include #endif #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-dsound INFO: " #define PREFIX_W "al-dsound WARNING: " #define PREFIX_E "al-dsound ERROR: " static int digi_directsound_detect(int input); static int digi_directsound_init(int input, int voices); static void digi_directsound_exit(int input); static int digi_directsound_set_mixer_volume(int volume); static int digi_directsound_get_mixer_volume(void); static void digi_directsound_init_voice(int voice, AL_CONST SAMPLE * sample); static void digi_directsound_release_voice(int voice); static void digi_directsound_start_voice(int voice); static void digi_directsound_stop_voice(int voice); static void digi_directsound_loop_voice(int voice, int playmode); static void *digi_directsound_lock_voice(int voice, int start, int end); static void digi_directsound_unlock_voice(int voice); static int digi_directsound_get_position(int voice); static void digi_directsound_set_position(int voice, int position); static int digi_directsound_get_volume(int voice); static void digi_directsound_set_volume(int voice, int volume); static int digi_directsound_get_frequency(int voice); static void digi_directsound_set_frequency(int voice, int frequency); static int digi_directsound_get_pan(int voice); static void digi_directsound_set_pan(int voice, int pan); /* template driver: will be cloned for each device */ static DIGI_DRIVER digi_directsound = { 0, empty_string, empty_string, empty_string, 0, // available voices 0, // voice number offset 16, // maximum voices we can support 4, // default number of voices to use /* setup routines */ digi_directsound_detect, digi_directsound_init, digi_directsound_exit, digi_directsound_set_mixer_volume, digi_directsound_get_mixer_volume, /* audiostream locking functions */ digi_directsound_lock_voice, digi_directsound_unlock_voice, NULL, // AL_METHOD(int, buffer_size, (void)); /* voice control functions */ digi_directsound_init_voice, digi_directsound_release_voice, digi_directsound_start_voice, digi_directsound_stop_voice, digi_directsound_loop_voice, /* position control functions */ digi_directsound_get_position, digi_directsound_set_position, /* volume control functions */ digi_directsound_get_volume, digi_directsound_set_volume, NULL, // AL_METHOD(void, ramp_volume, (int voice, int time, int endvol)); NULL, // AL_METHOD(void, stop_volume_ramp, (int voice)); /* pitch control functions */ digi_directsound_get_frequency, digi_directsound_set_frequency, NULL, // AL_METHOD(void, sweep_frequency, (int voice, int time, int endfreq)); NULL, // AL_METHOD(void, stop_frequency_sweep, (int voice)); /* pan control functions */ digi_directsound_get_pan, digi_directsound_set_pan, NULL, // AL_METHOD(void, sweep_pan, (int voice, int time, int endpan)); NULL, // AL_METHOD(void, stop_pan_sweep, (int voice)); /* effect control functions */ NULL, // AL_METHOD(void, set_echo, (int voice, int strength, int delay)); NULL, // AL_METHOD(void, set_tremolo, (int voice, int rate, int depth)); NULL, // AL_METHOD(void, set_vibrato, (int voice, int rate, int depth)); /* input functions */ 0, /* int rec_cap_bits; */ 0, /* int rec_cap_stereo; */ digi_directsound_rec_cap_rate, digi_directsound_rec_cap_param, digi_directsound_rec_source, digi_directsound_rec_start, digi_directsound_rec_stop, digi_directsound_rec_read }; /* sound driver globals */ static LPDIRECTSOUND directsound = NULL; static LPDIRECTSOUNDBUFFER prim_buf = NULL; static long int initial_volume; static int _freq, _bits, _stereo; static int alleg_to_dsound_volume[256]; static int alleg_to_dsound_pan[256]; /* internal driver representation of a voice */ struct DIRECTSOUND_VOICE { int bits; int bytes_per_sample; int freq, pan, vol; int stereo; int reversed; int bidir; int len; unsigned char *data; int loop_offset; int loop_len; int looping; void *lock_buf_a; long lock_size_a; LPDIRECTSOUNDBUFFER ds_buffer; LPDIRECTSOUNDBUFFER ds_loop_buffer; LPDIRECTSOUNDBUFFER ds_locked_buffer; }; static struct DIRECTSOUND_VOICE *ds_voices; /* dynamically generated driver list */ static _DRIVER_INFO *driver_list = NULL; #define MAX_DRIVERS 16 static int num_drivers = 0; static char *driver_names[MAX_DRIVERS]; static LPGUID driver_guids[MAX_DRIVERS]; /* DSEnumCallback: * Callback function for enumerating the available DirectSound drivers. */ static BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) { if (lpGuid) { driver_guids[num_drivers] = lpGuid; driver_names[num_drivers] = _AL_MALLOC_ATOMIC(strlen(lpcstrDescription)+1); if(driver_names[num_drivers]) { _al_sane_strncpy(driver_names[num_drivers], lpcstrDescription, strlen(lpcstrDescription)+1); num_drivers++; } } return (num_drivers < MAX_DRIVERS); } /* _get_win_digi_driver_list: * System driver hook for listing the available sound drivers. This * generates the device list at runtime, to match whatever DirectSound * devices are available. */ _DRIVER_INFO *_get_win_digi_driver_list(void) { DIGI_DRIVER *driver; HRESULT hr; int i; if (!driver_list) { driver_list = _create_driver_list(); /* enumerate the DirectSound drivers */ hr = DirectSoundEnumerate(DSEnumCallback, NULL); if (hr == DS_OK) { /* Allegro mixer to DirectSound drivers */ for (i=0; iid, driver, TRUE); } /* pure DirectSound drivers */ for (i=0; iid = DIGI_DIRECTX(i); driver->ascii_name = driver_names[i]; _driver_list_append_driver(&driver_list, driver->id, driver, TRUE); } } /* Allegro mixer to WaveOut drivers */ for (i=0; i<2; i++) { driver = _get_woalmix_driver(i); _driver_list_append_driver(&driver_list, driver->id, driver, TRUE); } } return driver_list; } /* _free_win_digi_driver_list: * Helper function for freeing the dynamically generated driver list. */ void _free_win_digi_driver_list(void) { int i = 0; if (driver_list) { while (driver_list[i].driver) { _AL_FREE(driver_list[i].driver); i++; } _destroy_driver_list(driver_list); driver_list = NULL; } for (i = 0; i < num_drivers; i++) { _AL_FREE(driver_names[i]); } _free_win_dsalmix_name_list(); } /* ds_err: * Returns a DirectSound error string. */ #ifdef DEBUGMODE static char *ds_err(long err) { static char err_str[64]; switch (err) { case DS_OK: _al_sane_strncpy(err_str, "DS_OK", sizeof(err_str)); break; case DSERR_ALLOCATED: _al_sane_strncpy(err_str, "DSERR_ALLOCATED", sizeof(err_str)); break; case DSERR_BADFORMAT: _al_sane_strncpy(err_str, "DSERR_BADFORMAT", sizeof(err_str)); break; case DSERR_INVALIDPARAM: _al_sane_strncpy(err_str, "DSERR_INVALIDPARAM", sizeof(err_str)); break; case DSERR_NOAGGREGATION: _al_sane_strncpy(err_str, "DSERR_NOAGGREGATION", sizeof(err_str)); break; case DSERR_OUTOFMEMORY: _al_sane_strncpy(err_str, "DSERR_OUTOFMEMORY", sizeof(err_str)); break; case DSERR_UNINITIALIZED: _al_sane_strncpy(err_str, "DSERR_UNINITIALIZED", sizeof(err_str)); break; case DSERR_UNSUPPORTED: _al_sane_strncpy(err_str, "DSERR_UNSUPPORTED", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "DSERR_UNKNOWN", sizeof(err_str)); break; } return err_str; } #else #define ds_err(hr) "\0" #endif /* digi_directsound_detect: */ static int digi_directsound_detect(int input) { HRESULT hr; int id; /* deduce our device number from the driver ID code */ id = ((digi_driver->id >> 8) & 0xFF) - 'A'; if (input) return digi_directsound_capture_detect(driver_guids[id]); if (!directsound) { /* initialize DirectSound interface */ hr = DirectSoundCreate(driver_guids[id], &directsound, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "DirectSound interface creation failed during detect (%s).\n", ds_err(hr)); return 0; } _TRACE(PREFIX_I "DirectSound interface successfully created.\n"); /* release DirectSound interface */ IDirectSound_Release(directsound); directsound = NULL; } return 1; } /* digi_directsound_init: */ static int digi_directsound_init(int input, int voices) { HRESULT hr; DSCAPS dscaps; DSBUFFERDESC desc; WAVEFORMATEX format; int v, id; HWND allegro_wnd = win_get_window(); /* deduce our device number from the driver ID code */ id = ((digi_driver->id >> 8) & 0xFF) - 'A'; if (input) return digi_directsound_capture_init(driver_guids[id]); digi_driver->voices = voices; /* initialize DirectSound interface */ hr = DirectSoundCreate(driver_guids[id], &directsound, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't create DirectSound interface (%s).\n", ds_err(hr)); goto Error; } /* set cooperative level */ hr = IDirectSound_SetCooperativeLevel(directsound, allegro_wnd, DSSCL_PRIORITY); if (FAILED(hr)) _TRACE(PREFIX_W "Can't set DirectSound cooperative level (%s).\n", ds_err(hr)); else _TRACE(PREFIX_I "DirectSound cooperation level set to PRIORITY.\n"); /* get hardware capabilities */ dscaps.dwSize = sizeof(DSCAPS); hr = IDirectSound_GetCaps(directsound, &dscaps); if (FAILED(hr)) { _TRACE(PREFIX_E "Can't get DirectSound caps (%s).\n", ds_err(hr)); goto Error; } /* For some reason the audio driver on my machine doesn't seem to set either * PRIMARY16BIT or PRIMARY8BIT; of course it actually does support 16-bit * sound. */ if (((dscaps.dwFlags & DSCAPS_PRIMARY16BIT) || !(dscaps.dwFlags & DSCAPS_PRIMARY8BIT)) && ((_sound_bits >= 16) || (_sound_bits <= 0))) _bits = 16; else _bits = 8; if ((dscaps.dwFlags & DSCAPS_PRIMARYSTEREO) && _sound_stereo) _stereo = 1; else _stereo = 0; if ((dscaps.dwMaxSecondarySampleRate > (DWORD)_sound_freq) && (_sound_freq > 0)) _freq = _sound_freq; else _freq = dscaps.dwMaxSecondarySampleRate; _TRACE(PREFIX_I "DirectSound caps: %u bits, %s, %uHz\n", _bits, _stereo ? "stereo" : "mono", _freq); /* create primary buffer */ memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; hr = IDirectSound_CreateSoundBuffer(directsound, &desc, &prim_buf, NULL); if (hr != DS_OK) { _TRACE(PREFIX_W "Can't create primary buffer (%s)\nGlobal volume control won't be available.\n", ds_err(hr)); } /* get current format */ if (prim_buf) { hr = IDirectSoundBuffer_GetFormat(prim_buf, &format, sizeof(format), NULL); if (FAILED(hr)) { _TRACE(PREFIX_W "Can't get primary buffer format (%s).\n", ds_err(hr)); } else { format.nChannels = _stereo ? 2 : 1; format.nSamplesPerSec = _freq; format.wBitsPerSample = _bits; format.nBlockAlign = (format.wBitsPerSample * format.nChannels) >> 3; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; hr = IDirectSoundBuffer_SetFormat(prim_buf, &format); if (FAILED(hr)) { _TRACE(PREFIX_W "Can't set primary buffer format (%s).\n", ds_err(hr)); } /* output primary format */ hr = IDirectSoundBuffer_GetFormat(prim_buf, &format, sizeof(format), NULL); if (FAILED(hr)) { _TRACE(PREFIX_W "Can't get primary buffer format (%s).\n", ds_err(hr)); } else { _TRACE(PREFIX_I "primary format:\n"); _TRACE(PREFIX_I " %u channels\n %u Hz\n %u AvgBytesPerSec\n %u BlockAlign\n %u bits\n %u size\n", format.nChannels, format.nSamplesPerSec, format.nAvgBytesPerSec, format.nBlockAlign, format.wBitsPerSample, format.cbSize); } } /* get primary buffer (global) volume */ IDirectSoundBuffer_GetVolume(prim_buf, &initial_volume); } /* initialize physical voices */ ds_voices = (struct DIRECTSOUND_VOICE *)_AL_MALLOC(sizeof(struct DIRECTSOUND_VOICE) * voices); for (v = 0; v < digi_driver->voices; v++) { ds_voices[v].ds_buffer = NULL; ds_voices[v].ds_loop_buffer = NULL; ds_voices[v].ds_locked_buffer = NULL; } /* setup volume lookup table */ alleg_to_dsound_volume[0] = DSBVOLUME_MIN; for (v = 1; v < 256; v++) alleg_to_dsound_volume[v] = MAX(DSBVOLUME_MIN, DSBVOLUME_MAX + 2000.0*log10(v/255.0)); /* setup pan lookup table */ alleg_to_dsound_pan[0] = DSBPAN_LEFT; for (v = 1; v < 128; v++) alleg_to_dsound_pan[v] = MAX(DSBPAN_LEFT, DSBPAN_CENTER + 2000.0*log10(v/127.0)); alleg_to_dsound_pan[255] = DSBPAN_RIGHT; for (v = 128; v < 255; v++) alleg_to_dsound_pan[v] = MIN(DSBPAN_RIGHT, DSBPAN_CENTER - 2000.0*log10((255.0-v)/127.0)); return 0; Error: _TRACE(PREFIX_E "digi_directsound_init() failed.\n"); digi_directsound_exit(FALSE); return -1; } /* digi_directsound_exit: */ static void digi_directsound_exit(int input) { int v; if (input) { digi_directsound_capture_exit(); return; } /* destroy physical voices */ for (v = 0; v < digi_driver->voices; v++) digi_directsound_release_voice(v); _AL_FREE(ds_voices); ds_voices = NULL; /* destroy primary buffer */ if (prim_buf) { /* restore primary buffer initial volume */ IDirectSoundBuffer_SetVolume(prim_buf, initial_volume); IDirectSoundBuffer_Release(prim_buf); prim_buf = NULL; } /* shutdown DirectSound */ if (directsound) { IDirectSound_Release(directsound); directsound = NULL; } } /* digi_directsound_set_mixer_volume: */ static int digi_directsound_set_mixer_volume(int volume) { int ds_vol; if (prim_buf) { ds_vol = alleg_to_dsound_volume[CLAMP(0, volume, 255)]; IDirectSoundBuffer_SetVolume(prim_buf, ds_vol); } return 0; } /* digi_directsound_get_mixer_volume: */ static int digi_directsound_get_mixer_volume(void) { LONG vol; if (!prim_buf) return -1; IDirectSoundBuffer_GetVolume(prim_buf, &vol); vol = CLAMP(0, pow(10, (vol/2000.0))*255.0 - DSBVOLUME_MAX, 255); return vol; } /********************************************************/ /*********** voice management functions *****************/ /********************************************************/ /* create_dsound_buffer: * Worker function for creating a DirectSound buffer. */ static LPDIRECTSOUNDBUFFER create_dsound_buffer(int len, int freq, int bits, int stereo, int vol, int pan) { LPDIRECTSOUNDBUFFER snd_buf; WAVEFORMATEX wf; DSBUFFERDESC dsbdesc; HRESULT hr; int switch_mode; /* setup wave format structure */ memset(&wf, 0, sizeof(WAVEFORMATEX)); wf.wFormatTag = WAVE_FORMAT_PCM; wf.nChannels = stereo ? 2 : 1; wf.nSamplesPerSec = freq; wf.wBitsPerSample = bits; wf.nBlockAlign = bits * (stereo ? 2 : 1) / 8; wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; /* setup DSBUFFERDESC structure */ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); /* need default controls (pan, volume, frequency) */ dsbdesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; switch_mode = get_display_switch_mode(); if ((switch_mode == SWITCH_BACKAMNESIA) || (switch_mode == SWITCH_BACKGROUND)) dsbdesc.dwFlags |= DSBCAPS_GLOBALFOCUS; dsbdesc.dwBufferBytes = len * (bits / 8) * (stereo ? 2 : 1); dsbdesc.lpwfxFormat = &wf; /* create buffer */ hr = IDirectSound_CreateSoundBuffer(directsound, &dsbdesc, &snd_buf, NULL); if (FAILED(hr)) { _TRACE(PREFIX_E "create_directsound_buffer() failed (%s).\n", ds_err(hr)); _TRACE(PREFIX_E " - %d Hz, %s, %d bits\n", freq, stereo ? "stereo" : "mono", bits); return NULL; } /* set volume */ IDirectSoundBuffer_SetVolume(snd_buf, alleg_to_dsound_volume[CLAMP(0, vol, 255)]); /* set pan */ IDirectSoundBuffer_SetPan(snd_buf, alleg_to_dsound_pan[CLAMP(0, pan, 255)]); return snd_buf; } /* fill_dsound_buffer: * Worker function for copying data to a DirectSound buffer. */ static int fill_dsound_buffer(LPDIRECTSOUNDBUFFER snd_buf, int offset, int len, int bits, int stereo, int reversed, unsigned char *data) { void *buf_a; unsigned long int size, size_a; HRESULT hr; /* transform from samples to bytes */ size = len * (bits / 8) * (stereo ? 2 : 1); offset = offset * (bits / 8) * (stereo ? 2 : 1); /* lock the buffer portion */ hr = IDirectSoundBuffer_Lock(snd_buf, offset, size, &buf_a, &size_a, NULL, NULL, 0); /* if buffer lost, restore and retry lock */ if (hr == DSERR_BUFFERLOST) { IDirectSoundBuffer_Restore(snd_buf); hr = IDirectSoundBuffer_Lock(snd_buf, offset, size, &buf_a, &size_a, NULL, NULL, 0); if (FAILED(hr)) { _TRACE(PREFIX_E "fill_dsound_buffer() failed (%s).\n", ds_err(hr)); return -1; } } if (reversed) { if (stereo) { if (bits == 8) { /* 8-bit stereo */ unsigned short *read_p = (unsigned short *)data + len - 1; unsigned short *write_p = (unsigned short *)buf_a; while (len--) *write_p++ = *read_p--; } else if (bits == 16) { /* 16-bit stereo (conversion needed) */ unsigned long *read_p = (unsigned long *)data + len - 1; unsigned long *write_p = (unsigned long *)buf_a; while (len--) *write_p++ = *read_p-- ^ 0x80008000; } } else { if (bits == 8) { /* 8-bit mono */ unsigned char *read_p = (unsigned char *)data + len - 1; unsigned char *write_p = (unsigned char *)buf_a; while (len--) *write_p++ = *read_p--; } else { /* 16-bit mono (conversion needed) */ unsigned short *read_p = (unsigned short *)data + len - 1; unsigned short *write_p = (unsigned short *)buf_a; while (len--) *write_p++ = *read_p-- ^ 0x8000; } } } else { if (bits == 8) { /* 8-bit mono and stereo */ memcpy(buf_a, data, size); } else if (bits == 16) { /* 16-bit mono and stereo (conversion needed) */ unsigned short *read_p = (unsigned short *)data; unsigned short *write_p = (unsigned short *)buf_a; size >>= 1; while (size--) *write_p++ = *read_p++ ^ 0x8000; } } /* unlock the buffer */ IDirectSoundBuffer_Unlock(snd_buf, buf_a, size_a, NULL, 0); return 0; } /* digi_directsound_init_voice: */ static void digi_directsound_init_voice(int voice, AL_CONST SAMPLE *sample) { ds_voices[voice].bits = sample->bits; ds_voices[voice].bytes_per_sample = (sample->bits/8) * (sample->stereo ? 2 : 1); ds_voices[voice].freq = sample->freq; ds_voices[voice].pan = 128; ds_voices[voice].vol = 255; ds_voices[voice].stereo = sample->stereo; ds_voices[voice].reversed = FALSE; ds_voices[voice].bidir = FALSE; ds_voices[voice].len = sample->len; ds_voices[voice].data = (unsigned char *)sample->data; ds_voices[voice].loop_offset = sample->loop_start; ds_voices[voice].loop_len = sample->loop_end - sample->loop_start; ds_voices[voice].looping = FALSE; ds_voices[voice].lock_buf_a = NULL; ds_voices[voice].lock_size_a = 0; ds_voices[voice].ds_locked_buffer = NULL; ds_voices[voice].ds_loop_buffer = NULL; ds_voices[voice].ds_buffer = create_dsound_buffer(ds_voices[voice].len, ds_voices[voice].freq, ds_voices[voice].bits, ds_voices[voice].stereo, ds_voices[voice].vol, ds_voices[voice].pan); if (!ds_voices[voice].ds_buffer) return; fill_dsound_buffer(ds_voices[voice].ds_buffer, 0, /* offset */ ds_voices[voice].len, ds_voices[voice].bits, ds_voices[voice].stereo, ds_voices[voice].reversed, ds_voices[voice].data); } /* digi_directsound_release_voice: */ static void digi_directsound_release_voice(int voice) { /* just in case */ digi_directsound_unlock_voice(voice); if (ds_voices[voice].ds_buffer) { IDirectSoundBuffer_Release(ds_voices[voice].ds_buffer); ds_voices[voice].ds_buffer = NULL; } if (ds_voices[voice].ds_loop_buffer) { IDirectSoundBuffer_Release(ds_voices[voice].ds_loop_buffer); ds_voices[voice].ds_loop_buffer = NULL; } } /* digi_directsound_start_voice: */ static void digi_directsound_start_voice(int voice) { if (ds_voices[voice].looping && ds_voices[voice].ds_loop_buffer) { IDirectSoundBuffer_Play(ds_voices[voice].ds_loop_buffer, 0, 0, DSBPLAY_LOOPING); } else if (ds_voices[voice].ds_buffer) { IDirectSoundBuffer_Play(ds_voices[voice].ds_buffer, 0, 0, ds_voices[voice].looping ? DSBPLAY_LOOPING : 0); } } /* digi_directsound_stop_voice: */ static void digi_directsound_stop_voice(int voice) { if (ds_voices[voice].looping && ds_voices[voice].ds_loop_buffer) { IDirectSoundBuffer_Stop(ds_voices[voice].ds_loop_buffer); } else if (ds_voices[voice].ds_buffer) { IDirectSoundBuffer_Stop(ds_voices[voice].ds_buffer); } } /* update_voice_buffers: * Worker function for updating the voice buffers with the current * parameters. */ static void update_voice_buffers(int voice, int reversed, int bidir, int loop) { int update_main_buffer = FALSE; int update_loop_buffer = FALSE; int update_reversed = (ds_voices[voice].reversed != reversed); int update_loop = (ds_voices[voice].looping != loop); int update_bidir = (ds_voices[voice].bidir != bidir); /* no work to do? */ if (!update_reversed && !update_bidir && !update_loop) return; /* we need to change looping or bidir? */ if (update_loop || update_bidir) { ds_voices[voice].looping = loop; ds_voices[voice].bidir = bidir; if (!loop && ds_voices[voice].ds_loop_buffer) { /* we don't need a loop buffer anymore, destroy it */ if (ds_voices[voice].ds_locked_buffer == ds_voices[voice].ds_loop_buffer) digi_directsound_unlock_voice(voice); IDirectSoundBuffer_Release(ds_voices[voice].ds_loop_buffer); ds_voices[voice].ds_loop_buffer = NULL; } else if (loop && !ds_voices[voice].ds_loop_buffer) { /* we haven't got one, create it */ ds_voices[voice].ds_loop_buffer = create_dsound_buffer(ds_voices[voice].loop_len * (bidir ? 2 : 1), ds_voices[voice].freq, ds_voices[voice].bits, ds_voices[voice].stereo, ds_voices[voice].vol, ds_voices[voice].pan); update_loop_buffer = TRUE; } else if (update_bidir) { /* we need to resize the loop buffer */ if (ds_voices[voice].ds_locked_buffer == ds_voices[voice].ds_loop_buffer) digi_directsound_unlock_voice(voice); IDirectSoundBuffer_Release(ds_voices[voice].ds_loop_buffer); ds_voices[voice].ds_loop_buffer = create_dsound_buffer(ds_voices[voice].loop_len * (bidir ? 2 : 1), ds_voices[voice].freq, ds_voices[voice].bits, ds_voices[voice].stereo, ds_voices[voice].vol, ds_voices[voice].pan); update_loop_buffer = TRUE; } } /* we need to change the order? */ if (update_reversed) { ds_voices[voice].reversed = reversed; update_main_buffer = TRUE; update_loop_buffer = TRUE; } /* we need to update the main buffer? */ if (update_main_buffer) { fill_dsound_buffer(ds_voices[voice].ds_buffer, 0, /* offset */ ds_voices[voice].len, ds_voices[voice].bits, ds_voices[voice].stereo, ds_voices[voice].reversed, ds_voices[voice].data); } /* we need to update the loop buffer? */ if (update_loop_buffer && ds_voices[voice].ds_loop_buffer) { fill_dsound_buffer(ds_voices[voice].ds_loop_buffer, 0, /* offset */ ds_voices[voice].loop_len, ds_voices[voice].bits, ds_voices[voice].stereo, ds_voices[voice].reversed, ds_voices[voice].data + ds_voices[voice].loop_offset * ds_voices[voice].bytes_per_sample); if (ds_voices[voice].bidir) fill_dsound_buffer(ds_voices[voice].ds_loop_buffer, ds_voices[voice].loop_len, ds_voices[voice].loop_len, ds_voices[voice].bits, ds_voices[voice].stereo, !ds_voices[voice].reversed, ds_voices[voice].data + ds_voices[voice].loop_offset * ds_voices[voice].bytes_per_sample); /* rewind the buffer */ IDirectSoundBuffer_SetCurrentPosition(ds_voices[voice].ds_loop_buffer, 0); } } /* digi_directsound_loop_voice: */ static void digi_directsound_loop_voice(int voice, int playmode) { int reversed = (playmode & PLAYMODE_BACKWARD ? TRUE : FALSE); int bidir = (playmode & PLAYMODE_BIDIR ? TRUE : FALSE); int loop = (playmode & PLAYMODE_LOOP ? TRUE : FALSE); /* update the voice buffers */ update_voice_buffers(voice, reversed, bidir, loop); } /* digi_directsound_lock_voice: */ static void *digi_directsound_lock_voice(int voice, int start, int end) { LPDIRECTSOUNDBUFFER ds_locked_buffer; unsigned long size_a; void *buf_a; HRESULT hr; /* just in case */ digi_directsound_unlock_voice(voice); if (ds_voices[voice].looping && ds_voices[voice].ds_loop_buffer) ds_locked_buffer = ds_voices[voice].ds_loop_buffer; else ds_locked_buffer = ds_voices[voice].ds_buffer; start = start * ds_voices[voice].bytes_per_sample; end = end * ds_voices[voice].bytes_per_sample; hr = IDirectSoundBuffer_Lock(ds_locked_buffer, start, end - start, &buf_a, &size_a, NULL, NULL, 0); /* if buffer lost, restore and retry lock */ if (hr == DSERR_BUFFERLOST) { IDirectSoundBuffer_Restore(ds_locked_buffer); hr = IDirectSoundBuffer_Lock(ds_locked_buffer, start, end - start, &buf_a, &size_a, NULL, NULL, 0); if (FAILED(hr)) { _TRACE(PREFIX_E "digi_directsound_lock_voice() failed (%s).\n", ds_err(hr)); return NULL; } } ds_voices[voice].ds_locked_buffer = ds_locked_buffer; ds_voices[voice].lock_buf_a = buf_a; ds_voices[voice].lock_size_a = size_a; return buf_a; } /* digi_directsound_unlock_voice: */ static void digi_directsound_unlock_voice(int voice) { HRESULT hr; int lock_bytes; if (ds_voices[voice].ds_locked_buffer && ds_voices[voice].lock_buf_a) { if (ds_voices[voice].bits == 16) { unsigned short *p = (unsigned short *)ds_voices[voice].lock_buf_a; lock_bytes = ds_voices[voice].lock_size_a >> 1; while (lock_bytes--) *p++ ^= 0x8000; } hr = IDirectSoundBuffer_Unlock(ds_voices[voice].ds_locked_buffer, ds_voices[voice].lock_buf_a, ds_voices[voice].lock_size_a, NULL, 0); if (FAILED(hr)) { _TRACE(PREFIX_E "digi_directsound_unlock_voice() failed (%s).\n", ds_err(hr)); } ds_voices[voice].ds_locked_buffer = NULL; ds_voices[voice].lock_buf_a = NULL; ds_voices[voice].lock_size_a = 0; } } /* digi_directsound_get_position: */ static int digi_directsound_get_position(int voice) { HRESULT hr; unsigned long int play_cursor; unsigned long int write_cursor; unsigned long int status; int pos; if (ds_voices[voice].looping && ds_voices[voice].ds_loop_buffer) { /* is buffer playing? */ hr = IDirectSoundBuffer_GetStatus(ds_voices[voice].ds_loop_buffer, &status); if (FAILED(hr) || !(status & DSBSTATUS_PLAYING)) return -1; hr = IDirectSoundBuffer_GetCurrentPosition(ds_voices[voice].ds_loop_buffer, &play_cursor, &write_cursor); if (FAILED(hr)) { _TRACE(PREFIX_E "digi_directsound_get_position() failed (%s).\n", ds_err(hr)); return -1; } pos = play_cursor / ds_voices[voice].bytes_per_sample; /* handle bidir data */ if (ds_voices[voice].bidir && (pos >= ds_voices[voice].loop_len)) pos = (ds_voices[voice].loop_len - 1) - (pos - ds_voices[voice].loop_len); /* handle reversed data */ if (ds_voices[voice].reversed) pos = ds_voices[voice].loop_len - 1 - pos; return ds_voices[voice].loop_offset + pos; } else if (ds_voices[voice].ds_buffer) { /* is buffer playing? */ hr = IDirectSoundBuffer_GetStatus(ds_voices[voice].ds_buffer, &status); if (FAILED(hr) || !(status & DSBSTATUS_PLAYING)) return -1; hr = IDirectSoundBuffer_GetCurrentPosition(ds_voices[voice].ds_buffer, &play_cursor, &write_cursor); if (FAILED(hr)) { _TRACE(PREFIX_E "digi_directsound_get_position() failed (%s).\n", ds_err(hr)); return -1; } pos = play_cursor / ds_voices[voice].bytes_per_sample; /* handle reversed data */ if (ds_voices[voice].reversed) pos = ds_voices[voice].len - 1 - pos; return pos; } else return -1; } /* digi_directsound_set_position: */ static void digi_directsound_set_position(int voice, int position) { HRESULT hr; int pos; if (ds_voices[voice].ds_loop_buffer) { pos = CLAMP(0, position - ds_voices[voice].loop_offset, ds_voices[voice].loop_len-1); /* handle bidir data: todo? */ /* handle reversed data */ if (ds_voices[voice].reversed) pos = ds_voices[voice].loop_len - 1 - pos; hr = IDirectSoundBuffer_SetCurrentPosition(ds_voices[voice].ds_loop_buffer, pos * ds_voices[voice].bytes_per_sample); if (FAILED(hr)) { _TRACE(PREFIX_E "digi_directsound_set_position() failed (%s).\n", ds_err(hr)); } } if (ds_voices[voice].ds_buffer) { pos = position; /* handle reversed data */ if (ds_voices[voice].reversed) pos = ds_voices[voice].len - 1 - pos; hr = IDirectSoundBuffer_SetCurrentPosition(ds_voices[voice].ds_buffer, pos * ds_voices[voice].bytes_per_sample); if (FAILED(hr)) { _TRACE(PREFIX_E "digi_directsound_set_position() failed (%s).\n", ds_err(hr)); } } } /* digi_directsound_get_volume: */ static int digi_directsound_get_volume(int voice) { return ds_voices[voice].vol; } /* digi_directsound_set_volume: */ static void digi_directsound_set_volume(int voice, int volume) { int ds_vol; ds_voices[voice].vol = volume; if (ds_voices[voice].ds_buffer) { ds_vol = alleg_to_dsound_volume[CLAMP(0, volume, 255)]; IDirectSoundBuffer_SetVolume(ds_voices[voice].ds_buffer, ds_vol); if (ds_voices[voice].ds_loop_buffer) IDirectSoundBuffer_SetVolume(ds_voices[voice].ds_loop_buffer, ds_vol); } } /* digi_directsound_get_frequency: */ static int digi_directsound_get_frequency(int voice) { return ds_voices[voice].freq; } /* digi_directsound_set_frequency: */ static void digi_directsound_set_frequency(int voice, int frequency) { ds_voices[voice].freq = frequency; if (ds_voices[voice].ds_buffer) { IDirectSoundBuffer_SetFrequency(ds_voices[voice].ds_buffer, frequency); if (ds_voices[voice].ds_loop_buffer) IDirectSoundBuffer_SetFrequency(ds_voices[voice].ds_loop_buffer, frequency); } } /* digi_directsound_get_pan: */ static int digi_directsound_get_pan(int voice) { return ds_voices[voice].pan; } /* digi_directsound_set_pan: */ static void digi_directsound_set_pan(int voice, int pan) { int ds_pan; ds_voices[voice].pan = pan; if (ds_voices[voice].ds_buffer) { ds_pan = alleg_to_dsound_pan[CLAMP(0, pan, 255)]; IDirectSoundBuffer_SetPan(ds_voices[voice].ds_buffer, ds_pan); if (ds_voices[voice].ds_loop_buffer) IDirectSoundBuffer_SetPan(ds_voices[voice].ds_loop_buffer, ds_pan); } } allegro-4.4.3.1/src/win/wddaccel.c0000664000175000017500000004124613437077643015605 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw acceleration. * * By Stefan Schimanski. * * Bugfixes by Isaac Cruz. * * Accelerated rectfill() and hline() added by Shawn Hargreaves. * * Accelerated stretch_blit() and friends by Thomas Harte. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-ddaccel INFO: " #define PREFIX_W "al-ddaccel WARNING: " #define PREFIX_E "al-ddaccel ERROR: " /* software version pointers */ static void (*_orig_hline) (BITMAP * bmp, int x1, int y, int x2, int color); static void (*_orig_vline) (BITMAP * bmp, int x, int y1, int y2, int color); static void (*_orig_rectfill) (BITMAP * bmp, int x1, int y1, int x2, int y2, int color); static void (*_orig_draw_sprite) (BITMAP * bmp, BITMAP * sprite, int x, int y); static void (*_orig_masked_blit) (BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void (*_orig_stretch_blit) (BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked); /* ddraw_blit_to_self: * Accelerated vram -> vram blitting routine. */ static void ddraw_blit_to_self(BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { RECT src_rect; int dest_parent_x = dest_x + dest->x_ofs; int dest_parent_y = dest_y + dest->y_ofs; BITMAP *dest_parent; BITMAP *source_parent; src_rect.left = source_x + source->x_ofs; src_rect.top = source_y + source->y_ofs; src_rect.right = source_x + source->x_ofs + width; src_rect.bottom = source_y + source->y_ofs + height; /* find parents */ dest_parent = dest; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; source_parent = source; while (source_parent->id & BMP_ID_SUB) source_parent = (BITMAP *)source_parent->extra; _enter_gfx_critical(); gfx_directx_release_lock(dest); gfx_directx_release_lock(source); IDirectDrawSurface2_BltFast(DDRAW_SURFACE_OF(dest_parent)->id, dest_parent_x, dest_parent_y, DDRAW_SURFACE_OF(source_parent)->id, &src_rect, DDBLTFAST_WAIT); _exit_gfx_critical(); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap)) { src_rect.left = dest_parent_x; src_rect.top = dest_parent_y; src_rect.right = dest_parent_x + width; src_rect.bottom = dest_parent_y + height; win_gfx_driver->paint(&src_rect); } } /* ddraw_masked_blit: * Accelerated masked blitting routine. */ static void ddraw_masked_blit(BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { RECT dest_rect, source_rect; DDCOLORKEY src_key; HRESULT hr; BITMAP *dest_parent; BITMAP *source_parent; dest_rect.left = dest_x + dest->x_ofs; dest_rect.top = dest_y + dest->y_ofs; dest_rect.right = dest_x + dest->x_ofs + width; dest_rect.bottom = dest_y + dest->y_ofs + height; source_rect.left = source_x + source->x_ofs; source_rect.top = source_y + source->y_ofs; source_rect.right = source_x + source->x_ofs + width; source_rect.bottom = source_y + source->y_ofs + height; src_key.dwColorSpaceLowValue = source->vtable->mask_color; src_key.dwColorSpaceHighValue = source->vtable->mask_color; if (is_video_bitmap(source) || is_system_bitmap(source)) { /* find parents */ dest_parent = dest; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; source_parent = source; while (source_parent->id & BMP_ID_SUB) source_parent = (BITMAP *)source_parent->extra; _enter_gfx_critical(); gfx_directx_release_lock(dest); gfx_directx_release_lock(source); IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id, DDCKEY_SRCBLT, &src_key); hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect, DDRAW_SURFACE_OF(source_parent)->id, &source_rect, DDBLT_KEYSRC | DDBLT_WAIT, NULL); _exit_gfx_critical(); if (FAILED(hr)) _TRACE(PREFIX_E "Blt failed (%x)\n", hr); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap)) win_gfx_driver->paint(&dest_rect); } else { /* have to use the original software version */ _orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height); } } /* ddraw_draw_sprite: * Accelerated sprite drawing routine. */ static void ddraw_draw_sprite(BITMAP * bmp, BITMAP * sprite, int x, int y) { int sx, sy, w, h; if (is_video_bitmap(sprite) || is_system_bitmap(sprite)) { sx = 0; /* sprite->x_ofs & sprite->y_ofs will be accounted for in ddraw_masked_blit */ sy = 0; w = sprite->w; h = sprite->h; if (bmp->clip) { if (x < bmp->cl) { sx += bmp->cl - x; w -= bmp->cl - x; x = bmp->cl; } if (y < bmp->ct) { sy += bmp->ct - y; h -= bmp->ct - y; y = bmp->ct; } if (x + w > bmp->cr) w = bmp->cr - x; if (w <= 0) return; if (y + h > bmp->cb) h = bmp->cb - y; if (h <= 0) return; } ddraw_masked_blit(sprite, bmp, sx, sy, x, y, w, h); } else { /* have to use the original software version */ _orig_draw_sprite(bmp, sprite, x, y); } } /* ddraw_do_stretch_blit: * Accelerated stretch_blit, stretch_sprite, stretch_masked_blit */ static void ddraw_do_stretch_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked) { RECT dest_rect, source_rect; DDCOLORKEY src_key; HRESULT hr; BITMAP *dest_parent; BITMAP *source_parent; dest_rect.left = dest_x + dest->x_ofs; dest_rect.top = dest_y + dest->y_ofs; dest_rect.right = dest_x + dest->x_ofs + dest_width; dest_rect.bottom = dest_y + dest->y_ofs + dest_height; source_rect.left = source_x + source->x_ofs; source_rect.top = source_y + source->y_ofs; source_rect.right = source_x + source->x_ofs + source_width; source_rect.bottom = source_y + source->y_ofs + source_height; src_key.dwColorSpaceLowValue = source->vtable->mask_color; src_key.dwColorSpaceHighValue = source->vtable->mask_color; if ( ( (masked && (gfx_capabilities & GFX_HW_VRAM_STRETCH_BLIT_MASKED)) || (!masked && (gfx_capabilities & GFX_HW_VRAM_STRETCH_BLIT)) ) && ( is_video_bitmap(source) || is_system_bitmap(source) ) ) { /* find parents */ dest_parent = dest; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; source_parent = source; while (source_parent->id & BMP_ID_SUB) source_parent = (BITMAP *)source_parent->extra; _enter_gfx_critical(); gfx_directx_release_lock(dest); gfx_directx_release_lock(source); IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id, DDCKEY_SRCBLT, &src_key); hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect, DDRAW_SURFACE_OF(source_parent)->id, &source_rect, (masked ? DDBLT_KEYSRC : 0) | DDBLT_WAIT, NULL); _exit_gfx_critical(); if (FAILED(hr)) _TRACE(PREFIX_E "Blt failed (%x)\n", hr); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap)) win_gfx_driver->paint(&dest_rect); } else { /* have to use the original software version */ _orig_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked); } } /* ddraw_clear_to_color: * Accelerated screen clear routine. */ static void ddraw_clear_to_color(BITMAP * bitmap, int color) { RECT dest_rect; HRESULT hr; DDBLTFX blt_fx; BITMAP *parent; dest_rect.left = bitmap->cl + bitmap->x_ofs; dest_rect.top = bitmap->ct + bitmap->y_ofs; dest_rect.right = bitmap->x_ofs + bitmap->cr; dest_rect.bottom = bitmap->y_ofs + bitmap->cb; /* find parent */ parent = bitmap; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; /* set fill color */ blt_fx.dwSize = sizeof(blt_fx); blt_fx.dwDDFX = 0; blt_fx.dwFillColor = color; _enter_gfx_critical(); gfx_directx_release_lock(bitmap); hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx); _exit_gfx_critical(); if (FAILED(hr)) _TRACE(PREFIX_E "Blt failed (%x)\n", hr); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (parent == gfx_directx_forefront_bitmap)) win_gfx_driver->paint(&dest_rect); } /* ddraw_rectfill: * Accelerated rectangle fill routine. */ static void ddraw_rectfill(BITMAP *bitmap, int x1, int y1, int x2, int y2, int color) { RECT dest_rect; HRESULT hr; DDBLTFX blt_fx; BITMAP *parent; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_rectfill(bitmap, x1, y1, x2, y2, color); return; } if (x2 < x1) { int tmp = x1; x1 = x2; x2 = tmp; } if (y2 < y1) { int tmp = y1; y1 = y2; y2 = tmp; } if (bitmap->clip) { if (x1 < bitmap->cl) x1 = bitmap->cl; if (x2 >= bitmap->cr) x2 = bitmap->cr-1; if (x2 < x1) return; if (y1 < bitmap->ct) y1 = bitmap->ct; if (y2 >= bitmap->cb) y2 = bitmap->cb-1; if (y2 < y1) return; } dest_rect.left = x1 + bitmap->x_ofs; dest_rect.top = y1 + bitmap->y_ofs; dest_rect.right = x2 + bitmap->x_ofs + 1; dest_rect.bottom = y2 + bitmap->y_ofs + 1; /* find parent */ parent = bitmap; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; /* set fill color */ blt_fx.dwSize = sizeof(blt_fx); blt_fx.dwDDFX = 0; blt_fx.dwFillColor = color; _enter_gfx_critical(); gfx_directx_release_lock(bitmap); hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx); _exit_gfx_critical(); if (FAILED(hr)) _TRACE(PREFIX_E "Blt failed (%x)\n", hr); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (parent == gfx_directx_forefront_bitmap)) win_gfx_driver->paint(&dest_rect); } /* ddraw_hline: * Accelerated scanline fill routine. */ static void ddraw_hline(BITMAP *bitmap, int x1, int y, int x2, int color) { RECT dest_rect; HRESULT hr; DDBLTFX blt_fx; BITMAP *parent; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_hline(bitmap, x1, y, x2, color); return; } if (x1 > x2) { int tmp = x1; x1 = x2; x2 = tmp; } if (bitmap->clip) { if ((y < bitmap->ct) || (y >= bitmap->cb)) return; if (x1 < bitmap->cl) x1 = bitmap->cl; if (x2 >= bitmap->cr) x2 = bitmap->cr-1; if (x2 < x1) return; } dest_rect.left = x1 + bitmap->x_ofs; dest_rect.top = y + bitmap->y_ofs; dest_rect.right = x2 + bitmap->x_ofs + 1; dest_rect.bottom = y + bitmap->y_ofs + 1; /* find parent */ parent = bitmap; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; /* set fill color */ blt_fx.dwSize = sizeof(blt_fx); blt_fx.dwDDFX = 0; blt_fx.dwFillColor = color; _enter_gfx_critical(); gfx_directx_release_lock(bitmap); hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx); _exit_gfx_critical(); if (FAILED(hr)) _TRACE(PREFIX_E "Blt failed (%x)\n", hr); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (parent == gfx_directx_forefront_bitmap)) win_gfx_driver->paint(&dest_rect); } /* ddraw_vline: * Accelerated vline routine. */ static void ddraw_vline(BITMAP *bitmap, int x, int y1, int y2, int color) { RECT dest_rect; HRESULT hr; DDBLTFX blt_fx; BITMAP *parent; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_vline(bitmap, x, y1, y2, color); return; } if (y1 > y2) { int tmp = y1; y1 = y2; y2 = tmp; } if (bitmap->clip) { if ((x < bitmap->cl) || (x >= bitmap->cr)) return; if (y1 < bitmap->ct) y1 = bitmap->ct; if (y2 >= bitmap->cb) y2 = bitmap->cb-1; if (y2 < y1) return; } dest_rect.top = y1 + bitmap->y_ofs; dest_rect.left = x + bitmap->x_ofs; dest_rect.bottom = y2 + bitmap->y_ofs + 1; dest_rect.right = x + bitmap->x_ofs + 1; /* find parent */ parent = bitmap; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; /* set fill color */ blt_fx.dwSize = sizeof(blt_fx); blt_fx.dwDDFX = 0; blt_fx.dwFillColor = color; _enter_gfx_critical(); gfx_directx_release_lock(bitmap); hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx); _exit_gfx_critical(); if (FAILED(hr)) _TRACE(PREFIX_E "Blt failed (%x)\n", hr); /* only for windowed mode */ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (parent == gfx_directx_forefront_bitmap)) win_gfx_driver->paint(&dest_rect); } /* gfx_directx_enable_acceleration: * Checks graphic driver for capabilities to accelerate Allegro. */ void gfx_directx_enable_acceleration(GFX_DRIVER * drv) { /* safe pointer to software versions */ _orig_hline = _screen_vtable.hline; _orig_vline = _screen_vtable.vline; _orig_rectfill = _screen_vtable.rectfill; _orig_draw_sprite = _screen_vtable.draw_sprite; _orig_masked_blit = _screen_vtable.masked_blit; _orig_stretch_blit = _screen_vtable.do_stretch_blit; /* accelerated video to video blits? */ if (ddcaps.dwCaps & DDCAPS_BLT) { _screen_vtable.blit_to_self = ddraw_blit_to_self; _screen_vtable.blit_to_self_forward = ddraw_blit_to_self; _screen_vtable.blit_to_self_backward = ddraw_blit_to_self; _screen_vtable.blit_from_system = ddraw_blit_to_self; _screen_vtable.blit_to_system = ddraw_blit_to_self; if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH) { _screen_vtable.do_stretch_blit = ddraw_do_stretch_blit; gfx_capabilities |= GFX_HW_VRAM_STRETCH_BLIT | GFX_HW_SYS_STRETCH_BLIT; } gfx_capabilities |= (GFX_HW_VRAM_BLIT | GFX_HW_SYS_TO_VRAM_BLIT); } /* accelerated color fills? */ if (ddcaps.dwCaps & DDCAPS_BLTCOLORFILL) { _screen_vtable.clear_to_color = ddraw_clear_to_color; _screen_vtable.rectfill = ddraw_rectfill; _screen_vtable.hline = ddraw_hline; _screen_vtable.vline = ddraw_vline; gfx_capabilities |= (GFX_HW_HLINE | GFX_HW_FILL); } /* accelerated color key blits? */ if ((ddcaps.dwCaps & DDCAPS_COLORKEY) && (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) { _screen_vtable.masked_blit = ddraw_masked_blit; _screen_vtable.draw_sprite = ddraw_draw_sprite; if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH) { _screen_vtable.do_stretch_blit = ddraw_do_stretch_blit; gfx_capabilities |= GFX_HW_VRAM_STRETCH_BLIT_MASKED|GFX_HW_SYS_STRETCH_BLIT_MASKED; } if (_screen_vtable.color_depth == 8) _screen_vtable.draw_256_sprite = ddraw_draw_sprite; gfx_capabilities |= (GFX_HW_VRAM_BLIT_MASKED | GFX_HW_SYS_TO_VRAM_BLIT_MASKED); } } /* gfx_directx_enable_triple_buffering: * Checks graphic driver for triple buffering capability. */ void gfx_directx_enable_triple_buffering(GFX_DRIVER *drv) { HRESULT hr; hr = IDirectDrawSurface2_GetFlipStatus(DDRAW_SURFACE_OF(gfx_directx_forefront_bitmap)->id, DDGFS_ISFLIPDONE); if ((hr == DD_OK) || (hr == DDERR_WASSTILLDRAWING)) { drv->poll_scroll = gfx_directx_poll_scroll; gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; } } allegro-4.4.3.1/src/win/wddbmpl.c0000664000175000017500000000552013437077643015463 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DirectDraw surface list management. * * By Stefan Schimanski. * * See readme.txt for copyright information. */ #include "wddraw.h" #define PREFIX_I "al-wddbmpl INFO: " #define PREFIX_W "al-wddbmpl WARNING: " #define PREFIX_E "al-wddbmpl ERROR: " /* double linked list */ static DDRAW_SURFACE *ddraw_surface_list = NULL; /* register_ddraw_surface: * Adds a surface to the linked list. */ void register_ddraw_surface(DDRAW_SURFACE *surf) { _enter_gfx_critical(); surf->next = ddraw_surface_list; surf->prev = NULL; if (ddraw_surface_list) ddraw_surface_list->prev = surf; ddraw_surface_list = surf; _exit_gfx_critical(); } /* unregister_ddraw_surface: * Removes a surface from the linked list. */ void unregister_ddraw_surface(DDRAW_SURFACE *surf) { DDRAW_SURFACE *item; _enter_gfx_critical(); item = ddraw_surface_list; while (item) { if (item == surf) { /* surface found, unlink now */ if (item->next) item->next->prev = item->prev; if (item->prev) item->prev->next = item->next; if (ddraw_surface_list == item) ddraw_surface_list = item->next; item->next = NULL; item->prev = NULL; break; } item = item->next; } _exit_gfx_critical(); } /* unregister_all_ddraw_surfaces: * Removes all surfaces from the linked list. */ void unregister_all_ddraw_surfaces(void) { DDRAW_SURFACE *item, *next_item; _enter_gfx_critical(); next_item = ddraw_surface_list; while (next_item) { item = next_item; next_item = next_item->next; item->next = NULL; item->prev = NULL; } ddraw_surface_list = NULL; _exit_gfx_critical(); } /* restore_all_ddraw_surfaces: * Restores all the surfaces. Returns 0 on success or -1 on failure, * in which case restoring is stopped at the first failure. */ int restore_all_ddraw_surfaces(void) { DDRAW_SURFACE *item; HRESULT hr; _enter_gfx_critical(); item = ddraw_surface_list; while (item) { hr = IDirectDrawSurface2_Restore(item->id); if (FAILED(hr)) { _exit_gfx_critical(); return -1; } item = item->next; } _exit_gfx_critical(); _TRACE(PREFIX_I "all DirectDraw surfaces restored\n"); return 0; } allegro-4.4.3.1/src/win/dllver.rc0000664000175000017500000000156713437077643015513 0ustar siegesiege// Windows resource file for the version info sheet // generated by misc/fixver.sh #include 1 VERSIONINFO FILEVERSION 4, 4, 3, 0 PRODUCTVERSION 4, 4, 3, 0 FILEOS VOS__WINDOWS32 FILETYPE VFT_DLL BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "Comments", "Please see AUTHORS for a list of contributors\000" VALUE "CompanyName", "Allegro Developers\000\000" VALUE "FileDescription", "Allegro\000" VALUE "FileVersion", "4.4.3\000" VALUE "InternalName", "ALLEG44\000" VALUE "LegalCopyright", "Copyright 1994-2019 Allegro Developers\000\000" VALUE "OriginalFilename", "ALLEG44.DLL\000" VALUE "ProductName", "Allegro\000" VALUE "ProductVersion", "4.4.3\000" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0809, 1252 END END allegro-4.4.3.1/src/unix/0000775000175000017500000000000013437077643014052 5ustar siegesiegeallegro-4.4.3.1/src/unix/udrvlist.c0000664000175000017500000000573613437077643016105 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Dynamic driver lists shared by Unixy system drivers. * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" _DRIVER_INFO *_unix_gfx_driver_list = 0; _DRIVER_INFO *_unix_digi_driver_list = 0; _DRIVER_INFO *_unix_midi_driver_list = 0; /* _unix_driver_lists_init: * Initialise driver lists. */ void _unix_driver_lists_init(void) { _unix_gfx_driver_list = _create_driver_list(); if (_unix_gfx_driver_list) _driver_list_append_list(&_unix_gfx_driver_list, _gfx_driver_list); _unix_digi_driver_list = _create_driver_list(); if (_unix_digi_driver_list) _driver_list_append_list(&_unix_digi_driver_list, _digi_driver_list); _unix_midi_driver_list = _create_driver_list(); if (_unix_midi_driver_list) _driver_list_append_list(&_unix_midi_driver_list, _midi_driver_list); } /* _unix_driver_lists_shutdown: * Free driver lists. */ void _unix_driver_lists_shutdown(void) { if (_unix_gfx_driver_list) { _destroy_driver_list(_unix_gfx_driver_list); _unix_gfx_driver_list = 0; } if (_unix_digi_driver_list) { _destroy_driver_list(_unix_digi_driver_list); _unix_digi_driver_list = 0; } if (_unix_midi_driver_list) { _destroy_driver_list(_unix_midi_driver_list); _unix_midi_driver_list = 0; } } /* _unix_register_gfx_driver: * Used by modules to register graphics drivers. */ void _unix_register_gfx_driver(int id, GFX_DRIVER *driver, int autodetect, int priority) { if (priority) _driver_list_prepend_driver(&_unix_gfx_driver_list, id, driver, autodetect); else _driver_list_append_driver(&_unix_gfx_driver_list, id, driver, autodetect); } /* _unix_register_digi_driver: * Used by modules to register digital sound drivers. */ void _unix_register_digi_driver(int id, DIGI_DRIVER *driver, int autodetect, int priority) { if (priority) _driver_list_prepend_driver(&_unix_digi_driver_list, id, driver, autodetect); else _driver_list_append_driver(&_unix_digi_driver_list, id, driver, autodetect); } /* _unix_register_midi_driver: * Used by modules to register MIDI drivers. */ void _unix_register_midi_driver(int id, MIDI_DRIVER *driver, int autodetect, int priority) { if (priority) _driver_list_prepend_driver(&_unix_midi_driver_list, id, driver, autodetect); else _driver_list_append_driver(&_unix_midi_driver_list, id, driver, autodetect); } allegro-4.4.3.1/src/unix/ukeybd.c0000664000175000017500000000136513437077643015506 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Unix keyboard module. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" /* list the available drivers */ _DRIVER_INFO _keyboard_driver_list[] = { { 0, NULL, 0 } }; allegro-4.4.3.1/src/unix/sgial.c0000664000175000017500000001756413437077643015332 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * SGI AL sound driver. * * By Lisa Parratt. * * See readme.txt for copyright information. */ #include "allegro.h" #if (defined ALLEGRO_WITH_SGIALDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #include #include #include #ifdef ALLEGRO_HAVE_LIBPTHREAD #include #endif #define _AL_SGIAL_PORTSIZE 12288 #ifdef ALLEGRO_HAVE_LIBPTHREAD #define _AL_SGIAL_BUFFERSIZE 2048 #else #define _AL_SGIAL_BUFFERSIZE 4096 #endif static ALconfig _al_sgial_config; static ALport _al_sgial_port; static int _al_sgial_bufsize; static unsigned char *_al_sgial_bufdata; static int _al_sgial_signed; static int _al_sgial_detect(int input); static int _al_sgial_init(int input, int voices); static void _al_sgial_exit(int input); static int _al_sgial_mixer_volume(int volume); static int _al_sgial_buffer_size(void); static char _al_sgial_desc[256] = EMPTY_STRING; #ifdef ALLEGRO_HAVE_LIBPTHREAD static pthread_t thread; #endif DIGI_DRIVER digi_sgial = { DIGI_SGIAL, empty_string, empty_string, "Silicon Graphics Audio", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, _al_sgial_detect, _al_sgial_init, _al_sgial_exit, _al_sgial_mixer_volume, NULL, NULL, NULL, _al_sgial_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* _al_sgial_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int _al_sgial_buffer_size(void) { return _al_sgial_bufsize; } #ifdef ALLEGRO_HAVE_LIBPTHREAD /* _al_sgial_puller_thread_func: [dedicated thread] * We have threads, therefore we can use a thread to pull sound data * as required. */ static void *_al_sgial_puller_thread_func(void *arg) { int fd; fd_set fds; fd = alGetFD(_al_sgial_port); while (1) { alSetFillPoint(_al_sgial_port, _AL_SGIAL_PORTSIZE - _AL_SGIAL_BUFFERSIZE); FD_ZERO(&fds); FD_SET(fd, &fds); select(FD_SETSIZE, NULL, &fds, NULL, NULL); alWriteFrames(_al_sgial_port, _al_sgial_bufdata, _al_sgial_bufsize); _mix_some_samples((uintptr_t) _al_sgial_bufdata, 0, _al_sgial_signed); } } #else /* _al_sgial_update: [SIGALRM callback] * Updates data. */ static void _al_sgial_update(int threaded) { if (alGetFillable(_al_sgial_port) > _al_sgial_bufsize) { alWriteFrames(_al_sgial_port, _al_sgial_bufdata, _al_sgial_bufsize); _mix_some_samples((uintptr_t) _al_sgial_bufdata, 0, _al_sgial_signed); } } #endif /* _al_sgial_detect: * Detects driver presence. */ static int _al_sgial_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } /* A link error would have occured if the audio library was unavailable */ return TRUE; } /* _al_sgial_init: * SGI AL init routine. * This is different from many systems. Whilst SGI AL supports simultaneous * output, it is assumed that all streams will be at the same sample rate. * This driver is well behaved - as such it does *not* honour requested sample * rates, and always uses the system sample rate. */ static int _al_sgial_init(int input, int voices) { char tmp1[128], tmp2[128]; ALpv pv; int _al_sgial_bits; int _al_sgial_stereo; int _al_sgial_rate; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } /* SGI AL will down/up mix as appropriate. This is a crying waste of * Silicon Graphics audio hardware - in all likelihood it will be * upmixing to 24 bits. */ _al_sgial_bits = (_sound_bits == 8) ? AL_SAMPLE_8: AL_SAMPLE_16; _al_sgial_stereo = (_sound_stereo) ? AL_STEREO : AL_MONO; _al_sgial_signed = 1; pv.param = AL_RATE; if (alGetParams(AL_DEFAULT_OUTPUT, &pv, 1) < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not read SGI AL parameters")); return -1; } _al_sgial_rate = (int)alFixedToDouble(pv.value.ll); if (_al_sgial_rate < 0) { /* SGI AL couldn't tell us the sample rate: assume 44100 */ _al_sgial_rate = 44100; } _al_sgial_config = alNewConfig(); alSetSampFmt(_al_sgial_config, AL_SAMPFMT_TWOSCOMP); alSetQueueSize(_al_sgial_config, _AL_SGIAL_PORTSIZE); alSetWidth(_al_sgial_config, _al_sgial_bits); alSetChannels(_al_sgial_config, _al_sgial_stereo); _al_sgial_port = alOpenPort("Allegro", "w", _al_sgial_config); if (!_al_sgial_port) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open SGI AL port")); return -1; } _al_sgial_bufsize = _AL_SGIAL_BUFFERSIZE; _al_sgial_bufdata = _AL_MALLOC_ATOMIC(_al_sgial_bufsize*((_al_sgial_bits==AL_SAMPLE_16) ? 2 : 1)*((_al_sgial_stereo==AL_STEREO) ? 2 : 1)); if (!_al_sgial_bufdata) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); alClosePort(_al_sgial_port); alFreeConfig(_al_sgial_config); return -1; } digi_sgial.voices = voices; if (_mixer_init(_al_sgial_bufsize*((_al_sgial_stereo==AL_STEREO) ? 2 :1 ), _al_sgial_rate, ((_al_sgial_stereo == AL_STEREO) ? 1 : 0), ((_al_sgial_bits == AL_SAMPLE_16) ? 1 : 0), &digi_sgial.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); _AL_FREE(_al_sgial_bufdata); alClosePort(_al_sgial_port); alFreeConfig(_al_sgial_config); return -1; } _mix_some_samples((uintptr_t) _al_sgial_bufdata, 0, _al_sgial_signed); #ifdef ALLEGRO_HAVE_LIBPTHREAD /* Add audio thread. */ pthread_create(&thread, NULL, _al_sgial_puller_thread_func, NULL); #else /* Add audio interrupt. */ _unix_bg_man->register_func(_al_sgial_update); #endif uszprintf(_al_sgial_desc, sizeof(_al_sgial_desc), get_config_text("SGI AL: %d bits, %s, %d bps, %s"), _al_sgial_bits, uconvert_ascii((_al_sgial_signed ? "signed" : "unsigned"), tmp1), _al_sgial_rate, uconvert_ascii((_al_sgial_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = _al_sgial_desc; return 0; } /* _al_sgial_exit: * Shutdown SGI AL driver. */ static void _al_sgial_exit(int input) { if (input) return; #ifdef ALLEGRO_HAVE_LIBPTHREAD pthread_cancel(thread); #else _unix_bg_man->unregister_func(_al_sgial_update); #endif _AL_FREE(_al_sgial_bufdata); _al_sgial_bufdata = NULL; _mixer_exit(); alClosePort(_al_sgial_port); alFreeConfig(_al_sgial_config); } /* _al_sgial_mixer_volume: * Set mixer volume. */ static int _al_sgial_mixer_volume(int volume) { return 0; } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_SGIAL, &digi_sgial, TRUE, TRUE); } #endif #endif allegro-4.4.3.1/src/unix/alsa9.c0000664000175000017500000003522413437077643015235 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * ALSA 0.9 sound driver. * * By Thomas Fjellstrom. * * Extensively modified by Elias Pschernig. * * See readme.txt for copyright information. */ #include "allegro.h" #if (ALLEGRO_ALSA_VERSION == 9) && (defined ALLEGRO_WITH_ALSADIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #ifdef ALLEGRO_QNX #include "allegro/platform/aintqnx.h" #else #include "allegro/platform/aintunix.h" #endif #ifndef SCAN_DEPEND #include #define ALSA_PCM_NEW_HW_PARAMS_API 1 #include #include #endif #ifndef SND_PCM_FORMAT_S16_NE #ifdef ALLEGRO_BIG_ENDIAN #define SND_PCM_FORMAT_S16_NE SND_PCM_FORMAT_S16_BE #else #define SND_PCM_FORMAT_S16_NE SND_PCM_FORMAT_S16_LE #endif #endif #ifndef SND_PCM_FORMAT_U16_NE #ifdef ALLEGRO_BIG_ENDIAN #define SND_PCM_FORMAT_U16_NE SND_PCM_FORMAT_U16_BE #else #define SND_PCM_FORMAT_U16_NE SND_PCM_FORMAT_U16_LE #endif #endif #define ALSA9_CHECK(a) do { \ int err = (a); \ if (err<0) { \ uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "ALSA: %s : %s", #a, get_config_text(snd_strerror(err))); \ goto Error; \ } \ } while(0) #define PREFIX_I "al-alsa9 INFO: " #define PREFIX_W "al-alsa9 WARNING: " #define PREFIX_E "al-alsa9 ERROR: " static char const *alsa_device = "default"; static char const *alsa_mixer_device = "default"; static snd_pcm_hw_params_t *hwparams = NULL; static snd_pcm_sw_params_t *swparams = NULL; static snd_output_t *snd_output = NULL; static snd_pcm_uframes_t alsa_bufsize; static snd_mixer_t *alsa_mixer = NULL; static snd_mixer_elem_t *alsa_mixer_elem = NULL; static long alsa_mixer_elem_min, alsa_mixer_elem_max; static double alsa_mixer_allegro_ratio = 0.0; #define ALSA_DEFAULT_BUFFER_MS 100 #define ALSA_DEFAULT_NUMFRAGS 5 static snd_pcm_t *pcm_handle; static unsigned char *alsa_bufdata; static int alsa_bits, alsa_signed, alsa_stereo; static unsigned int alsa_rate; static unsigned int alsa_fragments; static int alsa_sample_size; static struct pollfd *ufds = NULL; static int pdc = 0; static int poll_next; static char alsa_desc[256] = EMPTY_STRING; static int alsa_detect(int input); static int alsa_init(int input, int voices); static void alsa_exit(int input); static int alsa_set_mixer_volume(int volume); static int alsa_get_mixer_volume(void); static int alsa_buffer_size(void); DIGI_DRIVER digi_alsa = { DIGI_ALSA, empty_string, empty_string, "ALSA", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, alsa_detect, alsa_init, alsa_exit, alsa_set_mixer_volume, alsa_get_mixer_volume, NULL, NULL, alsa_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* alsa_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int alsa_buffer_size(void) { return alsa_bufsize; } /* xrun_recovery: * Underrun and suspend recovery */ static int xrun_recovery(snd_pcm_t *handle, int err) { if (err == -EPIPE) { /* under-run */ err = snd_pcm_prepare(pcm_handle); if (err < 0) fprintf(stderr, "Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err)); return 0; } /* TODO: Can't wait here like that - we are inside an 'interrupt' after all. */ #if 0 else if (err == -ESTRPIPE) { while ((err = snd_pcm_resume(pcm_handle)) == -EAGAIN) sleep(1); /* wait until the suspend flag is released */ if (err < 0) { err = snd_pcm_prepare(pcm_handle); if (err < 0) fprintf(stderr, "Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err)); } return 0; } #endif return err; } /* alsa_mix * Mix and send some samples to ALSA. */ static void alsa_mix(void) { int ret, samples = alsa_bufsize; unsigned char *ptr = alsa_bufdata; while (samples > 0) { ret = snd_pcm_writei(pcm_handle, ptr, samples); if (ret == -EAGAIN) continue; if (ret < 0) { if (xrun_recovery(pcm_handle, ret) < 0) fprintf(stderr, "Write error: %s\n", snd_strerror(ret)); poll_next = 0; break; /* skip one period */ } if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_RUNNING) poll_next = 1; samples -= ret; ptr += ret * alsa_sample_size; } _mix_some_samples((uintptr_t)alsa_bufdata, 0, alsa_signed); } /* alsa_update: * Updates main buffer in case ALSA is ready. */ static void alsa_update(int threaded) { unsigned short revents; if (poll_next) { poll(ufds, pdc, 0); snd_pcm_poll_descriptors_revents(pcm_handle, ufds, pdc, &revents); if (revents & POLLERR) { if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN || snd_pcm_state(pcm_handle) == SND_PCM_STATE_SUSPENDED) { int err = snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE; if (xrun_recovery(pcm_handle, err) < 0) { fprintf(stderr, "Write error: %s\n", snd_strerror(err)); } poll_next = 0; } else { fprintf(stderr, "Wait for poll failed\n"); } return; } if (!(revents & POLLOUT)) return; } alsa_mix(); } /* alsa_detect: * Detects driver presence. */ static int alsa_detect(int input) { int ret = FALSE; char tmp1[128], tmp2[128]; alsa_device = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_device", tmp2), alsa_device); ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (ret < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device")); return FALSE; } snd_pcm_close(pcm_handle); pcm_handle = NULL; return TRUE; } /* alsa_init: * ALSA init routine. */ static int alsa_init(int input, int voices) { int ret = 0; char tmp1[128], tmp2[128]; int format = 0; unsigned int numfrags = 0; snd_pcm_uframes_t fragsize; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } ALSA9_CHECK(snd_output_stdio_attach(&snd_output, stdout, 0)); alsa_device = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_device", tmp2), alsa_device); alsa_mixer_device = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_mixer_device", tmp2), alsa_mixer_device); fragsize = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_fragsize", tmp2), 0); numfrags = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_numfrags", tmp2), ALSA_DEFAULT_NUMFRAGS); ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (ret < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device")); return -1; } snd_mixer_open(&alsa_mixer, 0); if (alsa_mixer && snd_mixer_attach(alsa_mixer, alsa_mixer_device) >= 0 && snd_mixer_selem_register (alsa_mixer, NULL, NULL) >= 0 && snd_mixer_load(alsa_mixer) >= 0) { const char *alsa_mixer_elem_name = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_mixer_elem", tmp2), "PCM"); alsa_mixer_elem = snd_mixer_first_elem(alsa_mixer); while (alsa_mixer_elem) { const char *name = snd_mixer_selem_get_name(alsa_mixer_elem); if (strcasecmp(name, alsa_mixer_elem_name) == 0) { snd_mixer_selem_get_playback_volume_range(alsa_mixer_elem, &alsa_mixer_elem_min, &alsa_mixer_elem_max); alsa_mixer_allegro_ratio = (double) (alsa_mixer_elem_max - alsa_mixer_elem_min) / (double) 255; break; } alsa_mixer_elem = snd_mixer_elem_next(alsa_mixer_elem); } } /* Set format variables. */ alsa_bits = (_sound_bits == 8) ? 8 : 16; alsa_stereo = (_sound_stereo) ? 1 : 0; alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100; snd_pcm_hw_params_malloc(&hwparams); ALSA9_CHECK(snd_pcm_hw_params_any(pcm_handle, hwparams)); if (alsa_bits == 8) { if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_U8) == 0) { format = SND_PCM_FORMAT_U8; alsa_signed = 0; } else if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S8) == 0) { format = SND_PCM_FORMAT_S8; alsa_signed = 1; } else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); goto Error; } } else if (alsa_bits == 16) { if (sizeof(short) != 2) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); goto Error; } if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_U16_NE) == 0) { format = SND_PCM_FORMAT_U16_NE; alsa_signed = 0; } else if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_NE) == 0) { format = SND_PCM_FORMAT_S16_NE; alsa_signed = 1; } else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); goto Error; } } alsa_sample_size = (alsa_bits / 8) * (alsa_stereo ? 2 : 1); if (fragsize == 0) { unsigned int size = alsa_rate * ALSA_DEFAULT_BUFFER_MS / 1000 / numfrags; fragsize = 1; while (fragsize < size) fragsize <<= 1; } ALSA9_CHECK(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)); ALSA9_CHECK(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format)); ALSA9_CHECK(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, alsa_stereo + 1)); ALSA9_CHECK(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &alsa_rate, NULL)); ALSA9_CHECK(snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &fragsize, NULL)); ALSA9_CHECK(snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &numfrags, NULL)); ALSA9_CHECK(snd_pcm_hw_params(pcm_handle, hwparams)); ALSA9_CHECK(snd_pcm_hw_params_get_period_size(hwparams, &alsa_bufsize, NULL)); ALSA9_CHECK(snd_pcm_hw_params_get_periods(hwparams, &alsa_fragments, NULL)); TRACE (PREFIX_I "alsa_bufsize = %ld, alsa_fragments = %d\n", alsa_bufsize, alsa_fragments); snd_pcm_sw_params_malloc(&swparams); ALSA9_CHECK(snd_pcm_sw_params_current(pcm_handle, swparams)); ALSA9_CHECK(snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, alsa_bufsize)); ALSA9_CHECK(snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, fragsize)); ALSA9_CHECK(snd_pcm_sw_params(pcm_handle, swparams)); /* Allocate mixing buffer. */ alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize * alsa_sample_size); if (!alsa_bufdata) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); goto Error; } /* Initialise mixer. */ digi_alsa.voices = voices; if (_mixer_init(alsa_bufsize * (alsa_stereo ? 2 : 1), alsa_rate, alsa_stereo, ((alsa_bits == 16) ? 1 : 0), &digi_alsa.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); goto Error; } snd_pcm_prepare(pcm_handle); pdc = snd_pcm_poll_descriptors_count (pcm_handle); if (pdc <= 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid poll descriptors count")); goto Error; } ufds = _AL_MALLOC(sizeof(struct pollfd) * pdc); if (ufds == NULL) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory for poll descriptors")); goto Error; } ALSA9_CHECK(snd_pcm_poll_descriptors(pcm_handle, ufds, pdc)); poll_next = 0; _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed); /* Add audio interrupt. */ _unix_bg_man->register_func(alsa_update); uszprintf(alsa_desc, sizeof(alsa_desc), get_config_text ("Alsa 0.9, Device '%s': %d bits, %s, %d bps, %s"), alsa_device, alsa_bits, uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1), alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = alsa_desc; return 0; Error: if (pcm_handle) { snd_pcm_close(pcm_handle); pcm_handle = NULL; } return -1; } /* alsa_exit: * Shuts down ALSA driver. */ static void alsa_exit(int input) { if (input) return; _unix_bg_man->unregister_func(alsa_update); _AL_FREE(alsa_bufdata); alsa_bufdata = NULL; _mixer_exit(); if (alsa_mixer) snd_mixer_close(alsa_mixer); snd_pcm_close(pcm_handle); snd_pcm_hw_params_free(hwparams); snd_pcm_sw_params_free(swparams); } /* alsa_set_mixer_volume: * Set mixer volume (0-255) */ static int alsa_set_mixer_volume(int volume) { if (alsa_mixer && alsa_mixer_elem) { snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 0, volume * alsa_mixer_allegro_ratio); snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 1, volume * alsa_mixer_allegro_ratio); } return 0; } /* alsa_get_mixer_volume: * Return mixer volume (0-255) */ static int alsa_get_mixer_volume(void) { if (alsa_mixer && alsa_mixer_elem) { long vol1, vol2; snd_mixer_handle_events(alsa_mixer); if (snd_mixer_selem_get_playback_volume(alsa_mixer_elem, 0, &vol1) < 0) return -1; if (snd_mixer_selem_get_playback_volume(alsa_mixer_elem, 1, &vol2) < 0) return -1; vol1 /= alsa_mixer_allegro_ratio; vol2 /= alsa_mixer_allegro_ratio; return (vol1 + vol2) / 2; } return -1; } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_ALSA, &digi_alsa, TRUE, TRUE); } #endif #endif allegro-4.4.3.1/src/unix/jack.c0000664000175000017500000002036213437077643015131 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Jack sound driver. * * By Elias Pschernig. * * See readme.txt for copyright information. */ #include "allegro.h" #if (defined ALLEGRO_WITH_JACKDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #ifndef SCAN_DEPEND #include #endif /* This still uses Allegro's mixer, and mixes into an intermediate buffer, which * then is transferred to Jack. Another possibility would be to completely * circumvent Allegro's mixer and send each single voice to jack, letting Jack * take care of the mixing. I didn't care about some things in the Jack docs, * like the possibility of buffer sizes changing, or that no mutex_lock function * should be called (inside mix_some_samples). */ #define JACK_DEFAULT_BUFFER_SIZE -1 #define JACK_DEFAULT_CLIENT_NAME "allegro" #define AMP16 ((sample_t) 32768) #define AMP8 ((sample_t) 128) #define PREFIX_I "al-jack INFO: " #define PREFIX_W "al-jack WARNING: " #define PREFIX_E "al-jack ERROR: " typedef jack_default_audio_sample_t sample_t; static int jack_bufsize = JACK_DEFAULT_BUFFER_SIZE; static char const *jack_client_name = JACK_DEFAULT_CLIENT_NAME; static int jack_16bit; static int jack_stereo; static int jack_signed; static jack_nframes_t jack_rate; static char jack_desc[256] = EMPTY_STRING; static jack_client_t *jack_client = NULL; static jack_port_t *output_left, *output_right; static void *jack_buffer; static int jack_detect(int input); static int jack_init(int input, int voices); static void jack_exit(int input); static int jack_buffer_size(void); static int jack_set_mixer_volume(int volume); DIGI_DRIVER digi_jack = { DIGI_JACK, empty_string, empty_string, "JACK", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, jack_detect, jack_init, jack_exit, jack_set_mixer_volume, NULL, NULL, NULL, jack_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* jack_buffer_size: * Returns the current buffer size, for use by the audiostream code. */ static int jack_buffer_size(void) { return jack_bufsize; } /* jack_process: * The JACK processing functions. */ static int jack_process (jack_nframes_t nframes, void *arg) { jack_nframes_t i; /* TODO: Should be uint16_t and uint8_t? Endianess? */ unsigned short *buffer16 = jack_buffer; unsigned char *buffer8 = jack_buffer; jack_default_audio_sample_t *out_left; _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed); out_left = (jack_default_audio_sample_t *) jack_port_get_buffer (output_left, nframes); if (jack_stereo) { jack_default_audio_sample_t *out_right = (jack_default_audio_sample_t *) jack_port_get_buffer (output_right, nframes); if (jack_16bit) { for (i = 0; i < nframes; i++) { out_left[i] = ((sample_t) buffer16[i * 2] - AMP16) / AMP16; out_right[i] = ((sample_t) buffer16[i * 2 + 1] - AMP16) / AMP16; } } else { for (i = 0; i < nframes; i++) { out_left[i] = ((sample_t) buffer8[i * 2] - AMP8) / (sample_t) AMP8; out_right[i] = ((sample_t) buffer8[i * 2 + 1] - AMP8) / (sample_t) AMP8; } } } else { if (jack_16bit) { for (i = 0; i < nframes; i++) { out_left[i] = ((sample_t) buffer16[i] - AMP16) / AMP16; } } else { for (i = 0; i < nframes; i++) { out_left[i] = ((sample_t) buffer8[i] - AMP8) / AMP8; } } } return 0; } /* jack_detect: * Detects driver presence. */ static int jack_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text( "Input is not supported")); return FALSE; } if (!jack_client) { jack_client_name = get_config_string("sound", "jack_client_name", jack_client_name); jack_client = jack_client_new(jack_client_name); if (!jack_client) return FALSE; } return TRUE; } /* jack_init: * JACK init routine. */ static int jack_init(int input, int voices) { const char **ports; char tmp[128]; if (!jack_detect(input)) return -1; jack_bufsize = get_config_int("sound", "jack_buffer_size", jack_bufsize); if (jack_bufsize == -1) jack_bufsize = jack_get_buffer_size (jack_client); /* Those are already read in from the config file by Allegro. */ jack_16bit = (_sound_bits == 16 ? 1 : 0); jack_stereo = (_sound_stereo ? 1 : 0); /* Let Allegro mix in its native unsigned format. */ jack_signed = 0; jack_set_process_callback (jack_client, jack_process, NULL); output_left = jack_port_register (jack_client, jack_stereo ? "left" : "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (jack_stereo) output_right = jack_port_register (jack_client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); jack_rate = jack_get_sample_rate (jack_client); jack_buffer = _AL_MALLOC_ATOMIC(jack_bufsize * (1 + jack_16bit) * (1 + jack_stereo)); if (!jack_buffer) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text( "Cannot allocate audio buffer")); jack_exit (input); return -1; } digi_jack.voices = voices; if (_mixer_init(jack_bufsize * (1 + jack_stereo), jack_rate, jack_stereo, jack_16bit, &digi_jack.voices)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text( "Cannot init software mixer")); jack_exit (input); return -1; } _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed); if (jack_activate (jack_client)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text( "Cannot activate Jack client")); jack_exit (input); return 1; } /* Try to connect the ports. Failure to connect is not critical, since with * JACK, users may connect/disconnect ports anytime, without Allegro caring. */ if ((ports = jack_get_ports (jack_client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) { TRACE (PREFIX_I "Cannot find any physical playback ports"); } if (ports) { if (ports[0]) { if (jack_connect (jack_client, jack_port_name (output_left), ports[0]) == 0) TRACE (PREFIX_I "Connected left playback port to %s", ports[0]); } if (jack_stereo && ports[1]) { if (jack_connect (jack_client, jack_port_name (output_right), ports[1]) == 0) TRACE (PREFIX_I "Connected right playback port to %s", ports[1]); } _AL_FREE (ports); } uszprintf(jack_desc, sizeof(jack_desc), get_config_text ("Jack, client '%s': %d bits, %s, %d bps, %s"), jack_client_name, jack_16bit ? 16 : 8, uconvert_ascii((jack_signed ? "signed" : "unsigned"), tmp), jack_rate, uconvert_ascii((jack_stereo ? "stereo" : "mono"), tmp)); return 0; } /* jack_exit: * Shuts down the JACK driver. */ static void jack_exit(int input) { jack_client_close (jack_client); jack_client = NULL; } /* jack_set_mixer_volume: * Set mixer volume (0-255) */ static int jack_set_mixer_volume(int volume) { /* Not implemented */ return 0; } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_JACK, &digi_jack, TRUE, TRUE); } #endif #endif allegro-4.4.3.1/src/unix/uossmidi.c0000664000175000017500000003350713437077643016062 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Open Sound System sequencer support. * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_WITH_OSSMIDI #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #include #include #include #if defined(ALLEGRO_HAVE_SOUNDCARD_H) #include #elif defined(ALLEGRO_HAVE_SYS_SOUNDCARD_H) #include #elif defined(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) #include #elif defined(ALLEGRO_HAVE_LINUX_SOUNDCARD_H) #include #endif #include #if defined(ALLEGRO_HAVE_LINUX_AWE_VOICE_H) #include #define UOSSMIDI_HAVE_AWE32 #endif /* our patch data */ #include "../misc/fm_instr.h" #include "../misc/fm_emu.h" static int oss_midi_detect(int input); static int oss_midi_init(int input, int voices); static void oss_midi_exit(int input); static int oss_midi_set_mixer_volume(int volume); static int oss_midi_get_mixer_volume(void); static void oss_midi_key_on(int inst, int note, int bend, int vol, int pan); static void oss_midi_key_off(int voice); static void oss_midi_set_volume(int voice, int vol); static void oss_midi_set_pitch(int voice, int note, int bend); #define MAX_VOICES 256 static int seq_fd = -1; static int seq_device; static int seq_synth_type, seq_synth_subtype; static int seq_patch[MAX_VOICES]; static int seq_note[MAX_VOICES]; static int seq_drum_start; static char seq_desc[256] = EMPTY_STRING; static char seq_driver[256] = EMPTY_STRING; static char mixer_driver[256] = EMPTY_STRING; SEQ_DEFINEBUF(2048); MIDI_DRIVER midi_oss = { MIDI_OSS, empty_string, empty_string, "Open Sound System", 0, 0, 0xFFFF, 0, -1, -1, oss_midi_detect, oss_midi_init, oss_midi_exit, oss_midi_set_mixer_volume, oss_midi_get_mixer_volume, NULL, _dummy_load_patches, _dummy_adjust_patches, oss_midi_key_on, oss_midi_key_off, oss_midi_set_volume, oss_midi_set_pitch, _dummy_noop2, /* TODO */ _dummy_noop2 /* TODO */ }; /* as required by the OSS API */ void seqbuf_dump(void) { if (_seqbufptr) { write(seq_fd, _seqbuf, _seqbufptr); _seqbufptr = 0; } } /* attempt to open sequencer device */ static int seq_attempt_open(void) { char tmp1[128], tmp2[128], tmp3[128]; int fd; ustrzcpy(seq_driver, sizeof(seq_driver), get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("oss_midi_driver", tmp2), uconvert_ascii("/dev/sequencer", tmp3))); fd = open(uconvert_toascii(seq_driver, tmp1), O_WRONLY); if (fd < 0) uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: %s"), seq_driver, ustrerror(errno)); return fd; } /* find the best (supported) synth type for device */ static int seq_find_synth(int fd) { struct synth_info info; int num_synths, i; char *s; char tmp1[64], tmp2[256]; int score = 0, best_score, best_device; if (ioctl(fd, SNDCTL_SEQ_NRSYNTHS, &num_synths) == -1) return 0; best_device = -1; best_score = 0; /* Detect the best device */ for (i = 0; i < num_synths; i++) { info.device = i; if (ioctl(fd, SNDCTL_SYNTH_INFO, &info) == -1) return 0; switch (info.synth_type) { case SYNTH_TYPE_FM: /* FM synthesis is kind of ok */ score = 2; break; case SYNTH_TYPE_SAMPLE: /* Wavetable MIDI is cool! */ score = 3; break; case SYNTH_TYPE_MIDI: /* Only weird people want to use the MIDI out port... */ /* ... so we don't accept it yet, this can be fixed when * we've got a config file option to select the MIDI device * so then we'll only select this if people specifically * ask for it */ score = 0; break; } if (score > best_score) { best_score = score; best_device = i; } } if (best_score == 0) { return 0; } /* Cool, we got a decent synth type */ seq_device = best_device; /* Now get more information */ info.device = seq_device; if (ioctl(fd, SNDCTL_SYNTH_INFO, &info) == -1) return 0; seq_synth_type = info.synth_type; seq_synth_subtype = info.synth_subtype; midi_oss.voices = info.nr_voices; if (midi_oss.voices > MAX_VOICES) midi_oss.voices = MAX_VOICES; switch (seq_synth_type) { case SYNTH_TYPE_FM: switch (seq_synth_subtype) { case FM_TYPE_ADLIB: s = uconvert_ascii("Adlib", tmp1); break; case FM_TYPE_OPL3: s = uconvert_ascii("OPL3", tmp1); break; default: s = uconvert_ascii("FM (unknown)", tmp1); break; } break; case SYNTH_TYPE_SAMPLE: switch (seq_synth_subtype) { #ifdef UOSSMIDI_HAVE_AWE32 case SAMPLE_TYPE_AWE32: s = uconvert_ascii("AWE32", tmp1); break; #endif default: s = uconvert_ascii("sample (unknown)", tmp1); break; } break; case SYNTH_TYPE_MIDI: s = uconvert_ascii("MIDI out", tmp1); break; default: s = uconvert_ascii("Unknown synth", tmp1); break; } uszprintf(seq_desc, sizeof(seq_desc), uconvert_ascii("Open Sound System (%s)", tmp2), s); midi_driver->desc = seq_desc; return 1; } /* FM synth: load our instrument patches */ static void seq_set_fm_patches(int fd) { struct sbi_instrument ins; int i; ins.device = seq_device; ins.key = FM_PATCH; memset(ins.operators, 0, sizeof(ins.operators)); /* instruments */ for (i=0; i<128; i++) { ins.channel = i; memcpy(&ins.operators, &fm_instrument[i], sizeof(FM_INSTRUMENT)); write(fd, &ins, sizeof(ins)); } /* (emulated) drums */ for (i=0; i<47; i++) { ins.channel = 128+i; memset(ins.operators, 0, sizeof(ins.operators)); memcpy(&ins.operators, &fm_emulated_drum[i], sizeof(FM_INSTRUMENT)); write(fd, &ins, sizeof(ins)); } } /* FM synth setup */ static void seq_setup_fm (void) { seq_set_fm_patches(seq_fd); seq_drum_start = midi_oss.voices - 5; } #ifdef UOSSMIDI_HAVE_AWE32 /* AWE32 synth setup */ static void seq_setup_awe32 (void) { int bits = 0, drums; seq_drum_start = midi_oss.voices; if (seq_drum_start > 32) seq_drum_start = 32; /* These non-32 cases probably never happen, since the AWE32 has * 32 voices and anything higher needs a new interface... */ if (midi_oss.voices <= 1) { drums = 0; } else if (midi_oss.voices <= 4) { drums = 1; } else if (midi_oss.voices <= 32) { drums = midi_oss.voices / 8; } else { drums = 4; } #if 0 // I think I got this wrong /* Set the top 'drums' bits of bitfield and decrement seq_drum_start */ while (drums--) bits |= (1 << --seq_drum_start); #else /* The AWE driver seems to like receiving all percussion on MIDI channel * 10 (OSS channel 9) */ bits = (1<<9); seq_drum_start -= drums; #endif /* Tell the AWE which channels are drum channels. No, I don't know * what 'multi' mode is or how to play drums in the other modes. * This is just what playmidi does (except I'm using AWE_PLAY_MULTI * instead of its value, 1). */ AWE_SET_CHANNEL_MODE(seq_device, AWE_PLAY_MULTI); AWE_DRUM_CHANNELS(seq_device, bits); } #endif /* oss_midi_detect: * Sequencer detection routine. */ static int oss_midi_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } seq_fd = seq_attempt_open(); if (seq_fd < 0) return FALSE; close(seq_fd); return TRUE; } /* oss_midi_init: * Init the driver. */ static int oss_midi_init(int input, int voices) { char tmp1[128], tmp2[128], tmp3[128]; unsigned int i; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } seq_fd = seq_attempt_open(); if (seq_fd < 0) return -1; if (!seq_find_synth(seq_fd)) { close(seq_fd); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("No supported synth type found")); return -1; } ioctl(seq_fd, SNDCTL_SEQ_RESET); /* Driver-specific setup */ if (seq_synth_type == SYNTH_TYPE_FM) { seq_setup_fm(); } else if (seq_synth_type == SYNTH_TYPE_SAMPLE) { #ifdef UOSSMIDI_HAVE_AWE32 if (seq_synth_subtype == SAMPLE_TYPE_AWE32) { seq_setup_awe32(); } #endif } for (i = 0; i < (sizeof(seq_patch) / sizeof(int)); i++) { seq_patch[i] = -1; seq_note[i] = -1; } /* for the mixer routine */ ustrzcpy(mixer_driver, sizeof(mixer_driver), get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("oss_mixer_driver", tmp2), uconvert_ascii("/dev/mixer", tmp3))); return 0; } /* oss_midi_set_mixer_volume: * Sets the mixer volume for output. */ static int oss_midi_set_mixer_volume(int volume) { int fd, vol, ret; char tmp[128]; fd = open(uconvert_toascii(mixer_driver, tmp), O_WRONLY); if (fd < 0) return -1; vol = (volume * 100) / 255; vol = (vol << 8) | (vol); ret = ioctl(fd, MIXER_WRITE(SOUND_MIXER_SYNTH), &vol); close(fd); return ((ret == -1) ? -1 : 0); } /* oss_midi_get_mixer_volume: * Returns mixer volume. */ static int oss_midi_get_mixer_volume(void) { int fd, vol; char tmp[128]; fd = open(uconvert_toascii(mixer_driver, tmp), O_RDONLY); if (fd < 0) return -1; if (ioctl(fd, MIXER_READ(SOUND_MIXER_SYNTH), &vol) != 0) return -1; close(fd); vol = ((vol & 0xff) + (vol >> 8)) / 2; vol = vol * 255 / 100; return vol; } /* get_hardware_voice: * Get the hardware voice corresponding to this virtual voice. The * hardware may support more than one note per voice, in which case * you don't want to terminate old notes on reusing a voice, but when * Allegro reuses a voice it forgets the old note and won't ever send * a keyoff. So we should use more virtual (Allegro) voices than the * channels the hardware provides, and map them down to actual * hardware channels here. * * We also swap voices 9 and 15 (MIDI 10 and 16). This is necessary * because _midi_allocate_voice can only allocate in continuous ranges * -- so we use voices [0,seq_drum_start) for melody and for the * percussion [seq_drum_start,max_voices), as far as Allegro is * concerned. But hardware likes percussion on MIDI 10, so we need to * remap it. */ static int get_hardware_voice (int voice) { int hwvoice = voice; /* FIXME: is this OK/useful for other things than AWE32? */ if (seq_synth_type != SYNTH_TYPE_FM && seq_drum_start > 0) { /* map drums >= 15, everything else < 15 */ hwvoice = hwvoice * 15 / seq_drum_start; /* fix up so drums are on MIDI channel 10 */ if (hwvoice >= 15) hwvoice = 9; else if (hwvoice == 9) hwvoice = 15; } return hwvoice; } /* oss_midi_key_on: * Triggers the specified voice. */ static void oss_midi_key_on(int inst, int note, int bend, int vol, int pan) { int voice, hwvoice; int is_percussion = 0; /* percussion? */ if (inst > 127) { voice = _midi_allocate_voice(seq_drum_start, midi_driver->voices-1); /* TODO: Peter's code decrements inst by 35; but the AWE driver * ignores inst completely, using note instead, as God (well, GM) * intended. Does the FM driver ignore note? If so then we're OK. */ note = inst-128; inst -= 35; is_percussion = 1; } else voice = _midi_allocate_voice(0, seq_drum_start-1); if (voice < 0) return; /* Get the hardware voice corresponding to this virtual voice. */ hwvoice = get_hardware_voice (voice); /* FIXME: should we do this or not for FM? */ if (seq_synth_type != SYNTH_TYPE_FM) { /* Stop any previous note on this voice -- but not if it's percussion */ if (!is_percussion && seq_note[voice] != -1) { SEQ_STOP_NOTE(seq_device, hwvoice, seq_note[voice], 64); } } seq_note[voice] = note; /* make sure the (hardware) voice is set up with the right sound */ if (inst != seq_patch[hwvoice]) { SEQ_SET_PATCH(seq_device, hwvoice, inst); seq_patch[hwvoice] = inst; } SEQ_CONTROL(seq_device, hwvoice, CTL_PAN, pan); SEQ_BENDER(seq_device, hwvoice, 8192 + bend); SEQ_START_NOTE(seq_device, hwvoice, note, vol); SEQ_DUMPBUF(); } /* oss_midi_key_off: * Insert witty remark about this line being unhelpful. */ static void oss_midi_key_off(int voice) { /* Get the hardware voice corresponding to this virtual voice. */ int hwvoice = get_hardware_voice (voice); SEQ_STOP_NOTE(seq_device, hwvoice, seq_note[voice], 64); SEQ_DUMPBUF(); seq_note[voice] = -1; } /* oss_midi_set_volume: * Sets the volume of the specified voice. */ static void oss_midi_set_volume(int voice, int vol) { SEQ_CONTROL(seq_device, voice, CTL_MAIN_VOLUME, vol); } /* oss_midi_set_pitch: * Sets the pitch of the specified voice. */ static void oss_midi_set_pitch(int voice, int note, int bend) { SEQ_CONTROL(seq_device, voice, CTRL_PITCH_BENDER, 8192 + bend); } /* oss_midi_exit: * Cleanup when we are finished. */ static void oss_midi_exit(int input) { if (input) return; if (seq_fd > 0) { close(seq_fd); seq_fd = -1; } } #endif allegro-4.4.3.1/src/unix/alsamidi.c0000664000175000017500000001577513437077643016020 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * ALSA RawMIDI Sound driver. * * By Thomas Fjellstrom. * * See readme.txt for copyright information. */ #include "allegro.h" #if (defined ALLEGRO_WITH_ALSAMIDI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #ifdef ALLEGRO_QNX #include "allegro/platform/aintqnx.h" #else #include "allegro/platform/aintunix.h" #endif #ifndef SCAN_DEPEND #include #include #include #include #if ALLEGRO_ALSA_VERSION == 9 #define ALSA_PCM_NEW_HW_PARAMS_API 1 #include #else /* ALLEGRO_ALSA_VERSION == 5 */ #include #endif #endif #define ALSA_RAWMIDI_MAX_ERRORS 3 static int alsa_rawmidi_detect(int input); static int alsa_rawmidi_init(int input, int voices); static void alsa_rawmidi_exit(int input); static void alsa_rawmidi_output(int data); static char alsa_rawmidi_desc[256]; static snd_rawmidi_t *rawmidi_handle = NULL; static int alsa_rawmidi_errors = 0; MIDI_DRIVER midi_alsa = { MIDI_ALSA, /* id */ empty_string, /* name */ empty_string, /* desc */ "ALSA RawMIDI", /* ASCII name */ 0, /* voices */ 0, /* basevoice */ 0xFFFF, /* max_voices */ 0, /* def_voices */ -1, /* xmin */ -1, /* xmax */ alsa_rawmidi_detect, /* detect */ alsa_rawmidi_init, /* init */ alsa_rawmidi_exit, /* exit */ NULL, /* set_mixer_volume */ NULL, /* get_mixer_volume */ alsa_rawmidi_output, /* raw_midi */ _dummy_load_patches, /* load_patches */ _dummy_adjust_patches, /* adjust_patches */ _dummy_key_on, /* key_on */ _dummy_noop1, /* key_off */ _dummy_noop2, /* set_volume */ _dummy_noop3, /* set_pitch */ _dummy_noop2, /* set_pan */ _dummy_noop2 /* set_vibrato */ }; /* alsa_rawmidi_detect: * ALSA RawMIDI detection. */ static int alsa_rawmidi_detect(int input) { #if ALLEGRO_ALSA_VERSION == 9 const char *device = NULL; #else /* ALLEGRO_ALSA_VERSION == 5 */ int card = -1; int device = -1; #endif int ret = FALSE, err; char tmp1[128], tmp2[128], temp[256]; snd_rawmidi_t *handle = NULL; if (input) { ret = FALSE; } else { #if ALLEGRO_ALSA_VERSION == 9 device = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_device", tmp2), "default"); err = snd_rawmidi_open(NULL, &handle, device, 0); #else /* ALLEGRO_ALSA_VERSION == 5 */ card = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_card", tmp2), snd_defaults_rawmidi_card()); device = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_device", tmp2), snd_defaults_rawmidi_device()); err = snd_rawmidi_open(&handle, card, device, SND_RAWMIDI_OPEN_OUTPUT_APPEND); #endif if (err) { snprintf(temp, sizeof(temp), "Could not open card/rawmidi device: %s", snd_strerror(err)); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(temp)); ret = FALSE; } else { snd_rawmidi_close(handle); ret = TRUE; } } return ret; } /* alsa_rawmidi_init: * Inits the ALSA RawMIDI interface. */ static int alsa_rawmidi_init(int input, int voices) { int ret, err; char tmp1[128], tmp2[128], temp[256]; #if ALLEGRO_ALSA_VERSION == 9 snd_rawmidi_info_t *info; const char *device = NULL; #else /* ALLEGRO_ALSA_VERSION == 5 */ snd_rawmidi_info_t info; int card = -1; int device = -1; #endif if (input) { ret = -1; } else { #if ALLEGRO_ALSA_VERSION == 9 device = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_device", tmp2), "default"); err = snd_rawmidi_open(NULL, &rawmidi_handle, device, 0); #else /* ALLEGRO_ALSA_VERSION == 5 */ card = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_card", tmp2), snd_defaults_rawmidi_card()); device = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_rawmidi_device", tmp2), snd_defaults_rawmidi_device()); err = snd_rawmidi_open(&rawmidi_handle, card, device, SND_RAWMIDI_OPEN_OUTPUT_APPEND); #endif if (err) { snprintf(temp, sizeof(temp), "Could not open card/rawmidi device: %s", snd_strerror(err)); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(temp)); ret = -1; } else { ret = 0; } } if (rawmidi_handle) { #if ALLEGRO_ALSA_VERSION == 9 snd_rawmidi_nonblock(rawmidi_handle, 0); snd_rawmidi_info_malloc(&info); snd_rawmidi_info(rawmidi_handle, info); _al_sane_strncpy(alsa_rawmidi_desc, snd_rawmidi_info_get_name(info), sizeof(alsa_rawmidi_desc)); #else /* ALLEGRO_ALSA_VERSION == 5 */ snd_rawmidi_block_mode(rawmidi_handle, 1); snd_rawmidi_info(rawmidi_handle, &info); _al_sane_strncpy(alsa_rawmidi_desc, info.name, sizeof(alsa_rawmidi_desc)); #endif midi_alsa.desc = alsa_rawmidi_desc; alsa_rawmidi_errors = 0; } return ret; } /* alsa_rawmidi_exit: * Cleans up. */ static void alsa_rawmidi_exit(int input) { if (rawmidi_handle) { #if ALLEGRO_ALSA_VERSION == 9 snd_rawmidi_drain(rawmidi_handle); #else /* ALLEGRO_ALSA_VERSION == 5 */ snd_rawmidi_output_drain(rawmidi_handle); #endif snd_rawmidi_close(rawmidi_handle); } rawmidi_handle = NULL; } /* alsa_rawmidi_output: * Outputs MIDI data. */ static void alsa_rawmidi_output(int data) { int err; /* If there are too many errors, just give up. Otherwise the calling thread * can end up consuming CPU time for no reason. It probably means the user * hasn't configured ALSA properly. */ if (alsa_rawmidi_errors > ALSA_RAWMIDI_MAX_ERRORS) { return; } err = snd_rawmidi_write(rawmidi_handle, &data, sizeof(char)); if (err) { alsa_rawmidi_errors++; if (alsa_rawmidi_errors == ALSA_RAWMIDI_MAX_ERRORS) { TRACE("al-alsamidi: too many errors, giving up\n"); } } } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_midi_driver(MIDI_ALSA, &midi_alsa, TRUE, TRUE); } #endif /* ALLEGRO_MODULE */ #endif /* MIDI_ALSA */ allegro-4.4.3.1/src/unix/ugfxdrv.c0000664000175000017500000000131113437077643015677 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of Unix graphics drivers. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" /* list the available drivers */ BEGIN_GFX_DRIVER_LIST END_GFX_DRIVER_LIST allegro-4.4.3.1/src/unix/usnddrv.c0000664000175000017500000000266413437077643015713 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of Unix sound drivers. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" BEGIN_DIGI_DRIVER_LIST #if (defined ALLEGRO_WITH_JACKDIGI) && (!defined ALLEGRO_WITH_MODULES) DIGI_DRIVER_JACK #endif #if (defined ALLEGRO_WITH_SGIALDIGI) && (!defined ALLEGRO_WITH_MODULES) DIGI_DRIVER_SGIAL #endif #if (defined ALLEGRO_WITH_ARTSDIGI) && (!defined ALLEGRO_WITH_MODULES) DIGI_DRIVER_ARTS #endif #if (defined ALLEGRO_WITH_ESDDIGI) && (!defined ALLEGRO_WITH_MODULES) DIGI_DRIVER_ESD #endif #if (defined ALLEGRO_WITH_ALSADIGI) && (!defined ALLEGRO_WITH_MODULES) DIGI_DRIVER_ALSA #endif #if (defined ALLEGRO_WITH_OSSDIGI) DIGI_DRIVER_OSS #endif END_DIGI_DRIVER_LIST BEGIN_MIDI_DRIVER_LIST MIDI_DRIVER_DIGMID #if (defined ALLEGRO_WITH_ALSAMIDI) && (!defined ALLEGRO_WITH_MODULES) MIDI_DRIVER_ALSA #endif #if (defined ALLEGRO_WITH_OSSMIDI) MIDI_DRIVER_OSS #endif END_MIDI_DRIVER_LIST allegro-4.4.3.1/src/unix/uptimer.c0000664000175000017500000001137413437077643015711 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Timer module for Unix, using pthreads. * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #ifdef ALLEGRO_HAVE_LIBPTHREAD #include #include #include #include /* See hack later. */ #ifdef ALLEGRO_LINUX_VGA #ifdef ALLEGRO_HAVE_SYS_IO_H /* iopl() exists in here instead of unistd.h in glibc */ #include #endif #include "allegro/platform/aintlnx.h" #endif #define TIMER_TO_USEC(x) ((long)((x) / 1.193181)) #define USEC_TO_TIMER(x) ((long)((x) * (TIMERS_PER_SECOND / 1000000.))) static int ptimer_init(void); static void ptimer_exit(void); TIMER_DRIVER timerdrv_unix_pthreads = { TIMERDRV_UNIX_PTHREADS, empty_string, empty_string, "Unix pthreads timers", ptimer_init, ptimer_exit, NULL, NULL, /* install_int, remove_int */ NULL, NULL, /* install_param_int, remove_param_int */ NULL, NULL, /* can_simulate_retrace, simulate_retrace */ _unix_rest /* rest */ }; static pthread_t thread; static int thread_alive; static void block_all_signals(void) { #ifndef ALLEGRO_MACOSX sigset_t mask; sigfillset(&mask); pthread_sigmask(SIG_BLOCK, &mask, NULL); #endif } /* ptimer_thread_func: * The timer thread. */ static void *ptimer_thread_func(void *unused) { struct timeval old_time; struct timeval new_time; struct timeval delay; long interval = 0x8000; #ifdef ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK struct timespec old_time_ns; struct timespec new_time_ns; int clock_monotonic; #endif block_all_signals(); #ifdef ALLEGRO_LINUX_VGA /* privileges hack for Linux: * One of the jobs of the timer thread is to update the mouse pointer * on screen. When using the Mode-X driver under Linux console, this * involves selecting different planes (in modexgfx.s), which requires * special priviledges. */ if ((system_driver == &system_linux) && (__al_linux_have_ioperms)) { seteuid(0); iopl(3); seteuid(getuid()); } #endif #ifdef ALLEGRO_QNX /* thread priority adjustment for QNX: * The timer thread is set to the highest relative priority. * (see the comment in src/qnx/qsystem.c about the scheduling policy) */ { struct sched_param sparam; int spolicy; if (pthread_getschedparam(pthread_self(), &spolicy, &sparam) == EOK) { sparam.sched_priority += 4; pthread_setschedparam(pthread_self(), spolicy, &sparam); } } #endif #ifdef ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK /* clock_gettime(CLOCK_MONOTONIC, ...) is preferable to gettimeofday() in * case the system time is changed while the program is running. * CLOCK_MONOTONIC is not available on all systems. */ clock_monotonic = (clock_gettime(CLOCK_MONOTONIC, &old_time_ns) == 0); #endif gettimeofday(&old_time, 0); while (thread_alive) { /* `select' is more accurate than `usleep' on my system. */ delay.tv_sec = interval / TIMERS_PER_SECOND; delay.tv_usec = TIMER_TO_USEC(interval) % 1000000L; select(0, NULL, NULL, NULL, &delay); /* Calculate actual time elapsed. */ #ifdef ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK if (clock_monotonic) { clock_gettime(CLOCK_MONOTONIC, &new_time_ns); interval = USEC_TO_TIMER( (new_time_ns.tv_sec - old_time_ns.tv_sec) * 1000000L + (new_time_ns.tv_nsec - old_time_ns.tv_nsec) / 1000); old_time_ns = new_time_ns; } else #endif { gettimeofday(&new_time, 0); interval = USEC_TO_TIMER( (new_time.tv_sec - old_time.tv_sec) * 1000000L + (new_time.tv_usec - old_time.tv_usec)); old_time = new_time; } /* Handle a tick. */ interval = _handle_timer_tick(interval); } return NULL; } /* ptimer_init: * Installs the timer thread. */ static int ptimer_init(void) { thread_alive = 1; if (pthread_create(&thread, NULL, ptimer_thread_func, NULL) != 0) { thread_alive = 0; return -1; } return 0; } /* ptimer_exit: * Shuts down the timer thread. */ static void ptimer_exit(void) { if (thread_alive) { thread_alive = 0; pthread_join(thread, NULL); } } #endif allegro-4.4.3.1/src/unix/umain.c0000664000175000017500000000214213437077643015326 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Replacement for main to capture name of executable file. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro/internal/alconfig.h" #ifdef ALLEGRO_WITH_MAGIC_MAIN #undef main extern int __crt0_argc; extern char **__crt0_argv; extern void *_mangled_main_address; /* main: * Replacement for main function (capture arguments and call real main). */ int main(int argc, char *argv[]) { int (*real_main) (int, char*[]) = (int (*) (int, char*[])) _mangled_main_address; __crt0_argc = argc; __crt0_argv = argv; return (*real_main)(argc, argv); } #endif allegro-4.4.3.1/src/unix/usystem.c0000664000175000017500000003140713437077643015734 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of system drivers for the Unix library. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include #include #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #if defined(ALLEGRO_HAVE_SCHED_YIELD) && defined(_POSIX_PRIORITY_SCHEDULING) /* ALLEGRO_HAVE_SCHED_YIELD is set by configure */ /* Manpages say systems providing sched_yield() define * _POSIX_PRIORITY_SCHEDULING in unistd.h */ #include #else #include #endif #ifdef ALLEGRO_HAVE_SYS_UTSNAME_H #include #endif #ifdef ALLEGRO_HAVE_SV_PROCFS_H #include #include #include #endif /* list the available drivers */ _DRIVER_INFO _system_driver_list[] = { #ifdef ALLEGRO_WITH_XWINDOWS { SYSTEM_XWINDOWS, &system_xwin, TRUE }, #endif #ifdef ALLEGRO_LINUX { SYSTEM_LINUX, &system_linux, TRUE }, #endif #ifdef ALLEGRO_QNX { SYSTEM_QNX, &system_qnx, TRUE }, #endif #ifdef ALLEGRO_MACOSX { SYSTEM_MACOSX, &system_macosx, TRUE }, #endif { SYSTEM_NONE, &system_none, FALSE }, { 0, NULL, 0 } }; #ifndef ALLEGRO_MACOSX /* background function manager */ struct bg_manager *_unix_bg_man; #endif /* _unix_find_resource: * Helper for locating a Unix config file. Looks in the home directory * of the current user, and in /etc. */ int _unix_find_resource(char *dest, AL_CONST char *resource, int size) { char buf[256], tmp[256], *last; char *home = getenv("HOME"); if (home) { /* look for ~/file */ append_filename(buf, uconvert_ascii(home, tmp), resource, sizeof(buf)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } /* if it is a .cfg, look for ~/.filerc */ if (ustricmp(get_extension(resource), uconvert_ascii("cfg", tmp)) == 0) { ustrzcpy(buf, sizeof(buf) - ucwidth(OTHER_PATH_SEPARATOR), uconvert_ascii(home, tmp)); put_backslash(buf); ustrzcat(buf, sizeof(buf), uconvert_ascii(".", tmp)); ustrzcpy(tmp, sizeof(tmp), resource); ustrzcat(buf, sizeof(buf), ustrtok_r(tmp, ".", &last)); ustrzcat(buf, sizeof(buf), uconvert_ascii("rc", tmp)); if (file_exists(buf, FA_ARCH | FA_RDONLY | FA_HIDDEN, NULL)) { ustrzcpy(dest, size, buf); return 0; } } } /* look for /etc/file */ append_filename(buf, uconvert_ascii("/etc/", tmp), resource, sizeof(buf)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } /* if it is a .cfg, look for /etc/filerc */ if (ustricmp(get_extension(resource), uconvert_ascii("cfg", tmp)) == 0) { ustrzcpy(buf, sizeof(buf), uconvert_ascii("/etc/", tmp)); ustrzcpy(tmp, sizeof(tmp), resource); ustrzcat(buf, sizeof(buf), ustrtok_r(tmp, ".", &last)); ustrzcat(buf, sizeof(buf), uconvert_ascii("rc", tmp)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } } /* if it is a .dat, look in /usr/share/ and /usr/local/share/ */ if (ustricmp(get_extension(resource), uconvert_ascii("dat", tmp)) == 0) { ustrzcpy(buf, sizeof(buf), uconvert_ascii("/usr/share/allegro/", tmp)); ustrzcat(buf, sizeof(buf), resource); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } ustrzcpy(buf, sizeof(buf), uconvert_ascii("/usr/local/share/allegro/", tmp)); ustrzcat(buf, sizeof(buf), resource); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } } return -1; } #ifndef ALLEGRO_MACOSX /* _unix_read_os_type: * Set the os_type variable to something sensible. */ void _unix_read_os_type(void) { #ifdef ALLEGRO_HAVE_SYS_UTSNAME_H struct utsname utsn; char *tmpstr, *tmpstr2; size_t pos; uname(&utsn); /* fetch OS version and revision */ tmpstr = _AL_MALLOC_ATOMIC(strlen(utsn.release)+1); _al_sane_strncpy(tmpstr, utsn.release, strlen(utsn.release)+1); tmpstr2 = NULL; for (pos = 0; pos <= strlen(utsn.release); pos++) { if (tmpstr[pos] == '.') { tmpstr[pos] = '\0'; if (!tmpstr2) tmpstr2 = tmpstr + pos + 1; } } os_version = atoi(tmpstr); os_revision = atoi(tmpstr2); _AL_FREE(tmpstr); /* try to detect Unix systems we know of */ if (!strcmp(utsn.sysname, "Linux")) { os_type = OSTYPE_LINUX; } else if (!strcmp(utsn.sysname, "SunOS")) { os_type = OSTYPE_SUNOS; } else if (!strcmp(utsn.sysname, "FreeBSD")) { os_type = OSTYPE_FREEBSD; } else if (!strcmp(utsn.sysname, "NetBSD")) { os_type = OSTYPE_NETBSD; } else if (!strcmp(utsn.sysname, "OpenBSD")) { os_type = OSTYPE_OPENBSD; } else if ((!strcmp(utsn.sysname, "IRIX")) || (!strcmp(utsn.sysname, "IRIX64"))) { os_type = OSTYPE_IRIX; } else if (!strcmp(utsn.sysname, "Darwin")) { os_type = OSTYPE_DARWIN; } else if (!strcmp(utsn.sysname, "QNX")) { os_type = OSTYPE_QNX; } else { os_type = OSTYPE_UNIX; /* that's all we can say for now */ } #else os_type = OSTYPE_UNIX; #endif os_multitasking = TRUE; } #endif /* _unix_sysdrv_yield_timeslice: * Yields remaining timeslice portion to the system */ void _unix_yield_timeslice(void) { /* Some of our example programs, which used to draw as fast as possible, * caused input events from the X server to be *severely* delayed. * This was always a problem with the Allegro input model, even in 1999. * The usual workaround was to back off a little by inserting calls to * rest(0) in the program. That would end up calling sched_yield() or * select() with zero timeout. * * However, neither of those implementations have the intended effect in * 2011. This is possibly due to multi-core machines, changes to the Linux * scheduler, changes in X11, or some combination of the above. * We now call select() with a non-zero timeout. */ struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 1; select(0, NULL, NULL, NULL, &timeout); } #ifndef ALLEGRO_MACOSX /* _find_executable_file: * Helper function: searches path and current directory for executable. * Returns 1 on succes, 0 on failure. */ static int _find_executable_file(const char *filename, char *output, int size) { char *path; /* If filename has an explicit path, search current directory */ if (strchr (filename, '/')) { if (filename[0] == '/') { /* Full path; done */ do_uconvert (filename, U_ASCII, output, U_CURRENT, size); return 1; } else { struct stat finfo; char pathname[1024]; int len; /* Prepend current directory */ getcwd(pathname, sizeof(pathname)); len = strlen(pathname); pathname[len] = '/'; _al_sane_strncpy (pathname+len+1, filename, strlen(filename)); if ((stat(pathname, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) { do_uconvert (pathname, U_ASCII, output, U_CURRENT, size); return 1; } } } /* If filename has no explicit path, but we do have $PATH, search there */ else if ((path = getenv("PATH"))) { char *start = path, *end = path, *buffer = NULL, *temp; struct stat finfo; while (*end) { end = strchr (start, ':'); if (!end) end = strchr (start, '\0'); /* Resize `buffer' for path component, slash, filename and a '\0' */ temp = _AL_REALLOC (buffer, end - start + 1 + strlen (filename) + 1); if (temp) { buffer = temp; _al_sane_strncpy (buffer, start, end - start); *(buffer + (end - start)) = '/'; _al_sane_strncpy (buffer + (end - start) + 1, filename, end - start + 1 + strlen (filename) + 1); if ((stat(buffer, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) { do_uconvert (buffer, U_ASCII, output, U_CURRENT, size); _AL_FREE (buffer); return 1; } } /* else... ignore the failure; `buffer' is still valid anyway. */ start = end + 1; } /* Path search failed */ _AL_FREE (buffer); } return 0; } /* _unix_get_executable_name: * Return full path to the current executable, use proc fs if available. */ void _unix_get_executable_name(char *output, int size) { #ifdef ALLEGRO_HAVE_SV_PROCFS_H struct prpsinfo psinfo; int fd; #endif char linkname[1024]; char filename[1024]; struct stat finfo; FILE *pipe; pid_t pid; int len; #ifdef ALLEGRO_HAVE_GETEXECNAME { const char *s = getexecname(); if (s) { if (s[0] == '/') { /* Absolute path */ do_uconvert (s, U_ASCII, output, U_CURRENT, size); return; } else { /* Not an absolute path */ if (_find_executable_file(s, output, size)) return; } } } #endif /* We need the PID in order to query procfs */ pid = getpid(); /* Try a Linux-like procfs */ /* get symolic link to executable from proc fs */ sprintf (linkname, "/proc/%d/exe", (int)pid); if (stat (linkname, &finfo) == 0) { len = readlink (linkname, filename, sizeof(filename)-1); if (len>-1) { filename[len] = '\0'; do_uconvert (filename, U_ASCII, output, U_CURRENT, size); return; } } /* Use System V procfs calls if available */ #ifdef ALLEGRO_HAVE_SV_PROCFS_H sprintf (linkname, "/proc/%d/exe", (int)pid); fd = open(linkname, O_RDONLY); if (fd != -1) { ioctl(fd, PIOCPSINFO, &psinfo); close(fd); /* Use argv[0] directly if we can */ #ifdef ALLEGRO_HAVE_PROCFS_ARGCV if (psinfo.pr_argv && psinfo.pr_argc) { if (_find_executable_file(psinfo.pr_argv[0], output, size)) return; } else #endif { /* Emulate it */ /* We use the pr_psargs field to find argv[0] * This is better than using the pr_fname field because we need * the additional path information that may be present in argv[0] */ /* Skip other args */ char *s = strchr(psinfo.pr_psargs, ' '); if (s) s[0] = '\0'; if (_find_executable_file(psinfo.pr_psargs, output, size)) return; } /* Try the pr_fname just for completeness' sake if argv[0] fails */ if (_find_executable_file(psinfo.pr_fname, output, size)) return; } #endif /* Last resort: try using the output of the ps command to at least find */ /* the name of the file if not the full path */ uszprintf (linkname, sizeof(linkname), "ps -p %d", (int)pid); do_uconvert (linkname, U_CURRENT, filename, U_ASCII, size); pipe = popen(filename, "r"); if (pipe) { /* The first line of output is a header */ fgets(linkname, sizeof(linkname), pipe); /* The information we want is in the last column; find it */ len = strlen(linkname); while (linkname[len] != ' ' && linkname[len] != '\t') len--; /* The second line contains the info we want */ fgets(linkname, sizeof(linkname), pipe); pclose(pipe); /* Treat special cases: filename between [] and - for login shell */ if (linkname[len] == '-') len++; if (linkname[len] == '[' && linkname[strlen(linkname)] == ']') { len++; linkname[strlen(linkname)] = '\0'; } /* Now, the filename should be in the last column */ _al_sane_strncpy (filename, linkname+len+1, strlen(linkname)-len+1); if (_find_executable_file(filename, output, size)) return; /* Just return the output from ps... */ do_uconvert (filename, U_ASCII, output, U_CURRENT, size); return; } #ifdef ALLEGRO_WITH_MAGIC_MAIN /* Try the captured argv[0] */ if (_find_executable_file(__crt0_argv[0], output, size)) return; #endif /* Give up; return empty string */ do_uconvert ("", U_ASCII, output, U_CURRENT, size); } #endif /* _unix_get_page_size: * Get size of a memory page in bytes. If we can't do it, we make a guess. */ size_t _unix_get_page_size(void) { #if defined(ALLEGRO_HAVE_SYSCONF) && defined(_SC_PAGESIZE) long page_size = sysconf(_SC_PAGESIZE); #else long page_size = -1; #endif return (page_size == -1) ? 4096 : page_size; } allegro-4.4.3.1/src/unix/utimer.c0000664000175000017500000000604413437077643015527 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Unix timer module. * * By Peter Wang. * * _unix_rest by Elias Pschernig. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/platform/aintunix.h" #include #ifndef ALLEGRO_MACOSX /* System drivers provide their own lists, so this is just to keep the * Allegro framework happy. */ _DRIVER_INFO _timer_driver_list[] = { { 0, 0, 0 } }; #endif /* timeval_subtract: * Subtract the `struct timeval' values X and Y, storing the result * in RESULT. Return 1 if the difference is negative, otherwise 0. * * This function is from the glibc manual. It handles weird platforms * where the tv_sec is unsigned. */ static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) { /* Perform the carry for the later subtraction by updating Y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. * `tv_usec' is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; } void _unix_rest(unsigned int ms, void (*callback) (void)) { if (callback) { struct timeval tv, tv_end; gettimeofday (&tv_end, NULL); tv_end.tv_usec += ms * 1000; tv_end.tv_sec += (tv_end.tv_usec / 1000000L); tv_end.tv_usec %= 1000000L; while (1) { (*callback)(); gettimeofday (&tv, NULL); if (tv.tv_sec > tv_end.tv_sec) break; if (tv.tv_sec == tv_end.tv_sec && tv.tv_usec >= tv_end.tv_usec) break; } } else { struct timeval now; struct timeval end; struct timeval delay; int result; gettimeofday(&now, NULL); end = now; end.tv_usec += ms * 1000; end.tv_sec += (end.tv_usec / 1000000L); end.tv_usec %= 1000000L; while (1) { if (timeval_subtract(&delay, &end, &now)) break; #ifdef ALLEGRO_MACOSX result = usleep((delay.tv_sec * 1000000L) + delay.tv_usec); #else result = select(0, NULL, NULL, NULL, &delay); #endif if (result == 0) /* ok */ break; if ((result != -1) || (errno != EINTR)) break; /* interrupted */ gettimeofday(&now, NULL); } } } allegro-4.4.3.1/src/unix/usigalrm.c0000664000175000017500000001566713437077643016060 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Asynchronous event processing with SIGALRM. * * By Michael Bukin. * * Distorted by George Foot. * * Mangled by Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_QNX #include "allegro/platform/aintqnx.h" #else #include "allegro/platform/aintunix.h" #endif #ifndef ALLEGRO_HAVE_LIBPTHREAD #include #include #include #include static int _sigalrm_already_installed = FALSE; static volatile int _sigalrm_interrupt_pending = FALSE; static volatile int _sigalrm_cli_count = 0; static volatile int _sigalrm_abort_requested = FALSE; static volatile int _sigalrm_aborting = FALSE; static void (*_sigalrm_interrupt_handler)(unsigned long interval) = 0; void (*_sigalrm_timer_interrupt_handler)(unsigned long interval) = 0; static RETSIGTYPE (*_sigalrm_old_signal_handler)(int num) = 0; static RETSIGTYPE _sigalrm_signal_handler(int num); static int first_time = TRUE; /* _sigalrm_disable_interrupts: * Disables "interrupts". */ static void _sigalrm_disable_interrupts(void) { _sigalrm_cli_count++; } /* _sigalrm_enable_interrupts: * Enables "interrupts.". */ void _sigalrm_enable_interrupts(void) { if (--_sigalrm_cli_count == 0) { /* Process pending interrupts. */ first_time = TRUE; if (_sigalrm_interrupt_pending) { _sigalrm_interrupt_pending = FALSE; _sigalrm_signal_handler(SIGALRM); } } else if (_sigalrm_cli_count < 0) { abort(); } } /* _sigalrm_interrupts_disabled: * Tests if interrupts are disabled. */ static int _sigalrm_interrupts_disabled(void) { return _sigalrm_cli_count; } static struct timeval old_time; static struct timeval new_time; /* _sigalrm_time_passed: * Calculates time passed since last call to this function. */ static unsigned long _sigalrm_time_passed(void) { unsigned long interval; gettimeofday(&new_time, 0); if (!first_time) { interval = ((new_time.tv_sec - old_time.tv_sec) * 1000000L + (new_time.tv_usec - old_time.tv_usec)); } else { first_time = FALSE; interval = 0; } old_time = new_time; return interval; } /* _sigalrm_do_abort: * Aborts program (interrupts will be enabled on entry). */ static void _sigalrm_do_abort(void) { /* Someday, it may choose to abort or exit, depending on user choice. */ if (!_sigalrm_aborting) { _sigalrm_aborting = TRUE; exit(EXIT_SUCCESS); } } /* _sigalrm_request_abort: * Requests interrupt-safe abort (abort with enabled interrupts). */ void _sigalrm_request_abort(void) { if (_sigalrm_interrupts_disabled()) _sigalrm_abort_requested = TRUE; else _sigalrm_do_abort(); } /* _sigalrm_start_timer: * Starts timer in one-shot mode. */ static void _sigalrm_start_timer(void) { struct itimerval timer; _sigalrm_old_signal_handler = signal(SIGALRM, _sigalrm_signal_handler); timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 0; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 10000; /* 10 ms */ setitimer(ITIMER_REAL, &timer, 0); } /* _sigalrm_stop_timer: * Stops timer. */ static void _sigalrm_stop_timer(void) { struct itimerval timer; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 0; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &timer, 0); signal(SIGALRM, _sigalrm_old_signal_handler); } /* _sigalrm_signal_handler: * Handler for SIGALRM signal. */ static RETSIGTYPE _sigalrm_signal_handler(int num) { unsigned long interval, i; int err; if (_sigalrm_interrupts_disabled()) { _sigalrm_interrupt_pending = TRUE; return; } err = errno; interval = _sigalrm_time_passed(); while (interval) { i = MIN(interval, INT_MAX/(TIMERS_PER_SECOND/100)); interval -= i; i = i * (TIMERS_PER_SECOND/100) / 10000L; if (_sigalrm_interrupt_handler) (*_sigalrm_interrupt_handler)(i); if (_sigalrm_timer_interrupt_handler) (*_sigalrm_timer_interrupt_handler)(i); } /* Abort with enabled interrupts. */ if (_sigalrm_abort_requested) _sigalrm_do_abort(); _sigalrm_start_timer(); errno = err; } /* _sigalrm_init: * Starts interrupts processing. */ static int _sigalrm_init(void (*handler)(unsigned long interval)) { if (_sigalrm_already_installed) return -1; _sigalrm_already_installed = TRUE; _sigalrm_interrupt_handler = handler; _sigalrm_interrupt_pending = FALSE; _sigalrm_cli_count = 0; first_time = TRUE; _sigalrm_start_timer(); return 0; } /* _sigalrm_exit: * Stops interrupts processing. */ static void _sigalrm_exit(void) { if (!_sigalrm_already_installed) return; _sigalrm_stop_timer(); _sigalrm_interrupt_handler = 0; _sigalrm_interrupt_pending = FALSE; _sigalrm_cli_count = 0; _sigalrm_already_installed = FALSE; } /*============================================================ * SIGALRM bg_manager *-----------------------------------------------------------*/ #define MAX_FUNCS 16 static bg_func funcs[MAX_FUNCS]; static int max_func; /* highest+1 used entry */ static void bg_man_sigalrm_handler(unsigned long interval) { int i; for (i = 0; i < max_func; i++) if (funcs[i]) funcs[i](0); } static int bg_man_sigalrm_init(void) { return _sigalrm_init(bg_man_sigalrm_handler); } static void bg_man_sigalrm_exit(void) { _sigalrm_exit(); } static int bg_man_sigalrm_register_func(bg_func f) { int i; for (i = 0; funcs[i] && i < MAX_FUNCS; i++); if (i == MAX_FUNCS) return -1; funcs[i] = f; if (i == max_func) max_func++; return 0; } static int bg_man_sigalrm_unregister_func(bg_func f) { int i; for (i = 0; funcs[i] != f && i < max_func; i++); if (i == max_func) return -1; funcs[i] = NULL; if (i+1 == max_func) do { max_func--; } while ((max_func > 0) && !funcs[max_func-1]); return 0; } static void bg_man_sigalrm_enable_interrupts(void) { _sigalrm_enable_interrupts(); } static void bg_man_sigalrm_disable_interrupts(void) { _sigalrm_disable_interrupts(); } static int bg_man_sigalrm_interrupts_disabled(void) { return _sigalrm_interrupts_disabled(); } struct bg_manager _bg_man_sigalrm = { 0, bg_man_sigalrm_init, bg_man_sigalrm_exit, bg_man_sigalrm_register_func, bg_man_sigalrm_unregister_func, bg_man_sigalrm_enable_interrupts, bg_man_sigalrm_disable_interrupts, bg_man_sigalrm_interrupts_disabled }; #endif allegro-4.4.3.1/src/unix/umodules.c0000664000175000017500000001153013437077643016053 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Dynamically loaded modules. * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #ifdef ALLEGRO_WITH_MODULES #include #include #include #include typedef struct MODULE { void *handle; struct MODULE *next; } MODULE; /* list of loaded modules */ static MODULE *module_list = NULL; #define PREFIX_I "al-unix INFO: " /* where to look for modules.lst */ static char *module_path[] = { #ifdef ALLEGRO_MODULES_PATH ALLEGRO_MODULES_PATH, #else #error ALLEGRO_WITH_MODULES is defined, but not ALLEGRO_MODULES_PATH #endif NULL }; /* strip: * Strips leading and trailing whitespace from an ASCII string. */ static void strip(char *s) { char *x; if (!s[0]) return; for (x = s + strlen(s) - 1; isspace(*x); x--); x[1] = '\0'; for (x = s; isspace(*x); x++); memmove(s, x, strlen(x) + 1); } /* _unix_load_modules: * Find a modules.lst file and load the modules listed in it. */ void _unix_load_modules(int system_driver) { PACKFILE *f; char fullpath[1024]; char *fullpath_slash; char buf[1024]; char buf2[1024]; char **pathptr; char *filename; void *handle; void (*init)(int); MODULE *m; /* Read the ALLEGRO_MODULES environment variable. * But don't do it if we are root (for obvious reasons). */ if (geteuid() != 0) { char *env = getenv("ALLEGRO_MODULES"); if (env) { snprintf(fullpath, sizeof fullpath, "%s/%s", env, "modules.lst"); fullpath[(sizeof fullpath) - 1] = 0; f = pack_fopen(uconvert_ascii(fullpath, buf), F_READ); if (f) goto found; } } for (pathptr = module_path; *pathptr; pathptr++) { /* ALLEGRO_MODULES_PATH already includes the version, * as should ALLEGRO_MODULES. */ snprintf(fullpath, sizeof fullpath, "%s/modules.lst", *pathptr); fullpath[(sizeof fullpath) - 1] = 0; f = pack_fopen(uconvert_ascii(fullpath, buf), F_READ); if (f) goto found; } return; found: TRACE(PREFIX_I "Loading modules from \"%s\".\n", fullpath); fullpath_slash = strrchr(fullpath, '/'); while (TRUE) { if (!pack_fgets(buf, sizeof buf, f)) break; filename = uconvert_toascii(buf, buf2); strip(filename); if ((filename[0] == '#') || (strlen(filename) == 0)) continue; if (!fullpath_slash) { strncpy(fullpath, filename, sizeof fullpath); fullpath[(sizeof fullpath) - 1] = 0; } else { strncpy(fullpath_slash+1, filename, (sizeof fullpath) - (fullpath_slash - fullpath) - 1); fullpath[(sizeof fullpath) - 1] = 0; } if (!exists(uconvert_ascii(fullpath, buf))) continue; handle = dlopen(fullpath, RTLD_NOW); if (!handle) { /* useful during development */ /* printf("Error loading module: %s\n", dlerror()); */ continue; } init = dlsym(handle, "_module_init"); if (init) init(system_driver); m = _AL_MALLOC(sizeof(MODULE)); if (m) { m->handle = handle; m->next = module_list; module_list = m; } } pack_fclose(f); } /* _unix_unload_modules: * Unload loaded modules. */ void _unix_unload_modules(void) { MODULE *m, *next; void (*shutdown)(void); int *sym; int has_registered; for (m = module_list; m; m = next) { next = m->next; shutdown = dlsym(m->handle, "_module_shutdown"); if (shutdown) shutdown(); /* If a module has registered something via atexit, we can unload it * only if we are being called by the exit mechanism because, in this * case, we know that the registered routine has already been called; * otherwise the atexit machinery would end up referring to a function * that would not exist by the end of the program. */ sym = dlsym(m->handle, "_module_has_registered_via_atexit"); has_registered = (sym ? *sym : 0); if (!has_registered || _allegro_in_exit) dlclose(m->handle); _AL_FREE(m); } module_list = NULL; } #else /* ifdef ALLEGRO_WITH_MODULES */ void _unix_load_modules(int system_driver) { /* Fiddle dee dum, Fiddle dee dee, Eric, the half a bee */ } void _unix_unload_modules(void) { /* Ho ho ho, Tee hee hee, Eric, the half a bee */ } #endif allegro-4.4.3.1/src/unix/arts.c0000664000175000017500000001600513437077643015171 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * aRts sound driver (using artsc). * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #if (defined ALLEGRO_WITH_ARTSDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #ifdef ALLEGRO_MODULE int _module_has_registered_via_atexit = 0; #endif static int _al_arts_bits, _al_arts_rate, _al_arts_stereo; #define _al_arts_signed (TRUE) static arts_stream_t _al_arts_stream = NULL; static int _al_arts_bufsize; static int _al_arts_fragments; static unsigned char *_al_arts_bufdata = NULL; static int _al_arts_detect(int input); static int _al_arts_init(int input, int voices); static void _al_arts_exit(int input); static int _al_arts_buffer_size(void); static char _al_arts_desc[256] = EMPTY_STRING; DIGI_DRIVER digi_arts = { DIGI_ARTS, empty_string, empty_string, "aRts", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, _al_arts_detect, _al_arts_init, _al_arts_exit, NULL, NULL, NULL, NULL, _al_arts_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* _al_arts_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int _al_arts_buffer_size(void) { return _al_arts_bufsize / (_al_arts_bits / 8) / (_al_arts_stereo ? 2 : 1); } /* _al_arts_update: * Update data. */ static void _al_arts_update(int threaded) { int i; for (i = 0; i < _al_arts_fragments; i++) { if (arts_write(_al_arts_stream, _al_arts_bufdata, _al_arts_bufsize) < _al_arts_bufsize) break; _mix_some_samples((uintptr_t) _al_arts_bufdata, 0, _al_arts_signed); } } #define copy_error_text(code, tmp) \ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, \ uconvert_ascii(arts_error_text(code), (tmp))); /* _al_arts_detect: * Detect driver presence. */ static int _al_arts_detect(int input) { char tmp[ALLEGRO_ERROR_SIZE]; int code; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } code = arts_init(); if (code != 0) { copy_error_text(code, tmp); return FALSE; } arts_free(); return TRUE; } /* _al_arts_init: * Init routine. */ static int _al_arts_init(int input, int voices) { char tmp1[ALLEGRO_ERROR_SIZE]; char tmp2[128]; int code; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } /* Initialise artsc library. */ code = arts_init(); if (code != 0) { copy_error_text(code, tmp1); return -1; } #ifdef ALLEGRO_MODULE /* A side-effect of arts_init() is that it will register an * atexit handler. See umodules.c for this problem. * ??? this seems to be the case only for recent versions. */ _module_has_registered_via_atexit = 1; #endif /* Make a copy of the global sound settings. */ _al_arts_bits = (_sound_bits == 8) ? 8 : 16; _al_arts_stereo = (_sound_stereo) ? 1 : 0; _al_arts_rate = (_sound_freq > 0) ? _sound_freq : 44100; /* Open a stream for playback. */ _al_arts_stream = arts_play_stream(_al_arts_rate, _al_arts_bits, _al_arts_stereo ? 2 : 1, "allegro"); if (!_al_arts_stream) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open audio stream")); goto error; } /* Need non-blocking writes. */ code = arts_stream_set(_al_arts_stream, ARTS_P_BLOCKING, 0); if (code != 0) { copy_error_text(code, tmp1); goto error; } /* Try to reduce the latency of our stream. */ if (arts_stream_get(_al_arts_stream, ARTS_P_BUFFER_TIME) > 100) arts_stream_set(_al_arts_stream, ARTS_P_BUFFER_TIME, 100); /* Read buffer parameters and allocate buffer space. */ _al_arts_bufsize = arts_stream_get(_al_arts_stream, ARTS_P_PACKET_SIZE); _al_arts_fragments = arts_stream_get(_al_arts_stream, ARTS_P_PACKET_COUNT); _al_arts_bufdata = _AL_MALLOC_ATOMIC(_al_arts_bufsize); if (!_al_arts_bufdata) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); goto error; } /* Start up mixer. */ digi_arts.voices = voices; if (_mixer_init(_al_arts_bufsize / (_al_arts_bits / 8), _al_arts_rate, _al_arts_stereo, ((_al_arts_bits == 16) ? 1 : 0), &digi_arts.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); goto error; } _mix_some_samples((uintptr_t) _al_arts_bufdata, 0, _al_arts_signed); /* Add audio interrupt. */ _unix_bg_man->register_func(_al_arts_update); /* Decribe ourself. */ uszprintf(_al_arts_desc, sizeof(_al_arts_desc), get_config_text("%s: %d bits, %s, %d bps, %s"), "aRts", _al_arts_bits, uconvert_ascii("signed", tmp1), _al_arts_rate, uconvert_ascii((_al_arts_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = _al_arts_desc; return 0; error: if (_al_arts_bufdata) { _AL_FREE(_al_arts_bufdata); _al_arts_bufdata = NULL; } if (_al_arts_stream) { arts_close_stream(_al_arts_stream); _al_arts_stream = NULL; } arts_free(); return -1; } /* _al_arts_exit: * Shutdown routine. */ static void _al_arts_exit(int input) { if (input) return; _unix_bg_man->unregister_func(_al_arts_update); _mixer_exit(); _AL_FREE(_al_arts_bufdata); _al_arts_bufdata = NULL; /* Do not call the cleanup routines if we are being * called by the exit mechanism because they may have * already been called by it (see above). */ if (!_allegro_in_exit) { arts_close_stream(_al_arts_stream); _al_arts_stream = NULL; arts_free(); } } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_ARTS, &digi_arts, TRUE, TRUE); } #endif #endif allegro-4.4.3.1/src/unix/alsa5.c0000664000175000017500000002225313437077643015227 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * ALSA 0.5 sound driver. * * By Peter Wang (based heavily on uoss.c) * * See readme.txt for copyright information. */ #include "allegro.h" #if (ALLEGRO_ALSA_VERSION == 5) && (defined ALLEGRO_WITH_ALSADIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #ifdef ALLEGRO_QNX #include "allegro/platform/aintqnx.h" #else #include "allegro/platform/aintunix.h" #endif #ifndef SCAN_DEPEND #include #include #endif #ifndef SND_PCM_SFMT_S16_NE #ifdef ALLEGRO_BIG_ENDIAN #define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_BE #else #define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_LE #endif #endif #ifndef SND_PCM_SFMT_U16_NE #ifdef ALLEGRO_BIG_ENDIAN #define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_BE #else #define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_LE #endif #endif #define ALSA_DEFAULT_NUMFRAGS 16 static snd_pcm_t *pcm_handle; static int alsa_bufsize; static unsigned char *alsa_bufdata; static int alsa_bits, alsa_signed, alsa_rate, alsa_stereo; static int alsa_fragments; static char alsa_desc[256] = EMPTY_STRING; static int alsa_detect(int input); static int alsa_init(int input, int voices); static void alsa_exit(int input); static int alsa_set_mixer_volume(int volume); static int alsa_buffer_size(void); DIGI_DRIVER digi_alsa = { DIGI_ALSA, empty_string, empty_string, "ALSA", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, alsa_detect, alsa_init, alsa_exit, alsa_set_mixer_volume, NULL, NULL, NULL, alsa_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* alsa_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int alsa_buffer_size(void) { return alsa_bufsize * alsa_fragments / (alsa_bits / 8) / (alsa_stereo ? 2 : 1); } /* alsa_update: * Update data. */ static void alsa_update(int threaded) { int i; for (i = 0; i < alsa_fragments; i++) { if (snd_pcm_write(pcm_handle, alsa_bufdata, alsa_bufsize) != alsa_bufsize) break; _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed); } } /* alsa_detect: * Detect driver presence. */ static int alsa_detect(int input) { snd_pcm_t *handle; snd_pcm_info_t info; int card, device; char tmp1[128], tmp2[128]; int ret = FALSE; card = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_card", tmp2), snd_defaults_card()); device = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_pcmdevice", tmp2), snd_defaults_pcm_device()); if (snd_pcm_open(&handle, card, device, (SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK)) == 0) { if ((snd_pcm_info(handle, &info) == 0) && (info.flags & SND_PCM_INFO_PLAYBACK)) ret = TRUE; snd_pcm_close(handle); } return ret; } /* alsa_init: * ALSA init routine. */ static int alsa_init(int input, int voices) { int card, device; int format, bps, fragsize, numfrags; snd_pcm_channel_params_t params; snd_pcm_channel_setup_t setup; char tmp1[128], tmp2[128]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } /* Load config. */ card = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_card", tmp2), snd_defaults_card()); device = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_pcmdevice", tmp2), snd_defaults_pcm_device()); fragsize = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_fragsize", tmp2), -1); numfrags = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("alsa_numfrags", tmp2), ALSA_DEFAULT_NUMFRAGS); /* Open PCM device. */ if (snd_pcm_open(&pcm_handle, card, device, (SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK)) < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device")); goto error; } /* Set format variables. */ alsa_bits = (_sound_bits == 8) ? 8 : 16; alsa_stereo = (_sound_stereo) ? 1 : 0; alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100; format = ((alsa_bits == 16) ? SND_PCM_SFMT_S16_NE : SND_PCM_SFMT_U8); alsa_signed = 0; bps = alsa_rate * (alsa_stereo ? 2 : 1); switch (format) { case SND_PCM_SFMT_S8: alsa_signed = 1; case SND_PCM_SFMT_U8: alsa_bits = 8; break; case SND_PCM_SFMT_S16_NE: alsa_signed = 1; case SND_PCM_SFMT_U16_NE: alsa_bits = 16; bps <<= 1; if (sizeof(short) != 2) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); goto error; } break; default: ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); goto error; } if (fragsize < 0) { bps >>= 9; if (bps < 16) bps = 16; fragsize = 1; while ((fragsize << 1) < bps) fragsize <<= 1; } else { fragsize = fragsize * (alsa_bits / 8) * (alsa_stereo ? 2 : 1); } /* Set PCM channel format. */ memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.start_mode = SND_PCM_START_FULL; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.format.interleave = 1; params.format.format = format; params.format.rate = alsa_rate; params.format.voices = alsa_stereo + 1; params.buf.block.frag_size = fragsize; params.buf.block.frags_min = 1; params.buf.block.frags_max = numfrags; if (snd_pcm_channel_params(pcm_handle, ¶ms) < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not set channel parameters")); goto error; } snd_pcm_channel_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); /* Read back fragments information. */ memset(&setup, 0, sizeof(setup)); setup.mode = SND_PCM_MODE_BLOCK; setup.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_channel_setup(pcm_handle, &setup) < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not get channel setup")); goto error; } alsa_fragments = numfrags; alsa_bufsize = setup.buf.block.frag_size; /* Allocate mixing buffer. */ alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize); if (!alsa_bufdata) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); goto error; } /* Initialise mixer. */ digi_alsa.voices = voices; if (_mixer_init(alsa_bufsize / (alsa_bits / 8), alsa_rate, alsa_stereo, ((alsa_bits == 16) ? 1 : 0), &digi_alsa.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); goto error; } _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed); /* Add audio interrupt. */ _unix_bg_man->register_func(alsa_update); uszprintf(alsa_desc, sizeof(alsa_desc), get_config_text("Alsa 0.5, Card #%d, device #%d: %d bits, %s, %d bps, %s"), card, device, alsa_bits, uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1), alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = alsa_desc; return 0; error: if (pcm_handle) { snd_pcm_close(pcm_handle); pcm_handle = NULL; } return -1; } /* alsa_exit: * Shutdown ALSA driver. */ static void alsa_exit(int input) { if (input) { return; } _unix_bg_man->unregister_func(alsa_update); _AL_FREE(alsa_bufdata); alsa_bufdata = NULL; _mixer_exit(); snd_pcm_close(pcm_handle); } /* alsa_set_mixer_volume: * Set mixer volume (0-255) */ static int alsa_set_mixer_volume(int volume) { /* TODO */ #if 0 snd_mixer_t *handle; int card, device; if (snd_mixer_open(&handle, card, device) == 0) { /* do something special */ snd_mixer_close(handle); return 0; } return -1; #else return 0; #endif } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_ALSA, &digi_alsa, TRUE, TRUE); } #endif #endif allegro-4.4.3.1/src/unix/umouse.c0000664000175000017500000000132213437077643015531 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Unix mouse module. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" /* list the available drivers */ _DRIVER_INFO _mouse_driver_list[] = { { 0, NULL, 0 } }; allegro-4.4.3.1/src/unix/udjgpp.c0000664000175000017500000000144513437077643015513 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Some compatibility with DJGPP won't hurt. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro/internal/alconfig.h" static char *_allegro_program_arguments[] = { "./unknown", 0 }; int __crt0_argc = 1; char **__crt0_argv = _allegro_program_arguments; allegro-4.4.3.1/src/unix/uthreads.c0000664000175000017500000002014613437077643016040 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Asynchronous event processing with pthreads. * * By George Foot and Peter Wang. * * Synchronization functions added by Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/platform/aintunix.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_HAVE_LIBPTHREAD #include #include #include #include #ifndef ALLEGRO_MACOSX static void bg_man_pthreads_enable_interrupts(void); static void bg_man_pthreads_disable_interrupts(void); #define MAX_FUNCS 16 static bg_func funcs[MAX_FUNCS]; static int max_func; /* highest+1 used entry */ static pthread_t thread = 0; static int thread_alive = FALSE; static pthread_mutex_t cli_mutex; static pthread_cond_t cli_cond; static int cli_count; /* block_all_signals: * Blocks all signals for the calling thread. */ static void block_all_signals(void) { sigset_t mask; sigfillset(&mask); pthread_sigmask(SIG_BLOCK, &mask, NULL); } /* bg_man_pthreads_threadfunc: * Thread function for the background thread. */ static void *bg_man_pthreads_threadfunc(void *arg) { struct timeval old_time, new_time; struct timeval delay; unsigned long interval; int n; block_all_signals(); interval = 0; gettimeofday(&old_time, 0); while (thread_alive) { gettimeofday(&new_time, 0); /* add the new time difference to the remainder of the old difference */ interval += ((new_time.tv_sec - old_time.tv_sec) * 1000000L + (new_time.tv_usec - old_time.tv_usec)); old_time = new_time; /* run the callbacks for each 10ms elapsed, but limit to 18ms */ if (interval > 18000) interval = 18000; while (interval > 10000) { interval -= 10000; pthread_mutex_lock(&cli_mutex); /* wait until interrupts are enabled */ while (cli_count > 0) pthread_cond_wait(&cli_cond, &cli_mutex); /* call all the callbacks */ for (n = 0; n < max_func; n++) { if (funcs[n]) funcs[n](1); } pthread_mutex_unlock(&cli_mutex); } /* rest a little bit before checking again */ delay.tv_sec = 0; delay.tv_usec = 1000; select(0, NULL, NULL, NULL, &delay); } return NULL; } /* bg_man_pthreads_init: * Spawns the background thread. */ static int bg_man_pthreads_init(void) { int i; ASSERT(thread == 0); ASSERT(!thread_alive); for (i = 0; i < MAX_FUNCS; i++) funcs[i] = NULL; max_func = 0; cli_count = 0; pthread_mutex_init(&cli_mutex, NULL); pthread_cond_init(&cli_cond, NULL); thread_alive = TRUE; if (pthread_create(&thread, NULL, bg_man_pthreads_threadfunc, NULL)) { thread_alive = FALSE; pthread_mutex_destroy(&cli_mutex); pthread_cond_destroy(&cli_cond); thread = 0; return -1; } return 0; } /* bg_man_pthreads_exit: * Kills the background thread. */ static void bg_man_pthreads_exit(void) { ASSERT(!!thread == !!thread_alive); if (thread) { thread_alive = FALSE; pthread_join(thread, NULL); pthread_mutex_destroy(&cli_mutex); pthread_cond_destroy(&cli_cond); thread = 0; } } /* bg_man_pthreads_register_func: * Registers a function to be called by the background thread. */ static int bg_man_pthreads_register_func(bg_func f) { int i, ret = 0; bg_man_pthreads_disable_interrupts(); for (i = 0; i < MAX_FUNCS && funcs[i]; i++) ; if (i == MAX_FUNCS) ret = -1; else { funcs[i] = f; if (i == max_func) max_func++; } bg_man_pthreads_enable_interrupts(); return ret; } /* really_unregister_func: * Unregisters a function registered with bg_man_pthreads_register_func. */ static int really_unregister_func(bg_func f) { int i; for (i = 0; i < max_func && funcs[i] != f; i++) ; if (i == max_func) return -1; else { funcs[i] = NULL; if (i+1 == max_func) do { max_func--; } while ((max_func > 0) && !funcs[max_func-1]); return 0; } } /* bg_man_pthreads_unregister_func: * Wrapper for really_unregister_func to avoid locking problems. */ static int bg_man_pthreads_unregister_func(bg_func f) { /* Normally we just bg_man_pthread_disable_interrupts(), remove `f', * then bg_man_pthread_enable_interrupts(). * * However, the X system driver's input handler is a bg_man callback. * When it receives a close event, it calls exit(), which calls * allegro_exit(). Eventually various subsystems will try to * unregister their callbacks, i.e. call this function. But we're in * the middle of input handler call, and `cli_mutex' is still locked. * * So we... special case! If the calling thread is the bg_man thread * we simply bypass the locking, as there's no synchronisation * problem to avoid anyway. */ int ret; if (pthread_equal(pthread_self(), thread)) /* Being called from a bg_man registered callback. */ ret = really_unregister_func(f); else { /* Normal case. */ bg_man_pthreads_disable_interrupts(); ret = really_unregister_func(f); bg_man_pthreads_enable_interrupts(); } return ret; } /* bg_man_pthreads_enable_interrupts: * Enables interrupts for the background thread. */ static void bg_man_pthreads_enable_interrupts(void) { pthread_mutex_lock(&cli_mutex); if (--cli_count == 0) pthread_cond_signal(&cli_cond); pthread_mutex_unlock(&cli_mutex); } /* bg_man_pthreads_disable_interrupts: * Disables interrupts for the background thread. */ static void bg_man_pthreads_disable_interrupts(void) { pthread_mutex_lock(&cli_mutex); cli_count++; pthread_mutex_unlock(&cli_mutex); } /* bg_man_pthreads_interrupts_disabled: * Returns whether interrupts are disabled for the background thread. */ static int bg_man_pthreads_interrupts_disabled(void) { return cli_count; } /* the background manager object */ struct bg_manager _bg_man_pthreads = { 1, bg_man_pthreads_init, bg_man_pthreads_exit, bg_man_pthreads_register_func, bg_man_pthreads_unregister_func, bg_man_pthreads_enable_interrupts, bg_man_pthreads_disable_interrupts, bg_man_pthreads_interrupts_disabled }; #endif /* !ALLEGRO_MACOSX */ /* custom mutex that supports nested locking */ struct my_mutex { int lock_count; /* level of nested locking */ pthread_t owner; /* thread which owns the mutex */ pthread_mutex_t actual_mutex; /* underlying mutex object */ }; /* _unix_create_mutex: * Creates a mutex and returns a pointer to it. */ void *_unix_create_mutex(void) { struct my_mutex *mx; mx = _AL_MALLOC(sizeof(struct my_mutex)); if (!mx) { *allegro_errno = ENOMEM; return NULL; } mx->lock_count = 0; mx->owner = (pthread_t) 0; pthread_mutex_init(&mx->actual_mutex, NULL); return (void *)mx; } /* _unix_destroy_mutex: * Destroys a mutex. */ void _unix_destroy_mutex(void *handle) { struct my_mutex *mx = (struct my_mutex *)handle; pthread_mutex_destroy(&mx->actual_mutex); _AL_FREE(mx); } /* _unix_lock_mutex: * Locks a mutex. */ void _unix_lock_mutex(void *handle) { struct my_mutex *mx = (struct my_mutex *)handle; if (mx->owner != pthread_self()) { pthread_mutex_lock(&mx->actual_mutex); mx->owner = pthread_self(); } mx->lock_count++; } /* _unix_unlock_mutex: * Unlocks a mutex. */ void _unix_unlock_mutex(void *handle) { struct my_mutex *mx = (struct my_mutex *)handle; mx->lock_count--; if (mx->lock_count == 0) { mx->owner = (pthread_t) 0; pthread_mutex_unlock(&mx->actual_mutex); } } #endif /* ALLEGRO_HAVE_LIBPTHREAD */ allegro-4.4.3.1/src/unix/ufile.c0000664000175000017500000002763513437077643015337 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper routines to make file.c work on Unix (POSIX) platforms. * * By Michael Bukin. * * See readme.txt for copyright information. */ /* libc should use 64-bit for file sizes when possible */ #define _FILE_OFFSET_BITS 64 #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_HAVE_SYS_STAT_H #include #endif #ifdef ALLEGRO_HAVE_DIRENT_H #include #include #define NAMLEN(dirent) (strlen((dirent)->d_name)) #else /* Apparently all new systems have `dirent.h'. */ #error ALLEGRO_HAVE_DIRENT_H not defined #endif #ifdef ALLEGRO_HAVE_SYS_TIME_H #include #endif #ifdef ALLEGRO_HAVE_TIME_H #include #endif #define PREFIX_I "al-unix INFO: " #define PREFIX_I "al-unix INFO: " /* _al_file_isok: * Helper function to check if it is safe to access a file on a floppy * drive. */ int _al_file_isok(AL_CONST char *filename) { return TRUE; } /* _al_file_size_ex: * Measures the size of the specified file. */ uint64_t _al_file_size_ex(AL_CONST char *filename) { struct stat s; char tmp[1024]; if (stat(uconvert(filename, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } return s.st_size; } /* _al_file_time: * Returns the timestamp of the specified file. */ time_t _al_file_time(AL_CONST char *filename) { struct stat s; char tmp[1024]; if (stat(uconvert(filename, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } return s.st_mtime; } /* ff_get_filename: * When passed a completely specified file path, this returns a pointer * to the filename portion. */ static char *ff_get_filename(AL_CONST char *path) { char *p = (char*)path + strlen(path); while ((p > path) && (*(p - 1) != '/')) p--; return p; } /* ff_put_backslash: * If the last character of the filename is not a /, this routine will * concatenate a / on to it. */ static void ff_put_backslash(char *filename, int size) { int len = strlen(filename); if ((len > 0) && (len < (size - 1)) && (filename[len - 1] != '/')) { filename[len] = '/'; filename[len + 1] = 0; } } #define FF_MATCH_TRY 0 #define FF_MATCH_ONE 1 #define FF_MATCH_ANY 2 struct FF_MATCH_DATA { int type; AL_CONST char *s1; AL_CONST char *s2; }; /* ff_match: * Matches two strings ('*' matches any number of characters, * '?' matches any character). */ static int ff_match(AL_CONST char *s1, AL_CONST char *s2) { static unsigned int size = 0; static struct FF_MATCH_DATA *data = NULL; AL_CONST char *s1end; int index, c1, c2; /* handle NULL arguments */ if ((!s1) && (!s2)) { if (data) { _AL_FREE(data); data = NULL; } return 0; } s1end = s1 + strlen(s1); /* allocate larger working area if necessary */ if (data && (size < strlen(s2))) { _AL_FREE(data); data = NULL; } if (!data) { size = strlen(s2); data = _AL_MALLOC(sizeof(struct FF_MATCH_DATA) * size * 2 + 1); if (!data) return 0; } index = 0; data[0].s1 = s1; data[0].s2 = s2; data[0].type = FF_MATCH_TRY; while (index >= 0) { s1 = data[index].s1; s2 = data[index].s2; c1 = *s1; c2 = *s2; switch (data[index].type) { case FF_MATCH_TRY: if (c2 == 0) { /* pattern exhausted */ if (c1 == 0) return 1; else index--; } else if (c1 == 0) { /* string exhausted */ while (*s2 == '*') s2++; if (*s2 == 0) return 1; else index--; } else if (c2 == '*') { /* try to match the rest of pattern with empty string */ data[index++].type = FF_MATCH_ANY; data[index].s1 = s1end; data[index].s2 = s2 + 1; data[index].type = FF_MATCH_TRY; } else if ((c2 == '?') || (c1 == c2)) { /* try to match the rest */ data[index++].type = FF_MATCH_ONE; data[index].s1 = s1 + 1; data[index].s2 = s2 + 1; data[index].type = FF_MATCH_TRY; } else index--; break; case FF_MATCH_ONE: /* the rest of string did not match, try earlier */ index--; break; case FF_MATCH_ANY: /* rest of string did not match, try add more chars to string tail */ if (--data[index + 1].s1 >= s1) { data[index + 1].type = FF_MATCH_TRY; index++; } else index--; break; default: /* this is a bird? This is a plane? No it's a bug!!! */ return 0; } } return 0; } /* ff_get_attrib: * Builds up the attribute list of the file pointed to by name and s. */ static int ff_get_attrib(AL_CONST char *name, struct stat *s) { int attrib = 0; uid_t euid = geteuid(); if (euid != 0) { if (s->st_uid == euid) { if ((s->st_mode & S_IWUSR) == 0) attrib |= FA_RDONLY; } else if (s->st_gid == getegid()) { if ((s->st_mode & S_IWGRP) == 0) attrib |= FA_RDONLY; } else if ((s->st_mode & S_IWOTH) == 0) { attrib |= FA_RDONLY; } } if (S_ISDIR(s->st_mode)) attrib |= FA_DIREC; if ((name[0] == '.') && ((name[1] != '.') || (name[2] != '\0'))) attrib |= FA_HIDDEN; return attrib; } /* structure for use by the directory scanning routines */ #define FF_MAXPATHLEN 1024 struct FF_DATA { DIR *dir; char dirname[FF_MAXPATHLEN]; char pattern[FF_MAXPATHLEN]; int attrib; uint64_t size; }; /* al_findfirst: * Initiates a directory search. */ int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) { struct FF_DATA *ff_data; struct stat s; int actual_attrib; char tmp[1024]; char *p; /* allocate ff_data structure */ ff_data = _AL_MALLOC(sizeof(struct FF_DATA)); if (!ff_data) { *allegro_errno = ENOMEM; return -1; } memset(ff_data, 0, sizeof *ff_data); info->ff_data = (void *) ff_data; /* if the pattern contains no wildcard, we use stat() */ if (!ustrpbrk(pattern, uconvert("?*", U_ASCII, tmp, U_CURRENT, sizeof(tmp)))) { /* start the search */ errno = *allegro_errno = 0; if (stat(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) == 0) { /* get file attributes */ actual_attrib = ff_get_attrib(ff_get_filename(uconvert(pattern, U_CURRENT, tmp, U_UTF8, sizeof(tmp))), &s); /* does it match ? */ if ((actual_attrib & ~attrib) == 0) { info->attrib = actual_attrib; info->time = s.st_mtime; info->size = s.st_size; /* overflows at 2GB */ ff_data->size = s.st_size; ustrzcpy(info->name, sizeof(info->name), get_filename(pattern)); return 0; } } _AL_FREE(ff_data); info->ff_data = NULL; *allegro_errno = (errno ? errno : ENOENT); return -1; } ff_data->attrib = attrib; do_uconvert(pattern, U_CURRENT, ff_data->dirname, U_UTF8, sizeof(ff_data->dirname)); p = ff_get_filename(ff_data->dirname); _al_sane_strncpy(ff_data->pattern, p, sizeof(ff_data->pattern)); if (p == ff_data->dirname) _al_sane_strncpy(ff_data->dirname, "./", FF_MAXPATHLEN); else *p = 0; /* nasty bodge, but gives better compatibility with DOS programs */ if (strcmp(ff_data->pattern, "*.*") == 0) _al_sane_strncpy(ff_data->pattern, "*", FF_MAXPATHLEN); /* start the search */ errno = *allegro_errno = 0; ff_data->dir = opendir(ff_data->dirname); if (!ff_data->dir) { *allegro_errno = (errno ? errno : ENOENT); _AL_FREE(ff_data); info->ff_data = NULL; return -1; } if (al_findnext(info) != 0) { al_findclose(info); return -1; } return 0; } /* al_findnext: * Retrieves the next file from a directory search. */ int al_findnext(struct al_ffblk *info) { char tempname[FF_MAXPATHLEN]; char filename[FF_MAXPATHLEN]; int attrib; struct dirent *entry; struct stat s; struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; ASSERT(ff_data); /* if the pattern contained no wildcard */ if (!ff_data->dir) return -1; while (TRUE) { /* read directory entry */ entry = readdir(ff_data->dir); if (!entry) { *allegro_errno = (errno ? errno : ENOENT); return -1; } /* try to match file name with pattern */ tempname[0] = 0; if (NAMLEN(entry) >= sizeof(tempname)) strncat(tempname, entry->d_name, sizeof(tempname) - 1); else strncat(tempname, entry->d_name, NAMLEN(entry)); if (ff_match(tempname, ff_data->pattern)) { _al_sane_strncpy(filename, ff_data->dirname, FF_MAXPATHLEN); ff_put_backslash(filename, sizeof(filename)); strncat(filename, tempname, sizeof(filename) - strlen(filename) - 1); /* get file attributes */ if (stat(filename, &s) == 0) { attrib = ff_get_attrib(tempname, &s); /* does it match ? */ if ((attrib & ~ff_data->attrib) == 0) break; } else { /* evil! but no other way to avoid exiting for_each_file() */ *allegro_errno = 0; } } } info->attrib = attrib; info->time = s.st_mtime; info->size = s.st_size; /* overflows at 2GB */ ff_data->size = s.st_size; do_uconvert(tempname, U_UTF8, info->name, U_CURRENT, sizeof(info->name)); return 0; } /* al_findclose: * Cleans up after a directory search. */ void al_findclose(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; if (ff_data) { if (ff_data->dir) { closedir(ff_data->dir); } _AL_FREE(ff_data); info->ff_data = NULL; /* to avoid leaking memory */ ff_match(NULL, NULL); } } /* _al_getdcwd: * Returns the current directory on the specified drive. */ void _al_getdcwd(int drive, char *buf, int size) { char tmp[1024]; if (getcwd(tmp, sizeof(tmp))) do_uconvert(tmp, U_UTF8, buf, U_CURRENT, size); else usetc(buf, 0); } /* _al_ffblk_get_size: * Returns the size out of an _al_ffblk structure. */ uint64_t al_ffblk_get_size(struct al_ffblk *info) { struct FF_DATA *ff_data; ASSERT(info); ff_data = (struct FF_DATA *) info->ff_data; ASSERT(ff_data); return ff_data->size; } /* _al_detect_filename_encoding: * Platform specific function to detect the filename encoding. This is called * after setting a system driver, and even if this driver is SYSTEM_NONE. */ void _al_detect_filename_encoding(void) { char const *encoding = "unknown"; char *locale = getenv("LC_ALL"); if (!locale || !locale[0]) { locale = getenv("LC_CTYPE"); if (!locale || !locale[0]) locale = getenv("LANG"); } if (locale) { if (strstr(locale, "utf8") || strstr(locale, "UTF-8") || strstr(locale, "utf-8") || strstr(locale, "UTF8")) { /* Note: UTF8 is default anyway. */ set_filename_encoding(U_UTF8); encoding = "UTF8"; } /* TODO: detect other encodings, and support them in Allegro */ } TRACE(PREFIX_I "Assumed libc encoding is %s.\n", encoding); } allegro-4.4.3.1/src/unix/uoss.c0000664000175000017500000003346013437077643015215 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Open Sound System driver. Supports for /dev/dsp and /dev/audio. * * By Joshua Heyer. * * Modified by Michael Bukin. * * Input code by Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_WITH_OSSDIGI #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #include #include #include #include #include #include #include #if defined(ALLEGRO_HAVE_SOUNDCARD_H) #include #elif defined(ALLEGRO_HAVE_SYS_SOUNDCARD_H) #include #elif defined(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) #include #elif defined(ALLEGRO_HAVE_LINUX_SOUNDCARD_H) #include #endif #include #ifndef AFMT_S16_NE #ifdef ALLEGRO_BIG_ENDIAN #define AFMT_S16_NE AFMT_S16_BE #else #define AFMT_S16_NE AFMT_S16_LE #endif #endif #ifndef AFMT_U16_NE #ifdef ALLEGRO_BIG_ENDIAN #define AFMT_U16_NE AFMT_U16_BE #else #define AFMT_U16_NE AFMT_U16_LE #endif #endif #define OSS_DEFAULT_FRAGBITS 9 #define OSS_DEFAULT_NUMFRAGS 8 int _oss_fragsize; int _oss_numfrags; char _oss_driver[256] = EMPTY_STRING; static char _oss_mixer_driver[256] = EMPTY_STRING; static int oss_fd; static int oss_bufsize; static unsigned char *oss_bufdata; static int oss_signed, oss_format; static int oss_save_bits, oss_save_stereo, oss_save_freq; static int oss_rec_bufsize; static int oss_detect(int input); static int oss_init(int input, int voices); static void oss_exit(int input); static int oss_set_mixer_volume(int volume); static int oss_get_mixer_volume(void); static int oss_buffer_size(void); static int oss_rec_cap_rate(int bits, int stereo); static int oss_rec_cap_parm(int rate, int bits, int stereo); static int oss_rec_source(int source); static int oss_rec_start(int rate, int bits, int stereo); static void oss_rec_stop(void); static int oss_rec_read(void *buf); static char oss_desc[256] = EMPTY_STRING; DIGI_DRIVER digi_oss = { DIGI_OSS, empty_string, empty_string, "Open Sound System", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, oss_detect, oss_init, oss_exit, oss_set_mixer_volume, oss_get_mixer_volume, NULL, NULL, oss_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, oss_rec_cap_rate, oss_rec_cap_parm, oss_rec_source, oss_rec_start, oss_rec_stop, oss_rec_read }; /* oss_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int oss_buffer_size(void) { return oss_bufsize / (_sound_bits / 8) / (_sound_stereo ? 2 : 1); } /* oss_update: * Update data. */ static void oss_update(int threaded) { int i; audio_buf_info bufinfo; if (ioctl(oss_fd, SNDCTL_DSP_GETOSPACE, &bufinfo) != -1) { /* Write fragments. */ for (i = 0; i < bufinfo.fragments; i++) { write(oss_fd, oss_bufdata, oss_bufsize); _mix_some_samples((uintptr_t) oss_bufdata, 0, oss_signed); } } } /* open_oss_device: * Shared helper for the detect and init functions, which opens the * audio device and sets the sample mode parameters. */ static int open_oss_device(int input) { char tmp1[128], tmp2[128], tmp3[128]; int fragsize, fragbits, bits, stereo, freq; ustrzcpy(_oss_driver, sizeof(_oss_driver), get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("oss_driver", tmp2), uconvert_ascii("/dev/dsp", tmp3))); ustrzcpy(_oss_mixer_driver, sizeof(_oss_mixer_driver), get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("oss_mixer_driver", tmp2), uconvert_ascii("/dev/mixer", tmp3))); oss_fd = open(uconvert_toascii(_oss_driver, tmp1), (input ? O_RDONLY : O_WRONLY) | O_NONBLOCK); if (oss_fd < 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: %s"), _oss_driver, ustrerror(errno)); return -1; } _oss_fragsize = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("oss_fragsize", tmp2), -1); _oss_numfrags = get_config_int(uconvert_ascii("sound", tmp1), uconvert_ascii("oss_numfrags", tmp2), -1); if (_oss_fragsize < 0) _oss_fragsize = 1 << OSS_DEFAULT_FRAGBITS; if (_oss_numfrags < 0) _oss_numfrags = OSS_DEFAULT_NUMFRAGS; /* try to detect whether the DSP can do 16 bit sound or not */ if (_sound_bits == -1) { /* ask supported formats */ if (ioctl(oss_fd, SNDCTL_DSP_GETFMTS, &oss_format) != -1) { if (oss_format & AFMT_S16_NE) _sound_bits = 16; else if (oss_format & AFMT_U16_NE) _sound_bits = 16; else if (oss_format & AFMT_S8) _sound_bits = 8; else if (oss_format & AFMT_U8) _sound_bits = 8; else { /* ask current format */ oss_format = 0; if (ioctl(oss_fd, SNDCTL_DSP_SETFMT, &oss_format) != -1) { switch (oss_format) { case AFMT_S16_NE: case AFMT_U16_NE: _sound_bits = 16; break; case AFMT_S8: case AFMT_U8: _sound_bits = 8; break; } } } } } bits = (_sound_bits == 8) ? 8 : 16; stereo = (_sound_stereo) ? 1 : 0; freq = (_sound_freq > 0) ? _sound_freq : 45454; /* fragment size is specified in samples, not in bytes */ fragsize = _oss_fragsize * (bits / 8) * (stereo ? 2 : 1); fragsize += fragsize - 1; for (fragbits = 0; (fragbits < 16) && (fragsize > 1); fragbits++) fragsize /= 2; fragbits = CLAMP(4, fragbits, 16); _oss_numfrags = CLAMP(2, _oss_numfrags, 0x7FFF); fragsize = (_oss_numfrags << 16) | fragbits; if (ioctl(oss_fd, SNDCTL_DSP_SETFRAGMENT, &fragsize) == -1) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Setting fragment size: %s"), ustrerror(errno)); close(oss_fd); return -1; } _oss_fragsize = (1 << (fragsize & 0xFFFF)) / (bits / 8) / (stereo ? 2 : 1); _oss_numfrags = fragsize >> 16; oss_format = ((bits == 16) ? AFMT_S16_NE : AFMT_U8); if ((ioctl(oss_fd, SNDCTL_DSP_SETFMT, &oss_format) == -1) || (ioctl(oss_fd, SNDCTL_DSP_STEREO, &stereo) == -1) || (ioctl(oss_fd, SNDCTL_DSP_SPEED, &freq) == -1)) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Setting DSP parameters: %s"), ustrerror(errno)); close(oss_fd); return -1; } oss_signed = 0; switch (oss_format) { case AFMT_S8: oss_signed = 1; /* fallthrough */ case AFMT_U8: bits = 8; break; case AFMT_S16_NE: oss_signed = 1; /* fallthrough */ case AFMT_U16_NE: bits = 16; if (sizeof(short) != 2) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); close(oss_fd); return -1; } break; default: ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); close(oss_fd); return -1; } if ((stereo != 0) && (stereo != 1)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not in stereo or mono mode")); close(oss_fd); return -1; } _sound_bits = bits; _sound_stereo = stereo; _sound_freq = freq; return 0; } /* oss_detect: * Detect driver presence. */ static int oss_detect(int input) { if (input) { if (digi_driver != digi_input_driver) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("OSS output driver must be installed before input can be read")); return FALSE; } return TRUE; } if (open_oss_device(0) != 0) return FALSE; close(oss_fd); return TRUE; } /* oss_init: * OSS init routine. */ static int oss_init(int input, int voices) { char tmp1[128], tmp2[128]; audio_buf_info bufinfo; if (input) { digi_driver->rec_cap_bits = 16; digi_driver->rec_cap_stereo = TRUE; return 0; } if (open_oss_device(0) != 0) return -1; if (ioctl(oss_fd, SNDCTL_DSP_GETOSPACE, &bufinfo) == -1) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Getting buffer size: %s"), ustrerror(errno)); close(oss_fd); return -1; } oss_bufsize = bufinfo.fragsize; oss_bufdata = _AL_MALLOC_ATOMIC(oss_bufsize); if (oss_bufdata == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); close(oss_fd); return -1; } digi_oss.voices = voices; if (_mixer_init(oss_bufsize / (_sound_bits / 8), _sound_freq, _sound_stereo, ((_sound_bits == 16) ? 1 : 0), &digi_oss.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); close(oss_fd); return -1; } _mix_some_samples((uintptr_t) oss_bufdata, 0, oss_signed); /* Add audio interrupt. */ _unix_bg_man->register_func(oss_update); uszprintf(oss_desc, sizeof(oss_desc), get_config_text("%s: %d bits, %s, %d bps, %s"), _oss_driver, _sound_bits, uconvert_ascii((oss_signed ? "signed" : "unsigned"), tmp1), _sound_freq, uconvert_ascii((_sound_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = oss_desc; return 0; } /* oss_exit: * Shutdown OSS driver. */ static void oss_exit(int input) { if (input) { return; } _unix_bg_man->unregister_func(oss_update); _AL_FREE(oss_bufdata); oss_bufdata = 0; _mixer_exit(); close(oss_fd); } /* oss_set_mixer_volume: * Set mixer volume. */ static int oss_set_mixer_volume(int volume) { int fd, vol, ret; char tmp[128]; fd = open(uconvert_toascii(_oss_mixer_driver, tmp), O_WRONLY); if (fd < 0) return -1; vol = (volume * 100) / 255; vol = (vol << 8) | (vol); ret = ioctl(fd, MIXER_WRITE(SOUND_MIXER_PCM), &vol); close(fd); return ret; } /* oss_get_mixer_volume: * Return mixer volume. */ static int oss_get_mixer_volume(void) { int fd, vol; char tmp[128]; fd = open(uconvert_toascii(_oss_mixer_driver, tmp), O_RDONLY); if (fd < 0) return -1; if (ioctl(fd, MIXER_READ(SOUND_MIXER_PCM), &vol) != 0) return -1; close(fd); vol = ((vol & 0xff) + (vol >> 8)) / 2; vol = vol * 255 / 100; return vol; } /* oss_rec_cap_rate: * Returns maximum input sampling rate. */ static int oss_rec_cap_rate(int bits, int stereo) { return 44100; } /* oss_rec_cap_parm: * Returns whether the specified parameters can be set. */ static int oss_rec_cap_parm(int rate, int bits, int stereo) { return 1; } /* oss_rec_source: * Sets the sampling source for audio recording. */ static int oss_rec_source(int source) { int fd, src, ret; char tmp[128]; fd = open(uconvert_toascii(_oss_mixer_driver, tmp), O_WRONLY); if (fd < 0) return -1; switch (source) { case SOUND_INPUT_MIC: src = SOUND_MASK_MIC; break; case SOUND_INPUT_LINE: src = SOUND_MASK_LINE; break; case SOUND_INPUT_CD: src = SOUND_MASK_CD; break; default: return -1; } ret = ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &src); close(fd); return ret; } /* oss_rec_start: * Re-opens device with read-mode and starts recording (half-duplex). * Returns the DMA buffer size if successful. */ static int oss_rec_start(int rate, int bits, int stereo) { audio_buf_info bufinfo; /* Save current settings, and close playback device. */ oss_save_bits = _sound_bits; oss_save_stereo = _sound_stereo; oss_save_freq = _sound_freq; _unix_bg_man->unregister_func(oss_update); close(oss_fd); /* Reopen device for recording. */ _sound_bits = bits; _sound_stereo = stereo; _sound_freq = rate; if (open_oss_device(1) != 0) return 0; if (ioctl(oss_fd, SNDCTL_DSP_GETISPACE, &bufinfo) == -1) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Getting buffer size: %s"), ustrerror(errno)); close(oss_fd); return 0; } oss_rec_bufsize = bufinfo.fragsize; return oss_rec_bufsize; } /* oss_rec_stop: * Stops recording and switches the device back to the original mode. */ static void oss_rec_stop(void) { close(oss_fd); /* Reopen for playback with saved settings. */ _sound_bits = oss_save_bits; _sound_stereo = oss_save_stereo; _sound_freq = oss_save_freq; open_oss_device(0); _unix_bg_man->register_func(oss_update); } /* oss_rec_read: * Retrieves the just recorded buffer, if there is one. */ static int oss_rec_read(void *buf) { char *p; int i; if (read(oss_fd, buf, oss_rec_bufsize) != oss_rec_bufsize) return 0; /* Convert signedness. */ if ((_sound_bits == 16) && (oss_signed)) { p = buf; for (i = 0; i < oss_rec_bufsize; i++) p[i] ^= 0x80; } return 1; } #endif allegro-4.4.3.1/src/unix/udummy.c0000664000175000017500000000051413437077643015536 0ustar siegesiege/* This file contains a dummy symbol that gets unconditionally included * in liballeg_unsharable.a through a tweak in misc/deplib.sh, in order * to make sure that the static library contains at least one symbol. * This is needed for Solaris because the linker chokes when a library * contains no symbol. */ int _dummy_symbol; allegro-4.4.3.1/src/unix/ujoydrv.c0000664000175000017500000000130513437077643015717 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of Unix joystick drivers. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" BEGIN_JOYSTICK_DRIVER_LIST /* todo */ END_JOYSTICK_DRIVER_LIST allegro-4.4.3.1/src/unix/uesd.c0000664000175000017500000001505013437077643015157 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * ESD sound driver. * * By Michael Bukin. * * Bug fixes by Peter Wang and Eduard Bloch. * * See readme.txt for copyright information. */ #include "allegro.h" #if (defined ALLEGRO_WITH_ESDDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #include #include #include #include static int _al_esd_fd; static int _al_esd_bufsize; static unsigned char *_al_esd_bufdata; static int _al_esd_bits, _al_esd_signed, _al_esd_rate, _al_esd_stereo; static esd_format_t _al_esd_format; static int _al_esd_detect(int input); static int _al_esd_init(int input, int voices); static void _al_esd_exit(int input); static int _al_esd_set_mixer_volume(int volume); static int _al_esd_buffer_size(void); static char _al_esd_desc[256] = EMPTY_STRING; DIGI_DRIVER digi_esd = { DIGI_ESD, empty_string, empty_string, "Enlightened Sound Daemon", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, _al_esd_detect, _al_esd_init, _al_esd_exit, _al_esd_set_mixer_volume, NULL, NULL, NULL, _al_esd_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* _al_esd_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int _al_esd_buffer_size(void) { return _al_esd_bufsize / (_al_esd_bits / 8) / (_al_esd_stereo ? 2 : 1); } /* _al_esd_update: * Update data. */ static void _al_esd_update(int threaded) { fd_set wfds; struct timeval timeout; FD_ZERO(&wfds); FD_SET(_al_esd_fd, &wfds); timeout.tv_sec = 0; timeout.tv_usec = 0; if (select(_al_esd_fd+1, NULL, &wfds, NULL, &timeout) > 0) { write(_al_esd_fd, _al_esd_bufdata, _al_esd_bufsize); _mix_some_samples((uintptr_t) _al_esd_bufdata, 0, _al_esd_signed); } } /* _al_esd_detect: * Detect driver presence. */ static int _al_esd_detect(int input) { int fd; AL_CONST char *server; char tmp1[128], tmp2[128], tmp3[16]; char s[256]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } /* We don't want esdlib to spawn ESD while we are detecting it. */ putenv("ESD_NO_SPAWN=1"); /* Get ESD server name. */ server = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("esd_server", tmp2), uconvert_ascii("", tmp3)); /* Try to open ESD server. */ fd = esd_open_sound(uconvert_toascii(server, s)); if (fd < 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: can not open"), (ugetc(server) ? server : get_config_text("No server"))); return FALSE; } esd_close(fd); return TRUE; } /* _al_esd_init: * ESD init routine. */ static int _al_esd_init(int input, int voices) { AL_CONST char *server; char tmp1[128], tmp2[128], tmp3[16]; char s[256]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } server = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("esd_server", tmp2), uconvert_ascii("", tmp3)); _al_esd_bits = (_sound_bits == 8) ? 8 : 16; _al_esd_stereo = (_sound_stereo) ? 1 : 0; _al_esd_rate = (_sound_freq > 0) ? _sound_freq : ESD_DEFAULT_RATE; _al_esd_signed = 1; _al_esd_format = (((_al_esd_bits == 16) ? ESD_BITS16 : ESD_BITS8) | (_al_esd_stereo ? ESD_STEREO : ESD_MONO) | ESD_STREAM | ESD_PLAY); _al_esd_fd = esd_play_stream_fallback(_al_esd_format, _al_esd_rate, uconvert_toascii(server, s), NULL); if (_al_esd_fd < 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: can not open"), (ugetc(server) ? server : get_config_text("No server"))); return -1; } _al_esd_bufsize = ESD_BUF_SIZE; _al_esd_bufdata = _AL_MALLOC_ATOMIC(_al_esd_bufsize); if (_al_esd_bufdata == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); close(_al_esd_fd); return -1; } digi_esd.voices = voices; if (_mixer_init(_al_esd_bufsize / (_al_esd_bits / 8), _al_esd_rate, _al_esd_stereo, ((_al_esd_bits == 16) ? 1 : 0), &digi_esd.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); _AL_FREE(_al_esd_bufdata); _al_esd_bufdata = 0; close(_al_esd_fd); return -1; } _mix_some_samples((uintptr_t) _al_esd_bufdata, 0, _al_esd_signed); /* Add audio interrupt. */ _unix_bg_man->register_func(_al_esd_update); uszprintf(_al_esd_desc, sizeof(_al_esd_desc), get_config_text("%s: %d bits, %s, %d bps, %s"), server, _al_esd_bits, uconvert_ascii((_al_esd_signed ? "signed" : "unsigned"), tmp1), _al_esd_rate, uconvert_ascii((_al_esd_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = _al_esd_desc; return 0; } /* _al_esd_exit: * Shutdown ESD driver. */ static void _al_esd_exit(int input) { if (input) { return; } _unix_bg_man->unregister_func(_al_esd_update); _AL_FREE(_al_esd_bufdata); _al_esd_bufdata = 0; _mixer_exit(); close(_al_esd_fd); } /* _al_esd_set_mixer_volume: * Set mixer volume. */ static int _al_esd_set_mixer_volume(int volume) { return 0; } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_ESD, &digi_esd, TRUE, TRUE); } #endif #endif allegro-4.4.3.1/src/unix/ustimer.c0000664000175000017500000000337513437077643015716 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Timer module for Unix, using SIGALRM. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #ifndef ALLEGRO_HAVE_LIBPTHREAD static int sigalrm_timer_init(void); static void sigalrm_timer_exit(void); TIMER_DRIVER timerdrv_unix_sigalrm = { TIMERDRV_UNIX_SIGALRM, empty_string, empty_string, "Unix SIGALRM timer", sigalrm_timer_init, sigalrm_timer_exit, NULL, NULL, /* install_int, remove_int */ NULL, NULL, /* install_param_int, remove_param_int */ NULL, NULL, /* can_simulate_retrace, simulate_retrace */ _unix_rest /* rest */ }; /* sigalrm_timerint: * Timer "interrupt" handler. */ static void sigalrm_timerint(unsigned long interval) { _handle_timer_tick(interval); } /* sigalrm_timer_init: * Installs the timer driver. */ static int sigalrm_timer_init(void) { if (_unix_bg_man != &_bg_man_sigalrm) return -1; DISABLE(); _sigalrm_timer_interrupt_handler = sigalrm_timerint; ENABLE(); return 0; } /* sigalrm_timer_exit: * Shuts down the timer driver. */ static void sigalrm_timer_exit(void) { DISABLE(); _sigalrm_timer_interrupt_handler = 0; ENABLE(); } #endif allegro-4.4.3.1/src/rsfb.c0000664000175000017500000007514113437077643014177 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sprite rotation routines. * * By Shawn Hargreaves. * * Flipping routines by Andrew Geers. * * Optimized by Sven Sandberg. * * Blending added by Trent Gamblin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include static int __col; /* Blender for draw_trans_*_sprite. */ /* 8 bit */ #define DTS_BLENDER8 COLOR_MAP* #define MAKE_DTS_BLENDER8() color_map #define DTS_BLEND8(b,o,n) ((b)->data[(n)& 0xFF][(o) & 0xFF]) /* 15 bit */ #define DTS_BLENDER15 BLENDER_FUNC #define MAKE_DTS_BLENDER15() _blender_func15 #define DTS_BLEND15(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* 16 bit */ #define DTS_BLENDER16 BLENDER_FUNC #define MAKE_DTS_BLENDER16() _blender_func16 #define DTS_BLEND16(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* 24 bit */ #define DTS_BLENDER24 BLENDER_FUNC #define MAKE_DTS_BLENDER24() _blender_func24 #define DTS_BLEND24(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* 32 bit */ #define DTS_BLENDER32 BLENDER_FUNC #define MAKE_DTS_BLENDER32() _blender_func32 #define DTS_BLEND32(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_lit_*_sprite. */ /* 8 bit */ #define DLS_BLENDER8 unsigned char* #define MAKE_DLS_BLENDER8(a) (color_map->data[(a) & 0xFF]) #define DLS_BLEND8(b,a,c) ((b)[(c) & 0xFF]) #define DLSX_BLEND8(b,c) ((b)[(c) & 0xFF]) /* 15 bit */ #define DLS_BLENDER15 BLENDER_FUNC #define MAKE_DLS_BLENDER15(a) _blender_func15 #define DLS_BLEND15(b,a,n) ((*(b))(_blender_col_15, (n), (a))) #define DLSX_BLEND15(b,n) ((*(b))(_blender_col_15, (n), _blender_alpha)) /* 16 bit */ #define DLS_BLENDER16 BLENDER_FUNC #define MAKE_DLS_BLENDER16(a) _blender_func16 #define DLS_BLEND16(b,a,n) ((*(b))(_blender_col_16, (n), (a))) #define DLSX_BLEND16(b,n) ((*(b))(_blender_col_16, (n), _blender_alpha)) /* 24 bit */ #define DLS_BLENDER24 BLENDER_FUNC #define MAKE_DLS_BLENDER24(a) _blender_func24 #define DLS_BLEND24(b,a,n) ((*(b))(_blender_col_24, (n), (a))) #define DLSX_BLEND24(b,n) ((*(b))(_blender_col_24, (n), _blender_alpha)) /* 32 bit */ #define DLS_BLENDER32 BLENDER_FUNC #define MAKE_DLS_BLENDER32(a) _blender_func32 #define DLS_BLEND32(b,a,n) ((*(b))(_blender_col_32, (n), (a))) #define DLSX_BLEND32(b,n) ((*(b))(_blender_col_32, (n), _blender_alpha)) #define SCANLINE_TRANS_DRAWER8(bits_pp, GETPIXEL) \ static void draw_scanline_trans_##bits_pp(BITMAP *bmp, BITMAP *spr,\ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c, c2; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DTS_BLENDER8 blender = MAKE_DTS_BLENDER8(); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c2 = bmp_read##bits_pp(addr); \ c = DTS_BLEND8(blender, c2, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_TRANS_DRAWER15(bits_pp, GETPIXEL) \ static void draw_scanline_trans_##bits_pp(BITMAP *bmp, BITMAP *spr,\ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c, c2; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DTS_BLENDER15 blender = MAKE_DTS_BLENDER15(); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c2 = bmp_read##bits_pp(addr); \ c = DTS_BLEND15(blender, c2, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_TRANS_DRAWER16(bits_pp, GETPIXEL) \ static void draw_scanline_trans_##bits_pp(BITMAP *bmp, BITMAP *spr,\ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c, c2; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DTS_BLENDER16 blender = MAKE_DTS_BLENDER16(); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c2 = bmp_read##bits_pp(addr); \ c = DTS_BLEND16(blender, c2, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_TRANS_DRAWER24(bits_pp, GETPIXEL) \ static void draw_scanline_trans_##bits_pp(BITMAP *bmp, BITMAP *spr,\ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c, c2; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DTS_BLENDER24 blender = MAKE_DTS_BLENDER24(); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c2 = bmp_read##bits_pp(addr); \ c = DTS_BLEND24(blender, c2, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_TRANS_DRAWER32(bits_pp, GETPIXEL) \ static void draw_scanline_trans_##bits_pp(BITMAP *bmp, BITMAP *spr,\ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c, c2; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DTS_BLENDER32 blender = MAKE_DTS_BLENDER32(); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c2 = bmp_read##bits_pp(addr); \ c = DTS_BLEND32(blender, c2, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_LIT_DRAWER8(bits_pp, GETPIXEL) \ static void draw_scanline_lit_##bits_pp(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DLS_BLENDER8 blender = MAKE_DLS_BLENDER8(__col); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c = DLS_BLEND8(blender, __col, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_LIT_DRAWER15(bits_pp, GETPIXEL) \ static void draw_scanline_lit_##bits_pp(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DLS_BLENDER15 blender = MAKE_DLS_BLENDER15(__col); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c = DLS_BLEND15(blender, __col, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_LIT_DRAWER16(bits_pp, GETPIXEL) \ static void draw_scanline_lit_##bits_pp(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DLS_BLENDER16 blender = MAKE_DLS_BLENDER16(__col); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c = DLS_BLEND16(blender, __col, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_LIT_DRAWER24(bits_pp, GETPIXEL) \ static void draw_scanline_lit_##bits_pp(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DLS_BLENDER24 blender = MAKE_DLS_BLENDER24(__col); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c = DLS_BLEND24(blender, __col, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #define SCANLINE_LIT_DRAWER32(bits_pp, GETPIXEL) \ static void draw_scanline_lit_##bits_pp(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ DLS_BLENDER32 blender = MAKE_DLS_BLENDER32(__col); \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) { \ c = DLS_BLEND32(blender, __col, c); \ bmp_write##bits_pp(addr, c); \ } \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #ifdef ALLEGRO_COLOR8 SCANLINE_TRANS_DRAWER8(8, c = spr_line[l_spr_y>>16][l_spr_x>>16]); SCANLINE_LIT_DRAWER8(8, c = spr_line[l_spr_y>>16][l_spr_x>>16]); #endif #ifdef ALLEGRO_COLOR16 SCANLINE_TRANS_DRAWER15(15, c = ((unsigned short *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) SCANLINE_TRANS_DRAWER16(16, c = ((unsigned short *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) SCANLINE_LIT_DRAWER15(15, c = ((unsigned short *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) SCANLINE_LIT_DRAWER16(16, c = ((unsigned short *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) #endif #ifdef ALLEGRO_COLOR24 #ifdef ALLEGRO_LITTLE_ENDIAN SCANLINE_TRANS_DRAWER24(24, { unsigned char *p = spr_line[l_spr_y>>16] + (l_spr_x>>16) * 3; c = p[0]; c |= (int)p[1] << 8; c |= (int)p[2] << 16; }) SCANLINE_LIT_DRAWER24(24, { unsigned char *p = spr_line[l_spr_y>>16] + (l_spr_x>>16) * 3; c = p[0]; c |= (int)p[1] << 8; c |= (int)p[2] << 16; }) #else SCANLINE_TRANS_DRAWER24(24, { unsigned char *p = spr_line[l_spr_y>>16] + (l_spr_x>>16) * 3; c = (int)p[0] << 16; c |= (int)p[1] << 8; c |= p[2]; }) SCANLINE_LIT_DRAWER24(24, { unsigned char *p = spr_line[l_spr_y>>16] + (l_spr_x>>16) * 3; c = (int)p[0] << 16; c |= (int)p[1] << 8; c |= p[2]; }) #endif #endif #ifdef ALLEGRO_COLOR32 SCANLINE_TRANS_DRAWER32(32, c = ((uint32_t *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) SCANLINE_LIT_DRAWER32(32, c = ((uint32_t *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) #endif /* _parallelogram_map_standard_trans: * Helper function for calling _parallelogram_map() with the appropriate * scanline drawer. I didn't want to include this in the * _parallelogram_map() function since then you can bypass it and define * your own scanline drawer, eg. for anti-aliased rotations. */ static void _parallelogram_map_standard_trans(BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4]) { if (is_linear_bitmap(bmp)) { switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_trans_8, FALSE); break; #endif #ifdef ALLEGRO_COLOR16 case 15: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_trans_15, FALSE); break; case 16: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_trans_16, FALSE); break; #endif #ifdef ALLEGRO_COLOR24 case 24: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_trans_24, FALSE); break; #endif #ifdef ALLEGRO_COLOR32 case 32: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_trans_32, FALSE); break; #endif default: /* NOTREACHED */ ASSERT(0); } } } /* _parallelogram_map_standard_lit: * Helper function for calling _parallelogram_map() with the appropriate * scanline drawer. I didn't want to include this in the * _parallelogram_map() function since then you can bypass it and define * your own scanline drawer, eg. for anti-aliased rotations. */ static void _parallelogram_map_standard_lit(BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4], int color) { __col = color; if (is_linear_bitmap(bmp)) { switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_lit_8, FALSE); break; #endif #ifdef ALLEGRO_COLOR16 case 15: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_lit_15, FALSE); break; case 16: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_lit_16, FALSE); break; #endif #ifdef ALLEGRO_COLOR24 case 24: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_lit_24, FALSE); break; #endif #ifdef ALLEGRO_COLOR32 case 32: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_lit_32, FALSE); break; #endif default: /* NOTREACHED */ ASSERT(0); } } } /* _pivot_scaled_sprite_flip_trans: * The most generic routine to which you specify the position with angles, * scales, etc. */ static void _pivot_scaled_sprite_flip_trans(BITMAP *bmp, BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip) { fixed xs[4], ys[4]; _rotate_scale_flip_coordinates(sprite->w << 16, sprite->h << 16, x, y, cx, cy, angle, scale, scale, FALSE, v_flip, xs, ys); _parallelogram_map_standard_trans(bmp, sprite, xs, ys); } /* _pivot_scaled_sprite_flip_trans: * The most generic routine to which you specify the position with angles, * scales, etc. */ static void _pivot_scaled_sprite_flip_lit(BITMAP *bmp, BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip, int color) { fixed xs[4], ys[4]; _rotate_scale_flip_coordinates(sprite->w << 16, sprite->h << 16, x, y, cx, cy, angle, scale, scale, FALSE, v_flip, xs, ys); _parallelogram_map_standard_lit(bmp, sprite, xs, ys, color); } void rotate_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000, FALSE); } void rotate_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000, TRUE); } void rotate_scaled_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, (y<<16) + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, FALSE); } void rotate_scaled_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, (y<<16) + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, TRUE); } void pivot_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, FALSE); } void pivot_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, TRUE); } void pivot_scaled_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, FALSE); } void pivot_scaled_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_trans(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, TRUE); } void rotate_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000, FALSE, color); } void rotate_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, (y<<16) + (sprite->h * 0x10000) / 2, sprite->w << 15, sprite->h << 15, angle, 0x10000, TRUE, color); } void rotate_scaled_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, (y<<16) + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, FALSE, color); } void rotate_scaled_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, (y<<16) + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, TRUE, color); } void pivot_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, FALSE, color); } void pivot_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, TRUE, color); } void pivot_scaled_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, FALSE, color); } void pivot_scaled_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale, int color) { ASSERT(bmp); ASSERT(sprite); _pivot_scaled_sprite_flip_lit(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, TRUE, color); } allegro-4.4.3.1/src/vtable8.c0000664000175000017500000000445613437077643014611 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Table of functions for drawing onto 8 bit linear bitmaps. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_COLOR8 void _linear_draw_sprite8_end(void); void _linear_blit8_end(void); GFX_VTABLE __linear_vtable8 = { 8, MASK_COLOR_8, _stub_unbank_switch, NULL, NULL, NULL, NULL, NULL, _linear_getpixel8, _linear_putpixel8, _linear_vline8, _linear_hline8, _linear_hline8, _normal_line, _fast_line, _normal_rectfill, _soft_triangle, _linear_draw_sprite8, _linear_draw_sprite8, _linear_draw_sprite_v_flip8, _linear_draw_sprite_h_flip8, _linear_draw_sprite_vh_flip8, _linear_draw_trans_sprite8, NULL, _linear_draw_lit_sprite8, _linear_draw_rle_sprite8, _linear_draw_trans_rle_sprite8, NULL, _linear_draw_lit_rle_sprite8, _linear_draw_character8, _linear_draw_glyph8, _linear_blit8, _linear_blit8, _linear_blit8, _linear_blit8, _linear_blit8, _linear_blit8, _linear_blit_backward8, _blit_between_formats, _linear_masked_blit8, _linear_clear_to_color8, _pivot_scaled_sprite_flip, NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) _soft_draw_gouraud_sprite, _linear_draw_sprite8_end, _linear_blit8_end, _soft_polygon, _soft_rect, _soft_circle, _soft_circlefill, _soft_ellipse, _soft_ellipsefill, _soft_arc, _soft_spline, _soft_floodfill, _soft_polygon3d, _soft_polygon3d_f, _soft_triangle3d, _soft_triangle3d_f, _soft_quad3d, _soft_quad3d_f, _linear_draw_sprite_ex8 }; #endif allegro-4.4.3.1/src/spline.c0000664000175000017500000001274513437077643014536 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Bezier spline plotter. * * By Seymour Shlien. * * Optimised version by Sven Sandberg. * * I'm not sure wether or not we still use the Castelau Algorithm * described in the book :o) * * Interactive Computer Graphics * by Peter Burger and Duncan Gillies * Addison-Wesley Publishing Co 1989 * ISBN 0-201-17439-1 * * The 4 th order Bezier curve is a cubic curve passing * through the first and fourth point. The curve does * not pass through the middle two points. They are merely * guide points which control the shape of the curve. The * curve is tangent to the lines joining points 1 and 2 * and points 3 and 4. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* calc_spline: * Calculates a set of pixels for the bezier spline defined by the four * points specified in the points array. The required resolution * is specified by the npts parameter, which controls how many output * pixels will be stored in the x and y arrays. */ void calc_spline(AL_CONST int points[8], int npts, int *out_x, int *out_y) { /* Derivatives of x(t) and y(t). */ double x, dx, ddx, dddx; double y, dy, ddy, dddy; int i; /* Temp variables used in the setup. */ double dt, dt2, dt3; double xdt2_term, xdt3_term; double ydt2_term, ydt3_term; dt = 1.0 / (npts-1); dt2 = (dt * dt); dt3 = (dt2 * dt); /* x coordinates. */ xdt2_term = 3 * (points[4] - 2*points[2] + points[0]); xdt3_term = points[6] + 3 * (-points[4] + points[2]) - points[0]; xdt2_term = dt2 * xdt2_term; xdt3_term = dt3 * xdt3_term; dddx = 6*xdt3_term; ddx = -6*xdt3_term + 2*xdt2_term; dx = xdt3_term - xdt2_term + 3 * dt * (points[2] - points[0]); x = points[0]; out_x[0] = points[0]; x += .5; for (i=1; i MAX_POINTS) num_points = MAX_POINTS; calc_spline(points, num_points, xpts, ypts); acquire_bitmap(bmp); if ((_drawing_mode == DRAW_MODE_XOR) || (_drawing_mode == DRAW_MODE_TRANS)) { /* Must compensate for the end pixel being drawn twice, hence the mess. */ old_drawing_mode = _drawing_mode; old_drawing_pattern = _drawing_pattern; old_drawing_x_anchor = _drawing_x_anchor; old_drawing_y_anchor = _drawing_y_anchor; for (i=1; i #include #define RESYNC() XDGASync(_xwin.display, _xwin.screen); static XDGADevice *dga_device = NULL; static char _xdga2_driver_desc[256] = EMPTY_STRING; static Colormap _dga_cmap = 0; static int dga_event_base; static int keyboard_got_focus = FALSE; static int _xdga2_find_mode(int w, int h, int vw, int vh, int depth); static void _xdga2_handle_input(void); static BITMAP *_xdga2_gfxdrv_init(int w, int h, int vw, int vh, int color_depth); static BITMAP *_xdga2_soft_gfxdrv_init(int w, int h, int vw, int vh, int color_depth); static void _xdga2_gfxdrv_exit(BITMAP *bmp); static int _xdga2_poll_scroll(void); static int _xdga2_request_scroll(int x, int y); static int _xdga2_request_video_bitmap(BITMAP *bmp); static int _xdga2_scroll_screen(int x, int y); static void _xdga2_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync); static void _xdga2_acquire(BITMAP *bmp); static GFX_MODE_LIST *_xdga2_fetch_mode_list(void); #ifdef ALLEGRO_NO_ASM uintptr_t _xdga2_write_line(BITMAP *bmp, int line); #else uintptr_t _xdga2_write_line_asm(BITMAP *bmp, int line); #endif static void (*_orig_hline) (BITMAP *bmp, int x1, int y, int x2, int color); static void (*_orig_vline) (BITMAP *bmp, int x, int y1, int y2, int color); static void (*_orig_rectfill) (BITMAP *bmp, int x1, int y1, int x2, int y2, int color); static void (*_orig_draw_sprite) (BITMAP *bmp, BITMAP *sprite, int x, int y); static void (*_orig_masked_blit) (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void _xaccel_hline(BITMAP *bmp, int x1, int y, int x2, int color); static void _xaccel_vline(BITMAP *bmp, int x, int y1, int y2, int color); static void _xaccel_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); static void _xaccel_clear_to_color(BITMAP *bmp, int color); static void _xaccel_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void _xaccel_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y); static void _xaccel_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); #define DGA_MAX_EVENTS 5 GFX_DRIVER gfx_xdga2 = { GFX_XDGA2, empty_string, empty_string, "DGA 2.0", _xdga2_gfxdrv_init, _xdga2_gfxdrv_exit, _xdga2_scroll_screen, _xwin_vsync, _xdga2_set_palette_range, _xdga2_request_scroll, _xdga2_poll_scroll, NULL, NULL, NULL, NULL, _xdga2_request_video_bitmap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, _xdga2_fetch_mode_list, 640, 480, TRUE, 0, 0, 0, 0, FALSE }; GFX_DRIVER gfx_xdga2_soft = { GFX_XDGA2_SOFT, empty_string, empty_string, "DGA 2.0 soft", _xdga2_soft_gfxdrv_init, _xdga2_gfxdrv_exit, _xdga2_scroll_screen, _xwin_vsync, _xdga2_set_palette_range, _xdga2_request_scroll, _xdga2_poll_scroll, NULL, NULL, NULL, NULL, _xdga2_request_video_bitmap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, _xdga2_fetch_mode_list, 640, 480, TRUE, 0, 0, 0, 0, FALSE }; /* _xdga2_fetch_mode_list: * Creates list of available DGA2 video modes. */ static GFX_MODE_LIST *_xdga2_private_fetch_mode_list(void) { XDGAMode *mode; int bpp, num_modes, stored_modes, i, j, already_there; GFX_MODE_LIST *mode_list; GFX_MODE *tmp; mode = XDGAQueryModes(_xwin.display, _xwin.screen, &num_modes); if (!mode) return NULL; mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) goto error; mode_list->mode = NULL; stored_modes = 0; for (i=0; imode[j].width == mode[i].viewportWidth) && (mode_list->mode[j].height == mode[i].viewportHeight) && (mode_list->mode[j].bpp == bpp)) { already_there = TRUE; break; } } if (!already_there) { tmp = _AL_REALLOC(mode_list->mode, sizeof(GFX_MODE) * (stored_modes + 1)); if (!tmp) goto error; mode_list->mode = tmp; mode_list->mode[stored_modes].width = mode[i].viewportWidth; mode_list->mode[stored_modes].height = mode[i].viewportHeight; mode_list->mode[stored_modes].bpp = bpp; stored_modes++; } } tmp = _AL_REALLOC(mode_list->mode, sizeof(GFX_MODE) * (stored_modes + 1)); if (!tmp) goto error; mode_list->mode = tmp; mode_list->mode[stored_modes].width = 0; mode_list->mode[stored_modes].height = 0; mode_list->mode[stored_modes].bpp = 0; mode_list->num_modes = stored_modes; XFree(mode); return mode_list; error: if (mode_list) { _AL_FREE(mode_list->mode); _AL_FREE(mode_list); } XFree(mode); return NULL; } static GFX_MODE_LIST *_xdga2_fetch_mode_list(void) { GFX_MODE_LIST *list; XLOCK (); list = _xdga2_private_fetch_mode_list(); XUNLOCK (); return list; } /* _xdga2_find_mode: * Returns id number of specified video mode if available, 0 otherwise. */ static int _xdga2_find_mode(int w, int h, int vw, int vh, int depth) { XDGAMode *mode; int num_modes; int bpp, i, found; mode = XDGAQueryModes(_xwin.display, _xwin.screen, &num_modes); if (!mode) return 0; /* Let's first try setting also requested refresh rate */ for (i=0; i= vw) && (mode[i].imageHeight >= vh) && (mode[i].verticalRefresh >= _refresh_rate_request) && (bpp == depth)) break; } if (i == num_modes) { /* No modes were found, so now we don't care about refresh rate */ for (i=0; i= vw) && (mode[i].imageHeight >= vh) && (bpp == depth)) break; } if (i == num_modes) { /* No way out: mode not found */ XFree(mode); return 0; } } found = mode[i].num; XFree(mode); return found; } /* _xdga2_handle_input: * Handles DGA events pending from queue. */ static void _xdga2_handle_input(void) { int i, events, events_queued; static XDGAEvent event[DGA_MAX_EVENTS + 1]; XDGAEvent *cur_event; XKeyEvent key; int dx, dy, dz = 0; static int mouse_buttons = 0; if (_xwin.display == 0) return; XSync(_xwin.display, False); /* How much events are available in the queue. */ events = events_queued = XEventsQueued(_xwin.display, QueuedAlready); if (events <= 0) return; /* Limit amount of events we read at once. */ if (events > DGA_MAX_EVENTS) events = DGA_MAX_EVENTS; /* Read pending events. */ for (i = 0; i < events; i++) XNextEvent(_xwin.display, (XEvent *)&event[i]); /* see xwin.c */ if (events_queued > events && event[i - 1].type == dga_event_base+KeyRelease) { XNextEvent(_xwin.display, (XEvent *)&event[i]); events++; } /* Process all events. */ for (i = 0; i < events; i++) { /* see xwin.c */ if (event[i].type == dga_event_base+KeyRelease && (i + 1) < events) { if (event[i + 1].type == dga_event_base+KeyPress) { if (event[i].xkey.keycode == event[i + 1].xkey.keycode && event[i].xkey.time == event[i + 1].xkey.time) continue; } } cur_event = &event[i]; switch (cur_event->type - dga_event_base) { case KeyPress: XDGAKeyEventToXKeyEvent(&cur_event->xkey, &key); key.type -= dga_event_base; _xwin_keyboard_handler(&key, TRUE); break; case KeyRelease: XDGAKeyEventToXKeyEvent(&cur_event->xkey, &key); key.type -= dga_event_base; _xwin_keyboard_handler(&key, TRUE); break; case ButtonPress: if (cur_event->xbutton.button == Button1) mouse_buttons |= 1; else if (cur_event->xbutton.button == Button3) mouse_buttons |= 2; else if (cur_event->xbutton.button == Button2) mouse_buttons |= 4; else if (cur_event->xbutton.button == Button4) dz = 1; else if (cur_event->xbutton.button == Button5) dz = -1; if (_xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(0, 0, dz, 0, mouse_buttons); break; case ButtonRelease: if (cur_event->xbutton.button == Button1) mouse_buttons &= ~1; else if (cur_event->xbutton.button == Button3) mouse_buttons &= ~2; else if (cur_event->xbutton.button == Button2) mouse_buttons &= ~4; if (_xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons); break; case MotionNotify: dx = cur_event->xmotion.dx; dy = cur_event->xmotion.dy; if (((dx != 0) || (dy != 0)) && _xwin_mouse_interrupt) { (*_xwin_mouse_interrupt)(dx, dy, 0, 0, mouse_buttons); } break; default: break; } } } /* _xdga2_display_is_local: * Tests that display connection is local. * (Note: this is duplicated in xwin.c). */ static int _xdga2_private_display_is_local(void) { char *name; if (_xwin.display == 0) return 0; /* Get display name and test for local display. */ name = XDisplayName(0); return (((name == 0) || (name[0] == ':') || (strncmp(name, "unix:", 5) == 0)) ? 1 : 0); } /* _xdga2_gfxdrv_init_drv: * Initializes driver and creates screen bitmap. */ static BITMAP *_xdga2_private_gfxdrv_init_drv(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int accel) { int dga_error_base, dga_major_version, dga_minor_version; int mode, mask, red_shift = 0, green_shift = 0, blue_shift = 0; long input_mask; char tmp1[128], tmp2[128]; BITMAP *bmp; /* This is just to test if the system driver has been installed properly */ if (_xwin.window == None) return NULL; /* Test that display is local. */ if (!_xdga2_private_display_is_local()) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("This driver needs local display")); return NULL; } /* Choose convenient size. */ if ((w == 0) && (h == 0)) { w = 640; h = 480; } if ((w < 80) || (h < 80) || (w > 4096) || (h > 4096)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported screen size")); return NULL; } if (vw < w) vw = w; if (vh < h) vh = h; if (1 #ifdef ALLEGRO_COLOR8 && (depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (depth != 15) && (depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } /* Checks presence of DGA extension */ if (!XDGAQueryExtension(_xwin.display, &dga_event_base, &dga_error_base) || !XDGAQueryVersion(_xwin.display, &dga_major_version, &dga_minor_version)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DGA extension is not supported")); return NULL; } /* Works only with DGA 2.0 or newer */ if (dga_major_version < 2) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DGA 2.0 or newer is required")); return NULL; } /* Attempts to access the framebuffer */ if (!XDGAOpenFramebuffer(_xwin.display, _xwin.screen)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open framebuffer")); return NULL; } /* Finds suitable video mode number */ mode = _xdga2_find_mode(w, h, vw, vh, depth); if (!mode) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } /* Sets DGA video mode */ dga_device = XDGASetMode(_xwin.display, _xwin.screen, mode); if (dga_device == NULL) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not switch to DGA mode")); return NULL; } _xwin.in_dga_mode = 2; _set_current_refresh_rate(dga_device->mode.verticalRefresh); set_display_switch_mode(SWITCH_NONE); /* Installs DGA color map */ if (_dga_cmap) { XFreeColormap(_xwin.display, _dga_cmap); _dga_cmap = 0; } if ((dga_device->mode.visualClass == PseudoColor) || (dga_device->mode.visualClass == GrayScale) || (dga_device->mode.visualClass == DirectColor)) _dga_cmap = XDGACreateColormap(_xwin.display, _xwin.screen, dga_device, AllocAll); else _dga_cmap = XDGACreateColormap(_xwin.display, _xwin.screen, dga_device, AllocNone); XDGAInstallColormap(_xwin.display, _xwin.screen, _dga_cmap); /* Sets up direct color shifts */ if (depth != 8) { for (mask = dga_device->mode.redMask, red_shift = 0; (mask & 1) == 0; mask >>= 1, red_shift++); for (mask = dga_device->mode.greenMask, green_shift = 0; (mask & 1) == 0; mask >>= 1, green_shift++); for (mask = dga_device->mode.blueMask, blue_shift = 0; (mask & 1) == 0; mask >>= 1, blue_shift++); } switch (depth) { case 15: _rgb_r_shift_15 = red_shift; _rgb_g_shift_15 = green_shift; _rgb_b_shift_15 = blue_shift; break; case 16: _rgb_r_shift_16 = red_shift; _rgb_g_shift_16 = green_shift; _rgb_b_shift_16 = blue_shift; break; case 24: _rgb_r_shift_24 = red_shift; _rgb_g_shift_24 = green_shift; _rgb_b_shift_24 = blue_shift; break; case 32: _rgb_r_shift_32 = red_shift; _rgb_g_shift_32 = green_shift; _rgb_b_shift_32 = blue_shift; break; } /* Enables input */ XSync(_xwin.display, True); input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; XDGASelectInput(_xwin.display, _xwin.screen, input_mask); if (_xwin_keyboard_focused) { (*_xwin_keyboard_focused)(FALSE, 0); keyboard_got_focus = TRUE; } _mouse_on = TRUE; /* Creates screen bitmap */ drv->linear = TRUE; bmp = _make_bitmap(dga_device->mode.imageWidth, dga_device->mode.imageHeight, (uintptr_t)dga_device->data, drv, depth, dga_device->mode.bytesPerScanline); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } drv->w = bmp->cr = w; drv->h = bmp->cb = h; drv->vid_mem = dga_device->mode.imageWidth * dga_device->mode.imageHeight * BYTES_PER_PIXEL(depth); if (accel) { /* Hardware acceleration has been requested */ /* Updates line switcher to accommodate framebuffer synchronization */ #ifdef ALLEGRO_NO_ASM bmp->write_bank = _xdga2_write_line; bmp->read_bank = _xdga2_write_line; #else bmp->write_bank = _xdga2_write_line_asm; bmp->read_bank = _xdga2_write_line_asm; #endif _screen_vtable.acquire = _xdga2_acquire; /* Checks for hardware acceleration support */ if (dga_device->mode.flags & XDGASolidFillRect) { /* XDGAFillRectangle is available */ _orig_hline = _screen_vtable.hline; _orig_vline = _screen_vtable.vline; _orig_rectfill = _screen_vtable.rectfill; _screen_vtable.hline = _xaccel_hline; _screen_vtable.vline = _xaccel_vline; _screen_vtable.rectfill = _xaccel_rectfill; _screen_vtable.clear_to_color = _xaccel_clear_to_color; gfx_capabilities |= (GFX_HW_HLINE | GFX_HW_FILL); } if (dga_device->mode.flags & XDGABlitRect) { /* XDGACopyArea is available */ _screen_vtable.blit_to_self = _xaccel_blit_to_self; _screen_vtable.blit_to_self_forward = _xaccel_blit_to_self; _screen_vtable.blit_to_self_backward = _xaccel_blit_to_self; gfx_capabilities |= GFX_HW_VRAM_BLIT; } if (dga_device->mode.flags & XDGABlitTransRect) { /* XDGACopyTransparentArea is available */ _orig_draw_sprite = _screen_vtable.draw_sprite; _orig_masked_blit = _screen_vtable.masked_blit; _screen_vtable.masked_blit = _xaccel_masked_blit; _screen_vtable.draw_sprite = _xaccel_draw_sprite; if (_screen_vtable.color_depth == 8) _screen_vtable.draw_256_sprite = _xaccel_draw_sprite; gfx_capabilities |= GFX_HW_VRAM_BLIT_MASKED; } RESYNC(); } /* Checks for triple buffering */ if (dga_device->mode.viewportFlags & XDGAFlipRetrace) gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; /* Sets up driver description */ uszprintf(_xdga2_driver_desc, sizeof(_xdga2_driver_desc), uconvert_ascii("X-Windows DGA 2.0 graphics%s", tmp1), uconvert_ascii(accel ? (gfx_capabilities ? " (accelerated)" : "") : " (software only)", tmp2)); drv->desc = _xdga2_driver_desc; return bmp; } static BITMAP *_xdga2_gfxdrv_init_drv(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int accel) { BITMAP *bmp; XLOCK(); bmp = _xdga2_private_gfxdrv_init_drv(drv, w, h, vw, vh, depth, accel); XUNLOCK(); if (!bmp) _xdga2_gfxdrv_exit(bmp); else _xwin_input_handler = _xdga2_handle_input; return bmp; } /* _xdga2_gfxdrv_init: * Creates screen bitmap. */ static BITMAP *_xdga2_gfxdrv_init(int w, int h, int vw, int vh, int color_depth) { return _xdga2_gfxdrv_init_drv(&gfx_xdga2, w, h, vw, vh, color_depth, TRUE); } /* _xdga2_soft_gfxdrv_init: * Creates screen bitmap (software only mode). */ static BITMAP *_xdga2_soft_gfxdrv_init(int w, int h, int vw, int vh, int color_depth) { return _xdga2_gfxdrv_init_drv(&gfx_xdga2_soft, w, h, vw, vh, color_depth, FALSE); } /* _xdga2_gfxdrv_exit: * Shuts down gfx driver. */ static void _xdga2_gfxdrv_exit(BITMAP *bmp) { XLOCK(); if (_xwin.in_dga_mode) { _xwin_input_handler = 0; XDGACloseFramebuffer(_xwin.display, _xwin.screen); XDGASetMode(_xwin.display, _xwin.screen, 0); _xwin.in_dga_mode = 0; if (_dga_cmap) { XFreeColormap(_xwin.display, _dga_cmap); _dga_cmap = 0; } XInstallColormap(_xwin.display, _xwin.colormap); set_display_switch_mode(SWITCH_BACKGROUND); } XUNLOCK(); } /* _xdga2_poll_scroll: * Returns true if there are pending scrolling requests left. */ static int _xdga2_poll_scroll(void) { int result; XLOCK(); result = XDGAGetViewportStatus(_xwin.display, _xwin.screen); XUNLOCK(); return result; } /* _xdga2_request_scroll: * Starts a screen scroll but doesn't wait for the retrace. */ static int _xdga2_request_scroll(int x, int y) { XLOCK(); if (x < 0) x = 0; else if (x > dga_device->mode.maxViewportX) x = dga_device->mode.maxViewportX; if (y < 0) y = 0; else if (y > dga_device->mode.maxViewportY) y = dga_device->mode.maxViewportY; XDGASetViewport(_xwin.display, _xwin.screen, x, y, XDGAFlipRetrace); XUNLOCK(); return 0; } /* _xdga2_request_video_bitmap: * Page flips to display specified bitmap, but doesn't wait for retrace. */ static int _xdga2_request_video_bitmap(BITMAP *bmp) { XLOCK(); XDGASetViewport(_xwin.display, _xwin.screen, bmp->x_ofs, bmp->y_ofs, XDGAFlipRetrace); XUNLOCK(); return 0; } /* _xdga2_scroll_screen: * Scrolls DGA viewport. */ static int _xdga2_scroll_screen(int x, int y) { if (x < 0) x = 0; else if (x > dga_device->mode.maxViewportX) x = dga_device->mode.maxViewportX; if (y < 0) y = 0; else if (y > dga_device->mode.maxViewportY) y = dga_device->mode.maxViewportY; if ((_xwin.scroll_x == x) && (_xwin.scroll_y == y)) return 0; XLOCK(); _xwin.scroll_x = x; _xwin.scroll_y = y; if (_wait_for_vsync) while (XDGAGetViewportStatus(_xwin.display, _xwin.screen)) ; XDGASetViewport(_xwin.display, _xwin.screen, x, y, XDGAFlipRetrace); XUNLOCK(); return 0; } /* _xdga2_set_palette_range: * Sets palette entries. */ static void _xdga2_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) { int i; static XColor color[256]; XLOCK(); if (vsync) { XSync(_xwin.display, False); } if (dga_device->mode.depth == 8) { for (i = from; i <= to; i++) { color[i].flags = DoRed | DoGreen | DoBlue; color[i].pixel = i; color[i].red = ((p[i].r & 0x3F) * 65535L) / 0x3F; color[i].green = ((p[i].g & 0x3F) * 65535L) / 0x3F; color[i].blue = ((p[i].b & 0x3F) * 65535L) / 0x3F; } XStoreColors(_xwin.display, _dga_cmap, color + from, to - from + 1); XSync(_xwin.display, False); } XUNLOCK(); } /* _xdga2_lock: * Synchronizes with framebuffer. */ void _xdga2_lock(BITMAP *bmp) { XLOCK(); RESYNC(); XUNLOCK(); bmp->id |= BMP_ID_LOCKED; } /* _xdga2_acquire: * Video bitmap acquire function; synchronizes with framebuffer if needed. */ static void _xdga2_acquire(BITMAP *bmp) { if (!(bmp->id & BMP_ID_LOCKED)) _xdga2_lock(bmp); } #ifdef ALLEGRO_NO_ASM /* _xdga2_write_line: * Returns new line and synchronizes framebuffer if needed. */ uintptr_t _xdga2_write_line(BITMAP *bmp, int line) { if (!(bmp->id & BMP_ID_LOCKED)) _xdga2_lock(bmp); return (uintptr_t)(bmp->line[line]); } #endif /* _xaccel_hline: * Accelerated hline. */ static void _xaccel_hline(BITMAP *bmp, int x1, int y, int x2, int color) { int tmp; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_hline(bmp, x1, y, x2, color); return; } if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } if (bmp->clip) { if ((y < bmp->ct) || (y >= bmp->cb)) return; if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; } x1 += bmp->x_ofs; y += bmp->y_ofs; x2 += bmp->x_ofs; XLOCK(); XDGAFillRectangle(_xwin.display, _xwin.screen, x1, y, (x2 - x1) + 1, 1, color); XUNLOCK(); bmp->id &= ~BMP_ID_LOCKED; } /* _xaccel_vline: * Accelerated vline. */ static void _xaccel_vline(BITMAP *bmp, int x, int y1, int y2, int color) { int tmp; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_vline(bmp, x, y1, y2, color); return; } if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if ((x < bmp->cl) || (x >= bmp->cr)) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } x += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; XLOCK(); XDGAFillRectangle(_xwin.display, _xwin.screen, x, y1, 1, (y2 - y1) + 1, color); XUNLOCK(); bmp->id &= ~BMP_ID_LOCKED; } /* _xaccel_rectfill: * Accelerated rectfill. */ static void _xaccel_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { int tmp; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_rectfill(bmp, x1, y1, x2, y2, color); return; } if (x2 < x1) { tmp = x1; x1 = x2; x2 = tmp; } if (y2 < y1) { tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } x1 += bmp->x_ofs; y1 += bmp->y_ofs; x2 += bmp->x_ofs; y2 += bmp->y_ofs; XLOCK(); XDGAFillRectangle(_xwin.display, _xwin.screen, x1, y1, (x2 - x1) + 1, (y2 - y1) + 1, color); XUNLOCK(); bmp->id &= ~BMP_ID_LOCKED; } /* _xaccel_clear_to_color: * Accelerated clear_to_color. */ static void _xaccel_clear_to_color(BITMAP *bmp, int color) { int x1, y1, x2, y2; x1 = bmp->cl + bmp->x_ofs; y1 = bmp->ct + bmp->y_ofs; x2 = bmp->cr + bmp->x_ofs; y2 = bmp->cb + bmp->y_ofs; XLOCK(); XDGAFillRectangle(_xwin.display, _xwin.screen, x1, y1, x2 - x1, y2 - y1, color); XUNLOCK(); bmp->id &= ~BMP_ID_LOCKED; } /* _xaccel_blit_to_self: * Accelerated vram -> vram blit. */ static void _xaccel_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { source_x += source->x_ofs; source_y += source->y_ofs; dest_x += dest->x_ofs; dest_y += dest->y_ofs; XLOCK(); XDGACopyArea(_xwin.display, _xwin.screen, source_x, source_y, width, height, dest_x, dest_y); XUNLOCK(); dest->id &= ~BMP_ID_LOCKED; } /* _xaccel_draw_sprite: * Accelerated draw_sprite. */ static void _xaccel_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) { int sx, sy, w, h; if (is_video_bitmap(sprite)) { sx = 0; sy = 0; w = sprite->w; h = sprite->h; if (bmp->clip) { if (x < bmp->cl) { sx += bmp->cl - x; w -= bmp->cl - x; x = bmp->cl; } if (y < bmp->ct) { sy += bmp->ct - y; h -= bmp->ct - y; y = bmp->ct; } if (x + w > bmp->cr) w = bmp->cr - x; if (w <= 0) return; if (y + h > bmp->cb) h = bmp->cb - y; if (h <= 0) return; } sx += sprite->x_ofs; sy += sprite->y_ofs; x += bmp->x_ofs; y += bmp->y_ofs; XLOCK(); XDGACopyTransparentArea(_xwin.display, _xwin.screen, sx, sy, w, h, x, y, sprite->vtable->mask_color); XUNLOCK(); bmp->id &= ~BMP_ID_LOCKED; } else _orig_draw_sprite(bmp, sprite, x, y); } /* _xaccel_masked_blit: * Accelerated masked_blit. */ static void _xaccel_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { if (is_video_bitmap(source)) { source_x += source->x_ofs; source_y += source->y_ofs; dest_x += dest->x_ofs; dest_y += dest->y_ofs; XLOCK(); XDGACopyTransparentArea(_xwin.display, _xwin.screen, source_x, source_y, width, height, dest_x, dest_y, source->vtable->mask_color); XUNLOCK(); dest->id &= ~BMP_ID_LOCKED; } else _orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height); } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { if (system_driver != SYSTEM_XWINDOWS) return; _unix_register_gfx_driver(GFX_XDGA2_SOFT, &gfx_xdga2_soft, FALSE, FALSE); _unix_register_gfx_driver(GFX_XDGA2, &gfx_xdga2, FALSE, FALSE); } #endif #endif allegro-4.4.3.1/src/x/xgfxdrv.c0000664000175000017500000000631213437077643015174 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video driver for X-Windows. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/platform/aintunix.h" #include "xwin.h" static BITMAP *_xwin_gfxdrv_init(int w, int h, int vw, int vh, int color_depth); static void _xwin_gfxdrv_exit(BITMAP *bmp); static GFX_DRIVER gfx_xwin = { GFX_XWINDOWS, empty_string, empty_string, "X11 window", _xwin_gfxdrv_init, _xwin_gfxdrv_exit, _xwin_scroll_screen, _xwin_vsync, _xwin_set_palette_range, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR _xwin_set_mouse_sprite, _xwin_show_mouse, _xwin_hide_mouse, _xwin_move_mouse, #else NULL, NULL, NULL, NULL, #endif _xwin_drawing_mode, NULL, NULL, NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, 320, 200, TRUE, 0, 0, 0x10000, 0, TRUE }; static BITMAP *_xwin_fullscreen_gfxdrv_init(int w, int h, int vw, int vh, int color_depth); static GFX_DRIVER gfx_xwin_fullscreen = { GFX_XWINDOWS_FULLSCREEN, empty_string, empty_string, "X11 fullscreen", _xwin_fullscreen_gfxdrv_init, _xwin_gfxdrv_exit, _xwin_scroll_screen, _xwin_vsync, _xwin_set_palette_range, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR _xwin_set_mouse_sprite, _xwin_show_mouse, _xwin_hide_mouse, _xwin_move_mouse, #else NULL, NULL, NULL, NULL, #endif _xwin_drawing_mode, NULL, NULL, NULL, _xwin_fetch_mode_list, 320, 200, TRUE, 0, 0, 0x10000, 0, FALSE }; /* list the available drivers */ _DRIVER_INFO _xwin_gfx_driver_list[] = { #if (defined ALLEGRO_XWINDOWS_WITH_XF86DGA2) && (!defined ALLEGRO_WITH_MODULES) { GFX_XDGA2, &gfx_xdga2, FALSE }, { GFX_XDGA2_SOFT, &gfx_xdga2_soft, FALSE }, #endif { GFX_XWINDOWS_FULLSCREEN, &gfx_xwin_fullscreen, TRUE }, { GFX_XWINDOWS, &gfx_xwin, TRUE }, { 0, NULL, 0 } }; /* _xwin_gfxdrv_init: * Creates screen bitmap. */ static BITMAP *_xwin_gfxdrv_init(int w, int h, int vw, int vh, int color_depth) { return _xwin_create_screen(&gfx_xwin, w, h, vw, vh, color_depth, FALSE); } /* _xwin_gfxdrv_exit: * Shuts down the X-Windows driver. */ static void _xwin_gfxdrv_exit(BITMAP *bmp) { _xwin_destroy_screen(); } /* _xwin_fullscreen_gfxdrv_init: * Creates screen bitmap (with video mode extension). */ static BITMAP *_xwin_fullscreen_gfxdrv_init(int w, int h, int vw, int vh, int color_depth) { return _xwin_create_screen(&gfx_xwin_fullscreen, w, h, vw, vh, color_depth, TRUE); } allegro-4.4.3.1/src/x/xsystem.c0000664000175000017500000002643313437077643015226 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main system driver for the X-Windows library. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/platform/aintunix.h" #include "xwin.h" #include #include #include #include #include #include #include void (*_xwin_keyboard_interrupt)(int pressed, int code) = 0; void (*_xwin_keyboard_focused)(int focused, int state) = 0; void (*_xwin_mouse_interrupt)(int x, int y, int z, int w, int buttons) = 0; static int _xwin_sysdrv_init(void); static void _xwin_sysdrv_exit(void); static void _xwin_sysdrv_set_window_title(AL_CONST char *name); static int _xwin_sysdrv_set_close_button_callback(void (*proc)(void)); static void _xwin_sysdrv_message(AL_CONST char *msg); static int _xwin_sysdrv_display_switch_mode(int mode); static int _xwin_sysdrv_desktop_color_depth(void); static int _xwin_sysdrv_get_desktop_resolution(int *width, int *height); static void _xwin_sysdrv_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); static _DRIVER_INFO *_xwin_sysdrv_gfx_drivers(void); static _DRIVER_INFO *_xwin_sysdrv_digi_drivers(void); static _DRIVER_INFO *_xwin_sysdrv_midi_drivers(void); static _DRIVER_INFO *_xwin_sysdrv_keyboard_drivers(void); static _DRIVER_INFO *_xwin_sysdrv_mouse_drivers(void); #ifdef ALLEGRO_HAVE_LINUX_JOYSTICK_H static _DRIVER_INFO *_xwin_sysdrv_joystick_drivers(void); #endif static _DRIVER_INFO *_xwin_sysdrv_timer_drivers(void); /* the main system driver for running under X-Windows */ SYSTEM_DRIVER system_xwin = { SYSTEM_XWINDOWS, empty_string, empty_string, "X-Windows", _xwin_sysdrv_init, _xwin_sysdrv_exit, _unix_get_executable_name, _unix_find_resource, _xwin_sysdrv_set_window_title, _xwin_sysdrv_set_close_button_callback, _xwin_sysdrv_message, NULL, /* assert */ NULL, /* save_console_state */ NULL, /* restore_console_state */ NULL, /* create_bitmap */ NULL, /* created_bitmap */ NULL, /* create_sub_bitmap */ NULL, /* created_sub_bitmap */ NULL, /* destroy_bitmap */ NULL, /* read_hardware_palette */ NULL, /* set_palette_range */ NULL, /* get_vtable */ _xwin_sysdrv_display_switch_mode, NULL, /* display_switch_lock */ _xwin_sysdrv_desktop_color_depth, _xwin_sysdrv_get_desktop_resolution, _xwin_sysdrv_get_gfx_safe_mode, _unix_yield_timeslice, #ifdef ALLEGRO_HAVE_LIBPTHREAD _unix_create_mutex, _unix_destroy_mutex, _unix_lock_mutex, _unix_unlock_mutex, #else NULL, /* create_mutex */ NULL, /* destroy_mutex */ NULL, /* lock_mutex */ NULL, /* unlock_mutex */ #endif _xwin_sysdrv_gfx_drivers, _xwin_sysdrv_digi_drivers, _xwin_sysdrv_midi_drivers, _xwin_sysdrv_keyboard_drivers, _xwin_sysdrv_mouse_drivers, #ifdef ALLEGRO_HAVE_LINUX_JOYSTICK_H _xwin_sysdrv_joystick_drivers, #else NULL, /* joystick_driver_list */ #endif _xwin_sysdrv_timer_drivers }; static RETSIGTYPE (*old_sig_abrt)(int num); static RETSIGTYPE (*old_sig_fpe)(int num); static RETSIGTYPE (*old_sig_ill)(int num); static RETSIGTYPE (*old_sig_segv)(int num); static RETSIGTYPE (*old_sig_term)(int num); static RETSIGTYPE (*old_sig_int)(int num); #ifdef SIGQUIT static RETSIGTYPE (*old_sig_quit)(int num); #endif /* _xwin_signal_handler: * Used to trap various signals, to make sure things get shut down cleanly. */ static RETSIGTYPE _xwin_signal_handler(int num) { if (_unix_bg_man->interrupts_disabled() || _xwin.lock_count) { /* Can not shutdown X-Windows, restore old signal handlers and slam the door. */ signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); #ifdef SIGQUIT signal(SIGQUIT, old_sig_quit); #endif raise(num); abort(); } else { allegro_exit(); fprintf(stderr, "Shutting down Allegro due to signal #%d\n", num); raise(num); } } /* _xwin_bg_handler: * Really used for synchronous stuff. */ static void _xwin_bg_handler(int threaded) { _xwin_handle_input(); } /* _xwin_sysdrv_init: * Top level system driver wakeup call. */ static int _xwin_sysdrv_init(void) { char tmp[256]; _unix_read_os_type(); /* install emergency-exit signal handlers */ old_sig_abrt = signal(SIGABRT, _xwin_signal_handler); old_sig_fpe = signal(SIGFPE, _xwin_signal_handler); old_sig_ill = signal(SIGILL, _xwin_signal_handler); old_sig_segv = signal(SIGSEGV, _xwin_signal_handler); old_sig_term = signal(SIGTERM, _xwin_signal_handler); old_sig_int = signal(SIGINT, _xwin_signal_handler); #ifdef SIGQUIT old_sig_quit = signal(SIGQUIT, _xwin_signal_handler); #endif /* Initialise dynamic driver lists and load modules */ _unix_driver_lists_init(); if (_unix_gfx_driver_list) _driver_list_append_list(&_unix_gfx_driver_list, _xwin_gfx_driver_list); _unix_load_modules(SYSTEM_XWINDOWS); #ifdef ALLEGRO_HAVE_LIBPTHREAD _unix_bg_man = &_bg_man_pthreads; #else _unix_bg_man = &_bg_man_sigalrm; #endif /* Initialise bg_man */ if (_unix_bg_man->init()) { _xwin_sysdrv_exit(); return -1; } #ifdef ALLEGRO_MULTITHREADED if (_unix_bg_man->multi_threaded) { _xwin.mutex = _unix_create_mutex(); } #endif get_executable_name(tmp, sizeof(tmp)); set_window_title(get_filename(tmp)); if (get_config_int("system", "XInitThreads", 1)) XInitThreads(); /* Open the display, create a window, and background-process * events for it all. */ if (_xwin_open_display(0) || _xwin_create_window() || _unix_bg_man->register_func(_xwin_bg_handler)) { _xwin_sysdrv_exit(); return -1; } set_display_switch_mode(SWITCH_BACKGROUND); return 0; } /* _xwin_sysdrv_exit: * The end of the world... */ static void _xwin_sysdrv_exit(void) { /* This stops the X event handler running in the background, which * seems a nice thing to do before closing the connection to the X * display... (remove this and you get SIGABRTs during XCloseDisplay). */ _unix_bg_man->unregister_func(_xwin_bg_handler); _xwin_close_display(); _unix_bg_man->exit(); _unix_unload_modules(); _unix_driver_lists_shutdown(); signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); #ifdef SIGQUIT signal(SIGQUIT, old_sig_quit); #endif #ifdef ALLEGRO_MULTITHREADED if (_xwin.mutex) { _unix_destroy_mutex(_xwin.mutex); _xwin.mutex = NULL; } #endif } /* _xwin_sysdrv_set_window_title: * Sets window title. */ static void _xwin_sysdrv_set_window_title(AL_CONST char *name) { char title[128]; do_uconvert(name, U_CURRENT, title, U_ASCII, sizeof(title)); _xwin_set_window_title(title); } /* _xwin_sysdrv_set_close_button_callback: * Sets close button callback function. */ static int _xwin_sysdrv_set_close_button_callback(void (*proc)(void)) { _xwin.close_button_callback = proc; return 0; } /* _xwin_sysdrv_message: * Displays a message. Uses xmessage if possible, and stdout if not. */ static void _xwin_sysdrv_message(AL_CONST char *msg) { char buf[ALLEGRO_MESSAGE_SIZE+1]; char *msg2; size_t len; pid_t pid; int status; /* convert message to ASCII */ msg2 = uconvert(msg, U_CURRENT, buf, U_ASCII, ALLEGRO_MESSAGE_SIZE); /* xmessage interprets some strings beginning with '-' as command-line * options. To avoid this we make sure all strings we pass to it have * newlines on the end. This is also useful for the fputs() case. */ len = strlen(msg2); ASSERT(len < ALLEGRO_MESSAGE_SIZE); if ((len == 0) || (msg2[len-1] != '\n')) strcat(msg2, "\n"); /* fork a child */ pid = fork(); switch (pid) { case -1: /* fork error */ fputs(msg2, stdout); break; case 0: /* child process */ execlp("xmessage", "xmessage", "-buttons", "OK:101", "-default", "OK", "-center", msg2, (char *)NULL); /* if execution reaches here, it means execlp failed */ _exit(EXIT_FAILURE); break; default: /* parent process */ waitpid(pid, &status, 0); if ((!WIFEXITED(status)) || (WEXITSTATUS(status) != 101)) /* ok button */ { fputs(msg2, stdout); } break; } } /* _xwin_sysdrv_gfx_drivers: * Get the list of graphics drivers. */ static _DRIVER_INFO *_xwin_sysdrv_gfx_drivers(void) { return _unix_gfx_driver_list; } /* _xwin_sysdrv_digi_drivers: * Get the list of digital sound drivers. */ static _DRIVER_INFO *_xwin_sysdrv_digi_drivers(void) { return _unix_digi_driver_list; } /* _xwin_sysdrv_midi_drivers: * Get the list of MIDI drivers. */ static _DRIVER_INFO *_xwin_sysdrv_midi_drivers(void) { return _unix_midi_driver_list; } /* _xwin_sysdrv_keyboard_drivers: * Get the list of keyboard drivers. */ static _DRIVER_INFO *_xwin_sysdrv_keyboard_drivers(void) { return _xwin_keyboard_driver_list; } /* _xwin_sysdrv_mouse_drivers: * Get the list of mouse drivers. */ static _DRIVER_INFO *_xwin_sysdrv_mouse_drivers(void) { return _xwin_mouse_driver_list; } #ifdef ALLEGRO_HAVE_LINUX_JOYSTICK_H /* _xwin_sysdrv_joystick_drivers: * Get the list of joystick drivers. */ static _DRIVER_INFO *_xwin_sysdrv_joystick_drivers(void) { return _linux_joystick_driver_list; } #endif /* _xwin_sysdrv_timer_drivers: * Get the list of timer drivers. */ static _DRIVER_INFO *_xwin_sysdrv_timer_drivers(void) { return _xwin_timer_driver_list; } /* _xwin_sysdrv_display_switch_mode: * Tries to set the display switching mode (this is mostly just to * return sensible values to the caller: most of the modes don't * properly apply to X). */ static int _xwin_sysdrv_display_switch_mode(int mode) { if (_xwin.in_dga_mode) { if (mode != SWITCH_NONE) return -1; } if (mode != SWITCH_BACKGROUND) return -1; return 0; } /* _xwin_sysdrv_desktop_color_depth: * Returns the current desktop color depth. */ static int _xwin_sysdrv_desktop_color_depth(void) { if (_xwin.window_depth <= 8) return 8; else if (_xwin.window_depth <= 15) return 15; else if (_xwin.window_depth == 16) return 16; else return 32; } /* _xwin_sysdrv_get_desktop_resolution: * Returns the current desktop resolution. */ static int _xwin_sysdrv_get_desktop_resolution(int *width, int *height) { XLOCK(); *width = DisplayWidth(_xwin.display, _xwin.screen); *height = DisplayHeight(_xwin.display, _xwin.screen); XUNLOCK(); return 0; } /* _xwin_sysdrv_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void _xwin_sysdrv_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_XWINDOWS; mode->width = 320; mode->height = 200; mode->bpp = 8; } allegro-4.4.3.1/src/x/xtimer.c0000664000175000017500000000173513437077643015020 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * X-Windows timer module. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/platform/aintunix.h" /* list the available drivers */ _DRIVER_INFO _xwin_timer_driver_list[] = { #ifdef ALLEGRO_HAVE_LIBPTHREAD { TIMERDRV_UNIX_PTHREADS, &timerdrv_unix_pthreads, TRUE }, #else { TIMERDRV_UNIX_SIGALRM, &timerdrv_unix_sigalrm, TRUE }, #endif { 0, NULL, 0 } }; allegro-4.4.3.1/src/x/xkeyboard.c0000664000175000017500000005337413437077643015506 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * X keyboard driver. * * By Elias Pschernig. * * See readme.txt for copyright information. */ #include #include #include #include #include #include #include #include #include #include "allegro.h" #include "xalleg.h" #include "allegro/internal/aintern.h" #include "xwin.h" #define PREFIX_I "al-xkey INFO: " #define PREFIX_W "al-xkey WARNING: " #define PREFIX_E "al-xkey ERROR: " #ifdef ALLEGRO_XWINDOWS_WITH_XIM static XIM xim = NULL; static XIC xic = NULL; #endif static XModifierKeymap *xmodmap = NULL; static int xkeyboard_installed = 0; static int used[KEY_MAX]; static int sym_per_key; static int min_keycode, max_keycode; static KeySym *keysyms = NULL; static int main_pid; /* The pid to kill with ctrl-alt-del. */ static int pause_key = 0; /* Allegro's special pause key state. */ /* This table can be ammended to provide more reasonable defaults for * mappings other than US/UK. They are used to map X11 KeySyms as found in * X11/keysym.h to Allegro's KEY_* codes. This will only work well on US/UK * keyboards since Allegro simply doesn't have KEY_* codes for non US/UK * keyboards. So with other mappings, the unmapped keys will be distributed * arbitrarily to the remaining KEY_* codes. * * Double mappings should be avoided, else they can lead to different keys * producing the same KEY_* code on some mappings. * * In cases where there is no other way to detect a key, since we have no * ASCII applied to it, like KEY_LEFT or KEY_PAUSE, multiple mappings should * be ok though. This table will never be able to be 100% perfect, so just * try to make it work for as many as possible, using additional hacks in * some cases. There is also still the possibility to override keys with * the [xkeyboard] config section, so users can always re-map keys. (E.g. * to play an Allegro game which hard-coded KEY_Y and KEY_X for left and * right.) */ static struct { KeySym keysym; int allegro_key; } translation_table[] = { {XK_a, KEY_A}, {XK_b, KEY_B}, {XK_c, KEY_C}, {XK_d, KEY_D}, {XK_e, KEY_E}, {XK_f, KEY_F}, {XK_g, KEY_G}, {XK_h, KEY_H}, {XK_i, KEY_I}, {XK_j, KEY_J}, {XK_k, KEY_K}, {XK_l, KEY_L}, {XK_m, KEY_M}, {XK_n, KEY_N}, {XK_o, KEY_O}, {XK_p, KEY_P}, {XK_q, KEY_Q}, {XK_r, KEY_R}, {XK_s, KEY_S}, {XK_t, KEY_T}, {XK_u, KEY_U}, {XK_v, KEY_V}, {XK_w, KEY_W}, {XK_x, KEY_X}, {XK_y, KEY_Y}, {XK_z, KEY_Z}, {XK_0, KEY_0}, {XK_1, KEY_1}, {XK_2, KEY_2}, {XK_3, KEY_3}, {XK_4, KEY_4}, {XK_5, KEY_5}, {XK_6, KEY_6}, {XK_7, KEY_7}, {XK_8, KEY_8}, {XK_9, KEY_9}, /* Double mappings for numeric keyboard. * If an X server actually uses both at the same time, Allegro will * detect them as the same. But normally, an X server just reports it as * either of them, and therefore we always get the keys as KEY_*_PAD. */ {XK_KP_0, KEY_0_PAD}, {XK_KP_Insert, KEY_0_PAD}, {XK_KP_1, KEY_1_PAD}, {XK_KP_End, KEY_1_PAD}, {XK_KP_2, KEY_2_PAD}, {XK_KP_Down, KEY_2_PAD}, {XK_KP_3, KEY_3_PAD}, {XK_KP_Page_Down, KEY_3_PAD}, {XK_KP_4, KEY_4_PAD}, {XK_KP_Left, KEY_4_PAD}, {XK_KP_5, KEY_5_PAD}, {XK_KP_Begin, KEY_5_PAD}, {XK_KP_6, KEY_6_PAD}, {XK_KP_Right, KEY_6_PAD}, {XK_KP_7, KEY_7_PAD}, {XK_KP_Home, KEY_7_PAD}, {XK_KP_8, KEY_8_PAD}, {XK_KP_Up, KEY_8_PAD}, {XK_KP_9, KEY_9_PAD}, {XK_KP_Page_Up, KEY_9_PAD}, {XK_KP_Delete, KEY_DEL_PAD}, {XK_KP_Decimal, KEY_DEL_PAD}, /* Double mapping! * Same as above - but normally, the X server just reports one or the * other for the Pause key, and the other is not reported for any key. */ {XK_Pause, KEY_PAUSE}, {XK_Break, KEY_PAUSE}, {XK_F1, KEY_F1}, {XK_F2, KEY_F2}, {XK_F3, KEY_F3}, {XK_F4, KEY_F4}, {XK_F5, KEY_F5}, {XK_F6, KEY_F6}, {XK_F7, KEY_F7}, {XK_F8, KEY_F8}, {XK_F9, KEY_F9}, {XK_F10, KEY_F10}, {XK_F11, KEY_F11}, {XK_F12, KEY_F12}, {XK_Escape, KEY_ESC}, {XK_grave, KEY_TILDE}, /* US left of 1 */ {XK_minus, KEY_MINUS}, /* US right of 0 */ {XK_equal, KEY_EQUALS}, /* US 2 right of 0 */ {XK_BackSpace, KEY_BACKSPACE}, {XK_Tab, KEY_TAB}, {XK_bracketleft, KEY_OPENBRACE}, /* US right of P */ {XK_bracketright, KEY_CLOSEBRACE}, /* US 2 right of P */ {XK_Return, KEY_ENTER}, {XK_semicolon, KEY_COLON}, /* US right of L */ {XK_apostrophe, KEY_QUOTE}, /* US 2 right of L */ {XK_backslash, KEY_BACKSLASH}, /* US 3 right of L */ {XK_less, KEY_BACKSLASH2}, /* US left of Y */ {XK_comma, KEY_COMMA}, /* US right of M */ {XK_period, KEY_STOP}, /* US 2 right of M */ {XK_slash, KEY_SLASH}, /* US 3 right of M */ {XK_space, KEY_SPACE}, {XK_Insert, KEY_INSERT}, {XK_Delete, KEY_DEL}, {XK_Home, KEY_HOME}, {XK_End, KEY_END}, {XK_Page_Up, KEY_PGUP}, {XK_Page_Down, KEY_PGDN}, {XK_Left, KEY_LEFT}, {XK_Right, KEY_RIGHT}, {XK_Up, KEY_UP}, {XK_Down, KEY_DOWN}, {XK_KP_Divide, KEY_SLASH_PAD}, {XK_KP_Multiply, KEY_ASTERISK}, {XK_KP_Subtract, KEY_MINUS_PAD}, {XK_KP_Add, KEY_PLUS_PAD}, {XK_KP_Enter, KEY_ENTER_PAD}, {XK_Print, KEY_PRTSCR}, //{, KEY_ABNT_C1}, //{, KEY_YEN}, //{, KEY_KANA}, //{, KEY_CONVERT}, //{, KEY_NOCONVERT}, //{, KEY_AT}, //{, KEY_CIRCUMFLEX}, //{, KEY_COLON2}, //{, KEY_KANJI}, {XK_KP_Equal, KEY_EQUALS_PAD}, /* MacOS X */ //{, KEY_BACKQUOTE}, /* MacOS X */ //{, KEY_SEMICOLON}, /* MacOS X */ //{, KEY_COMMAND}, /* MacOS X */ {XK_Shift_L, KEY_LSHIFT}, {XK_Shift_R, KEY_RSHIFT}, {XK_Control_L, KEY_LCONTROL}, {XK_Control_R, KEY_RCONTROL}, {XK_Alt_L, KEY_ALT}, /* Double mappings. This is a bit of a problem, since you can configure * X11 differently to what report for those keys. */ {XK_Alt_R, KEY_ALTGR}, {XK_ISO_Level3_Shift, KEY_ALTGR}, {XK_Meta_L, KEY_LWIN}, {XK_Super_L, KEY_LWIN}, {XK_Meta_R, KEY_RWIN}, {XK_Super_R, KEY_RWIN}, {XK_Menu, KEY_MENU}, {XK_Scroll_Lock, KEY_SCRLOCK}, {XK_Num_Lock, KEY_NUMLOCK}, {XK_Caps_Lock, KEY_CAPSLOCK} }; /* Table of: Allegro's modifier flag, associated X11 flag, toggle method. */ static int modifier_flags[8][3] = { {KB_SHIFT_FLAG, ShiftMask, 0}, {KB_CAPSLOCK_FLAG, LockMask, 1}, {KB_CTRL_FLAG, ControlMask, 0}, {KB_ALT_FLAG, Mod1Mask, 0}, {KB_NUMLOCK_FLAG, Mod2Mask, 1}, {KB_SCROLOCK_FLAG, Mod3Mask, 1}, {KB_LWIN_FLAG | KB_RWIN_FLAG, Mod4Mask, 0}, /* Should we use only one? */ {KB_MENU_FLAG, Mod5Mask, 0} /* AltGr */ }; /* Table of key names. */ static char AL_CONST *key_names[1 + KEY_MAX]; /* update_shifts * Update Allegro's key_shifts variable, directly from the corresponding * X11 modifiers state. */ static void update_shifts(XKeyEvent *event) { int mask = 0; int i; for (i = 0; i < 8; i++) { int j; /* This is the state of the modifiers just before the key * press/release. */ if (event->state & modifier_flags[i][1]) mask |= modifier_flags[i][0]; /* In case a modifier key itself was pressed, we now need to update * the above state for Allegro, which wants the state after the * press, not before as reported by X. */ for (j = 0; j < xmodmap->max_keypermod; j++) { if (event->keycode && event->keycode == xmodmap->modifiermap[i * xmodmap->max_keypermod + j]) { if (event->type == KeyPress) { /* Modifier key pressed - toggle or set flag. */ if (modifier_flags[i][2]) mask ^= modifier_flags[i][0]; else mask |= modifier_flags[i][0]; } else if (event->type == KeyRelease) { /* Modifier key of non-toggle key released - remove flag. */ if (!modifier_flags[i][2]) mask &= ~modifier_flags[i][0]; } } } } _key_shifts = mask; } /* dga2_update_shifts * DGA2 doesn't seem to have a reliable state field. Therefore Allegro must * take care of modifier keys itself. */ static void dga2_update_shifts(XKeyEvent *event) { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < xmodmap->max_keypermod; j++) { if (event->keycode && event->keycode == xmodmap->modifiermap[i * xmodmap->max_keypermod + j]) { if (event->type == KeyPress) { if (modifier_flags[i][2]) _key_shifts ^= modifier_flags[i][0]; else _key_shifts |= modifier_flags[i][0]; } else if (event->type == KeyRelease) { if (!modifier_flags[i][2]) _key_shifts &= ~modifier_flags[i][0]; } } } /* Hack: DGA keys seem to get reported wrong otherwise. */ if (_key_shifts & modifier_flags[i][0]) event->state |= modifier_flags[i][1]; } } /* find_unknown_key_assignment * In some cases, X11 doesn't report any KeySym for a key - so the earliest * time we can map it to an Allegro key is when it is first pressed. */ static int find_unknown_key_assignment (int i) { int j; for (j = 1; j < KEY_MAX; j++) { if (!used[j]) { AL_CONST char *str; _xwin.keycode_to_scancode[i] = j; str = XKeysymToString(keysyms[sym_per_key * (i - min_keycode)]); if (str) key_names[j] = str; else key_names[j] = _keyboard_common_names[j]; used[j] = 1; break; } } if (j == KEY_MAX) { TRACE(PREFIX_E "You have more keys reported by X than Allegro's " "maximum of %i keys. Please send a bug report.\n", KEY_MAX); _xwin.keycode_to_scancode[i] = 0; } TRACE(PREFIX_I "Key %i missing:", i); for (j = 0; j < sym_per_key; j++) { char *sym_str = XKeysymToString(keysyms[sym_per_key * (i - min_keycode) + j]); TRACE(" %s", sym_str ? sym_str : "NULL"); } TRACE(" - assigned to %i.\n", _xwin.keycode_to_scancode[i]); return _xwin.keycode_to_scancode[i]; } /* unicode_getc: * Reads a character from a Unicode string. */ static int unicode_getc(AL_CONST char *s) { return *((unsigned short *)s); } /* _xwin_keyboard_handler: * Keyboard "interrupt" handler. */ void _xwin_keyboard_handler(XKeyEvent *event, int dga2_hack) { int keycode; if (!xkeyboard_installed) return; if (_xwin_keyboard_callback) (*_xwin_keyboard_callback)(event->type == KeyPress ? 1 : 0, event->keycode); keycode = _xwin.keycode_to_scancode[event->keycode]; if (keycode == -1) keycode = find_unknown_key_assignment(event->keycode); if (dga2_hack) dga2_update_shifts(event); else update_shifts(event); /* Special case the pause key. */ if (keycode == KEY_PAUSE) { /* Allegro ignore's releasing of the pause key. */ if (event->type == KeyRelease) return; if (pause_key) { event->type = KeyRelease; pause_key = 0; } else { pause_key = 1; } } if (event->type == KeyPress) { /* Key pressed. */ int len; char buffer[16]; char buffer2[16]; int unicode = 0, r = 0; #if defined (ALLEGRO_XWINDOWS_WITH_XIM) && defined(X_HAVE_UTF8_STRING) if (xic) { len = Xutf8LookupString(xic, event, buffer, sizeof buffer, NULL, NULL); } else #endif { /* XLookupString is supposed to only use ASCII. */ len = XLookupString(event, buffer, sizeof buffer, NULL, NULL); } buffer[len] = '\0'; uconvert(buffer, U_UTF8, buffer2, U_UNICODE, sizeof buffer2); unicode = unicode_getc(buffer2); #ifdef ALLEGRO_XWINDOWS_WITH_XIM r = XFilterEvent((XEvent *)event, _xwin.window); #endif if (keycode || unicode) { /* If we have a keycode, we want it to go to Allegro immediately, so the * key[] array is updated, and the user callbacks are called. OTOH, a key * should not be added to the keyboard buffer (parameter -1) if it was * filtered out as a compose key, or if it is a modifier key. */ if (r || keycode >= KEY_MODIFIERS) unicode = -1; else { /* Historically, Allegro expects to get only the scancode when Alt is * held down. */ if (_key_shifts & KB_ALT_FLAG) unicode = 0; } _handle_key_press(unicode, keycode); /* Detect Ctrl-Alt-End. */ if (keycode == KEY_END && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG) && (three_finger_flag)) { #ifndef ALLEGRO_HAVE_LIBPTHREAD if (_unix_bg_man == &_bg_man_sigalrm) { _sigalrm_request_abort(); } else #endif { TRACE(PREFIX_W "Three finger combo detected. SIGTERMing " "pid %d\n", main_pid); kill(main_pid, SIGTERM); } } } } else { /* Key release. */ _handle_key_release(keycode); } } /* _xwin_keyboard_focus_handler: * Handles switching of X keyboard focus. */ void _xwin_keyboard_focus_handler(XFocusChangeEvent *event) { /* Simulate release of all keys on focus out. */ if (event->type == FocusOut) { int i; for (i = 0; i < KEY_MAX; i++) { if (key[i]) _handle_key_release(i); } } } /* find_allegro_key * Search the translation table for the Allegro key corresponding to the * given KeySym. */ static int find_allegro_key(KeySym sym) { int i; int n = sizeof translation_table / sizeof *translation_table; for (i = 0; i < n; i++) { if (translation_table[i].keysym == sym) return translation_table[i].allegro_key; } return 0; } /* scancode_to_name: * Converts the given scancode to a description of the key. */ static AL_CONST char *x_scancode_to_name(int scancode) { ASSERT(scancode >= 0 && scancode < KEY_MAX); return key_names[scancode]; } /* x_get_keyboard_mapping: * Generate a mapping from X11 keycodes to Allegro KEY_* codes. We have * two goals: Every keypress should be mapped to a distinct Allegro KEY_* * code. And we want the KEY_* codes to match the pressed * key to some extent. To do the latter, the X11 KeySyms produced by a key * are examined. If a match is found in the table above, the mapping is * added to the mapping table. If no known KeySym is found for a key (or * the same KeySym is found for more keys) - the remaining keys are * distributed arbitrarily to the remaining KEY_* codes. * * In a future version, this could be simplified by mapping *all* the X11 * KeySyms to KEY_* codes. */ void _xwin_get_keyboard_mapping(void) { int i; int count; int missing = 0; memset(used, 0, sizeof used); memset(_xwin.keycode_to_scancode, 0, sizeof _xwin.keycode_to_scancode); XLOCK(); XDisplayKeycodes(_xwin.display, &min_keycode, &max_keycode); count = 1 + max_keycode - min_keycode; if (keysyms) { XFree(keysyms); } keysyms = XGetKeyboardMapping(_xwin.display, min_keycode, count, &sym_per_key); TRACE (PREFIX_I "%i keys, %i symbols per key.\n", count, sym_per_key); missing = 0; for (i = min_keycode; i <= max_keycode; i++) { KeySym sym = keysyms[sym_per_key * (i - min_keycode)]; KeySym sym2 = keysyms[sym_per_key * (i - min_keycode) + 1]; char *sym_str, *sym2_str; int allegro_key = 0; sym_str = XKeysymToString(sym); sym2_str = XKeysymToString(sym2); TRACE (PREFIX_I "key [%i: %s %s]", i, sym_str ? sym_str : "NULL", sym2_str ? sym2_str : "NULL"); /* Hack for French keyboards, to correctly map KEY_0 to KEY_9. */ if (sym2 >= XK_0 && sym2 <= XK_9) { allegro_key = find_allegro_key(sym2); } if (!allegro_key) { if (sym != NoSymbol) { allegro_key = find_allegro_key(sym); if (allegro_key == 0) { missing++; TRACE (" defering.\n"); } } else { /* No KeySym for this key - ignore it. */ _xwin.keycode_to_scancode[i] = -1; TRACE (" not assigned.\n"); } } if (allegro_key) { if (used[allegro_key]) { TRACE(" *double*"); } _xwin.keycode_to_scancode[i] = allegro_key; key_names[allegro_key] = XKeysymToString(keysyms[sym_per_key * (i - min_keycode)]); used[allegro_key] = 1; TRACE(" assigned to %i.\n", allegro_key); } } if (missing) { /* The keys still not assigned are just assigned arbitrarily now. */ for (i = min_keycode; i <= max_keycode; i++) { if (_xwin.keycode_to_scancode[i] == 0) { find_unknown_key_assignment(i); } } } if (xmodmap) XFreeModifiermap(xmodmap); xmodmap = XGetModifierMapping(_xwin.display); for (i = 0; i < 8; i++) { int j; TRACE (PREFIX_I "Modifier %d:", i + 1); for (j = 0; j < xmodmap->max_keypermod; j++) { KeySym sym = XKeycodeToKeysym(_xwin.display, xmodmap->modifiermap[i * xmodmap->max_keypermod + j], 0); char *sym_str = XKeysymToString(sym); TRACE(" %s", sym_str ? sym_str : "NULL"); } TRACE("\n"); } /* The [xkeymap] section can be useful, e.g. if trying to play a * game which has X and Y hardcoded as KEY_X and KEY_Y to mean * left/right movement, but on the X11 keyboard X and Y are far apart. * For normal use, a user never should have to touch [xkeymap] anymore * though, and proper written programs will not hardcode such mappings. */ { char *section, *option_format; char option[128], tmp1[128], tmp2[128]; section = uconvert_ascii("xkeymap", tmp1); option_format = uconvert_ascii("keycode%d", tmp2); for (i = min_keycode; i <= max_keycode; i++) { int scancode; uszprintf(option, sizeof(option), option_format, i); scancode = get_config_int(section, option, -1); if (scancode > 0) { _xwin.keycode_to_scancode[i] = scancode; TRACE(PREFIX_I "User override: KeySym %i assigned to %i.\n", i, scancode); } } } XUNLOCK(); } /* x_set_leds: * Update the keyboard LEDs. */ static void x_set_leds(int leds) { XKeyboardControl values; if (!xkeyboard_installed) return; XLOCK(); values.led = 1; values.led_mode = leds & KB_NUMLOCK_FLAG ? LedModeOn : LedModeOff; XChangeKeyboardControl(_xwin.display, KBLed | KBLedMode, &values); values.led = 2; values.led_mode = leds & KB_CAPSLOCK_FLAG ? LedModeOn : LedModeOff; XChangeKeyboardControl(_xwin.display, KBLed | KBLedMode, &values); values.led = 3; values.led_mode = leds & KB_SCROLOCK_FLAG ? LedModeOn : LedModeOff; XChangeKeyboardControl(_xwin.display, KBLed | KBLedMode, &values); XUNLOCK(); } /* x_keyboard_init * Initialise the X11 keyboard driver. */ static int x_keyboard_init(void) { #ifdef ALLEGRO_XWINDOWS_WITH_XIM XIMStyles *xim_styles; XIMStyle xim_style = 0; char *imvalret; int i; #endif if (xkeyboard_installed) return 0; main_pid = getpid(); memcpy(key_names, _keyboard_common_names, sizeof key_names); XLOCK (); #ifdef ALLEGRO_XWINDOWS_WITH_XIM /* Otherwise we are restricted to ISO-8859-1 characters. */ if (setlocale(LC_ALL, "") == NULL) { TRACE(PREFIX_W "Could not set default locale.\n"); } /* TODO: is this needed? modifiers = XSetLocaleModifiers("@im=none"); if (modifiers == NULL) { TRACE(PREFIX_W "XSetLocaleModifiers failed.\n"); } */ xim = XOpenIM(_xwin.display, NULL, NULL, NULL); if (xim == NULL) { TRACE(PREFIX_W "XOpenIM failed.\n"); } if (xim) { imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); if (imvalret != NULL || xim_styles == NULL) { TRACE(PREFIX_W "Input method doesn't support any styles.\n"); } if (xim_styles) { xim_style = 0; for (i = 0; i < xim_styles->count_styles; i++) { if (xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) { xim_style = xim_styles->supported_styles[i]; break; } } if (xim_style == 0) { TRACE (PREFIX_W "Input method doesn't support the style we support.\n"); } XFree(xim_styles); } } if (xim && xim_style) { xic = XCreateIC(xim, XNInputStyle, xim_style, XNClientWindow, _xwin.window, XNFocusWindow, _xwin.window, NULL); if (xic == NULL) { TRACE (PREFIX_W "XCreateIC failed.\n"); } } #endif _xwin_get_keyboard_mapping(); XUNLOCK(); xkeyboard_installed = 1; return 0; } /* x_keyboard_exit * Shut down the X11 keyboard driver. */ static void x_keyboard_exit(void) { if (!xkeyboard_installed) return; xkeyboard_installed = 0; XLOCK(); #ifdef ALLEGRO_XWINDOWS_WITH_XIM if (xic) { XDestroyIC(xic); xic = NULL; } if (xim) { XCloseIM(xim); xim = NULL; } #endif if (xmodmap) { XFreeModifiermap(xmodmap); xmodmap = NULL; } if (keysyms) { XFree(keysyms); keysyms = NULL; } XUNLOCK(); } static KEYBOARD_DRIVER keyboard_x = { KEYBOARD_XWINDOWS, "X11 keyboard", "X11 keyboard", "X11 keyboard", FALSE, x_keyboard_init, x_keyboard_exit, NULL, // AL_METHOD(void, poll, (void)); x_set_leds, NULL, // AL_METHOD(void, set_rate, (int delay, int rate)); NULL, // AL_METHOD(void, wait_for_input, (void)); NULL, // AL_METHOD(void, stop_waiting_for_input, (void)); NULL, // AL_METHOD(int, scancode_to_ascii, (int scancode)); x_scancode_to_name }; /* list the available drivers */ _DRIVER_INFO _xwin_keyboard_driver_list[] = { { KEYBOARD_XWINDOWS, &keyboard_x, TRUE }, { 0, NULL, 0 } }; allegro-4.4.3.1/src/x/xvtable.c0000664000175000017500000005545213437077643015162 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Magical wrappers for functions in vtable. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "xwin.h" #ifdef ALLEGRO_MULTITHREADED #include #endif static GFX_VTABLE _xwin_vtable; static void _xwin_putpixel(BITMAP *dst, int dx, int dy, int color); static void _xwin_vline(BITMAP *dst, int dx, int dy1, int dy2, int color); static void _xwin_hline(BITMAP *dst, int dx1, int dy, int dx2, int color); static void _xwin_rectfill(BITMAP *dst, int dx1, int dy1, int dx2, int dy2, int color); static void _xwin_draw_sprite(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_sprite_ex(BITMAP *dst, BITMAP *src, int dx, int dy, int mode, int flip); static void _xwin_draw_256_sprite(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_sprite_v_flip(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_sprite_h_flip(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_sprite_vh_flip(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_trans_sprite(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_trans_rgba_sprite(BITMAP *dst, BITMAP *src, int dx, int dy); static void _xwin_draw_lit_sprite(BITMAP *dst, BITMAP *src, int dx, int dy, int color); static void _xwin_draw_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy); static void _xwin_draw_trans_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy); static void _xwin_draw_trans_rgba_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy); static void _xwin_draw_lit_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy, int color); static void _xwin_draw_character(BITMAP *dst, BITMAP *src, int dx, int dy, int color, int bg); static void _xwin_draw_glyph(BITMAP *dst, AL_CONST FONT_GLYPH *src, int dx, int dy, int color, int bg); static void _xwin_blit_anywhere(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h); static void _xwin_blit_backward(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h); static void _xwin_masked_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h); static void _xwin_clear_to_color(BITMAP *dst, int color); /* _xwin_drawing_mode: * Set the GC's drawing mode */ void _xwin_drawing_mode(void) { /* Only SOLID can be handled directly by X11. */ if(_xwin.matching_formats && _drawing_mode == DRAW_MODE_SOLID) _xwin.drawing_mode_ok = TRUE; else _xwin.drawing_mode_ok = FALSE; } /* Direct X11 version of the function. */ static inline int _xwin_direct_putpixel(BITMAP *dst, int dx, int dy, int color) { if (!_xwin.drawing_mode_ok) return 0; dx += dst->x_ofs - _xwin.scroll_x; dy += dst->y_ofs - _xwin.scroll_y; if((dx >= _xwin.screen_width) || (dx < 0) || (dy >= _xwin.screen_height) || (dy < 0)) return 1; XLOCK(); XSetForeground(_xwin.display, _xwin.gc, color); XDrawPoint(_xwin.display, _xwin.window, _xwin.gc, dx, dy); XUNLOCK(); return 1; } /* Direct X11 version of the function. */ static inline int _xwin_direct_hline(BITMAP *dst, int dx1, int dy, int dx2, int color) { if (!_xwin.drawing_mode_ok) return 0; dx1 += dst->x_ofs - _xwin.scroll_x; dx2 += dst->x_ofs - _xwin.scroll_x; dy += dst->y_ofs - _xwin.scroll_y; if (dx1 < 0) dx1 = 0; if (dx2 >= _xwin.screen_width) dx2 = _xwin.screen_width - 1; if ((dx1 > dx2) || (dy < 0) || (dy >= _xwin.screen_height)) return 1; XLOCK(); XSetForeground(_xwin.display, _xwin.gc, color); XDrawLine(_xwin.display, _xwin.window, _xwin.gc, dx1, dy, dx2, dy); XUNLOCK(); return 1; } /* Direct X11 version of the function. */ static inline int _xwin_direct_vline(BITMAP *dst, int dx, int dy1, int dy2, int color) { if (!_xwin.drawing_mode_ok) return 0; dx += dst->x_ofs - _xwin.scroll_x; dy1 += dst->y_ofs - _xwin.scroll_y; dy2 += dst->y_ofs - _xwin.scroll_y; if (dy1 < 0) dy1 = 0; if (dy2 >= _xwin.screen_height) dy2 = _xwin.screen_height - 1; if ((dy1 > dy2) || (dx < 0) || (dx >= _xwin.screen_width)) return 1; XLOCK(); XSetForeground(_xwin.display, _xwin.gc, color); XDrawLine(_xwin.display, _xwin.window, _xwin.gc, dx, dy1, dx, dy2); XUNLOCK(); return 1; } /* Direct X11 version of the function. */ static inline int _xwin_direct_rectfill(BITMAP *dst, int dx1, int dy1, int dx2, int dy2, int color) { if (!_xwin.drawing_mode_ok) return 0; dx1 += dst->x_ofs - _xwin.scroll_x; dx2 += dst->x_ofs - _xwin.scroll_x; dy1 += dst->y_ofs - _xwin.scroll_y; dy2 += dst->y_ofs - _xwin.scroll_y; if (dx1 < 0) dx1 = 0; if (dx2 >= _xwin.screen_width) dx2 = _xwin.screen_width - 1; if (dx1 > dx2) return 1; if (dy1 < 0) dy1 = 0; if (dy2 >= _xwin.screen_height) dy2 = _xwin.screen_height - 1; if (dy1 > dy2) return 1; XLOCK(); XSetForeground(_xwin.display, _xwin.gc, color); XFillRectangle(_xwin.display, _xwin.window, _xwin.gc, dx1, dy1, dx2-dx1+1, dy2-dy1+1); XUNLOCK(); return 1; } /* Direct X11 version of the function. */ static inline int _xwin_direct_clear_to_color(BITMAP *dst, int color) { int dx1, dy1, dx2, dy2; if (!_xwin.drawing_mode_ok) return 0; dx1 = dst->cl + dst->x_ofs - _xwin.scroll_x; dx2 = dst->cr + dst->x_ofs - 1 - _xwin.scroll_x; dy1 = dst->ct + dst->y_ofs - _xwin.scroll_y; dy2 = dst->cb + dst->y_ofs - 1 - _xwin.scroll_y; if (dx1 < 0) dx1 = 0; if (dx2 >= _xwin.screen_width) dx2 = _xwin.screen_width - 1; if (dx1 > dx2) return 1; if (dy1 < 0) dy1 = 0; if (dy2 >= _xwin.screen_height) dy2 = _xwin.screen_height - 1; if (dy1 > dy2) return 1; XLOCK(); XSetForeground(_xwin.display, _xwin.gc, color); XFillRectangle(_xwin.display, _xwin.window, _xwin.gc, dx1, dy1, dx2-dx1+1, dy2-dy1+1); XUNLOCK(); return 1; } /* _xwin_replace_vtable: * Replace entries in vtable with magical wrappers. */ void _xwin_replace_vtable(struct GFX_VTABLE *vtable) { memcpy(&_xwin_vtable, vtable, sizeof(GFX_VTABLE)); vtable->acquire = _xwin_lock; vtable->release = _xwin_unlock; vtable->putpixel = _xwin_putpixel; vtable->vline = _xwin_vline; vtable->hline = _xwin_hline; vtable->hfill = _xwin_hline; vtable->rectfill = _xwin_rectfill; vtable->draw_sprite = _xwin_draw_sprite; vtable->draw_sprite_ex = _xwin_draw_sprite_ex; vtable->draw_256_sprite = _xwin_draw_256_sprite; vtable->draw_sprite_v_flip = _xwin_draw_sprite_v_flip; vtable->draw_sprite_h_flip = _xwin_draw_sprite_h_flip; vtable->draw_sprite_vh_flip = _xwin_draw_sprite_vh_flip; vtable->draw_trans_sprite = _xwin_draw_trans_sprite; vtable->draw_trans_rgba_sprite = _xwin_draw_trans_rgba_sprite; vtable->draw_lit_sprite = _xwin_draw_lit_sprite; vtable->draw_rle_sprite = _xwin_draw_rle_sprite; vtable->draw_trans_rle_sprite = _xwin_draw_trans_rle_sprite; vtable->draw_trans_rgba_rle_sprite = _xwin_draw_trans_rgba_rle_sprite; vtable->draw_lit_rle_sprite = _xwin_draw_lit_rle_sprite; vtable->draw_character = _xwin_draw_character; vtable->draw_glyph = _xwin_draw_glyph; vtable->blit_from_memory = _xwin_blit_anywhere; vtable->blit_from_system = _xwin_blit_anywhere; vtable->blit_to_self = _xwin_blit_anywhere; vtable->blit_to_self_forward = _xwin_blit_anywhere; vtable->blit_to_self_backward = _xwin_blit_backward; vtable->masked_blit = _xwin_masked_blit; vtable->clear_to_color = _xwin_clear_to_color; } /* _xwin_lock: * Lock X for drawing onto the display. */ void _xwin_lock(BITMAP *bmp) { XLOCK (); } /* _xwin_lock: * Unlock X after drawing. This will only truely call XUNLOCK when the * unlock count reaches 0. */ void _xwin_unlock(BITMAP *bmp) { XUNLOCK(); } /* _xwin_update_video_bitmap: * Update screen with correct offset for sub-bitmap. */ static void _xwin_update_video_bitmap(BITMAP *dst, int x, int y, int w, int h) { _xwin_update_screen(x + dst->x_ofs, y + dst->y_ofs, w, h); } /* _xwin_putpixel: * Wrapper for putpixel. */ static void _xwin_putpixel(BITMAP *dst, int dx, int dy, int color) { if (_xwin_in_gfx_call) { _xwin_vtable.putpixel(dst, dx, dy, color); return; } if (dst->clip && ((dx < dst->cl) || (dx >= dst->cr) || (dy < dst->ct) || (dy >= dst->cb))) return; _xwin_in_gfx_call = 1; _xwin_vtable.putpixel(dst, dx, dy, color); _xwin_in_gfx_call = 0; if (_xwin_direct_putpixel(dst, dx, dy, color)) return; _xwin_update_video_bitmap(dst, dx, dy, 1, 1); } /* _xwin_hline: * Wrapper for hline. */ static void _xwin_hline(BITMAP *dst, int dx1, int dy, int dx2, int color) { if (_xwin_in_gfx_call) { _xwin_vtable.hline(dst, dx1, dy, dx2, color); return; } if (dx1 > dx2) { int tmp = dx1; dx1 = dx2; dx2 = tmp; } if (dst->clip) { if (dx1 < dst->cl) dx1 = dst->cl; if (dx2 >= dst->cr) dx2 = dst->cr - 1; if ((dx1 > dx2) || (dy < dst->ct) || (dy >= dst->cb)) return; } _xwin_in_gfx_call = 1; _xwin_vtable.hline(dst, dx1, dy, dx2, color); _xwin_in_gfx_call = 0; if (_xwin_direct_hline(dst, dx1, dy, dx2, color)) return; _xwin_update_video_bitmap(dst, dx1, dy, dx2 - dx1 + 1, 1); } /* _xwin_vline: * Wrapper for vline. */ static void _xwin_vline(BITMAP *dst, int dx, int dy1, int dy2, int color) { if (_xwin_in_gfx_call) { _xwin_vtable.vline(dst, dx, dy1, dy2, color); return; } if (dy1 > dy2) { int tmp = dy1; dy1 = dy2; dy2 = tmp; } if (dst->clip) { if (dy1 < dst->ct) dy1 = dst->ct; if (dy2 >= dst->cb) dy2 = dst->cb - 1; if ((dx < dst->cl) || (dx >= dst->cr) || (dy1 > dy2)) return; } _xwin_in_gfx_call = 1; _xwin_vtable.vline(dst, dx, dy1, dy2, color); _xwin_in_gfx_call = 0; if (_xwin_direct_vline(dst, dx, dy1, dy2, color)) return; _xwin_update_video_bitmap(dst, dx, dy1, 1, dy2 - dy1 + 1); } /* _xwin_rectfill: * Wrapper for rectfill. */ static void _xwin_rectfill(BITMAP *dst, int dx1, int dy1, int dx2, int dy2, int color) { if (_xwin_in_gfx_call) { _xwin_vtable.rectfill(dst, dx1, dy1, dx2, dy2, color); return; } if (dy1 > dy2) { int tmp = dy1; dy1 = dy2; dy2 = tmp; } if (dx1 > dx2) { int tmp = dx1; dx1 = dx2; dx2 = tmp; } if (dst->clip) { if (dx1 < dst->cl) dx1 = dst->cl; if (dx2 >= dst->cr) dx2 = dst->cr - 1; if (dx1 > dx2) return; if (dy1 < dst->ct) dy1 = dst->ct; if (dy2 >= dst->cb) dy2 = dst->cb - 1; if (dy1 > dy2) return; } _xwin_in_gfx_call = 1; _xwin_vtable.rectfill(dst, dx1, dy1, dx2, dy2, color); _xwin_in_gfx_call = 0; if (_xwin_direct_rectfill(dst, dx1, dy1, dx2, dy2, color)) return; _xwin_update_video_bitmap(dst, dx1, dy1, dx2 - dx1 + 1, dy2 - dy1 + 1); } /* _xwin_clear_to_color: * Wrapper for clear_to_color. */ static void _xwin_clear_to_color(BITMAP *dst, int color) { if (_xwin_in_gfx_call) { _xwin_vtable.clear_to_color(dst, color); return; } _xwin_in_gfx_call = 1; _xwin_vtable.clear_to_color(dst, color); _xwin_in_gfx_call = 0; if (_xwin_direct_clear_to_color(dst, color)) return; _xwin_update_video_bitmap(dst, dst->cl, dst->ct, dst->cr - dst->cl, dst->cb - dst->ct); } /* _xwin_blit_anywhere: * Wrapper for blit. */ static void _xwin_blit_anywhere(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h) { if (_xwin_in_gfx_call) { _xwin_vtable.blit_from_memory(src, dst, sx, sy, dx, dy, w, h); return; } _xwin_in_gfx_call = 1; _xwin_vtable.blit_from_memory(src, dst, sx, sy, dx, dy, w, h); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dx, dy, w, h); } /* _xwin_blit_backward: * Wrapper for blit_backward. */ static void _xwin_blit_backward(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h) { if (_xwin_in_gfx_call) { _xwin_vtable.blit_to_self_backward(src, dst, sx, sy, dx, dy, w, h); return; } _xwin_in_gfx_call = 1; _xwin_vtable.blit_to_self_backward(src, dst, sx, sy, dx, dy, w, h); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dx, dy, w, h); } /* _xwin_masked_blit: * Wrapper for masked_blit. */ static void _xwin_masked_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h) { if (_xwin_in_gfx_call) { _xwin_vtable.masked_blit(src, dst, sx, sy, dx, dy, w, h); return; } _xwin_in_gfx_call = 1; _xwin_vtable.masked_blit(src, dst, sx, sy, dx, dy, w, h); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dx, dy, w, h); } #define CLIP_BOX(dst, x, y, w, h, x_orig, y_orig, w_orig, h_orig) \ { \ if (dst->clip) { \ int tmp, x_delta, y_delta; \ \ tmp = dst->cl - x_orig; \ x_delta = ((tmp < 0) ? 0 : tmp); \ x = x_orig + x_delta; \ \ tmp = dst->cr - x_orig; \ w = ((tmp > w_orig) ? w_orig : tmp) - x_delta; \ if (w <= 0) \ return; \ \ tmp = dst->ct - y_orig; \ y_delta = ((tmp < 0) ? 0 : tmp); \ y = y_orig + y_delta; \ \ tmp = dst->cb - y_orig; \ h = ((tmp > h_orig) ? h_orig : tmp) - y_delta; \ if (h <= 0) \ return; \ } \ else { \ x = x_orig; \ y = y_orig; \ w = w_orig; \ h = h_orig; \ } \ } /* _xwin_draw_sprite: * Wrapper for draw_sprite. */ static void _xwin_draw_sprite(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_sprite_ex: * Wrapper for draw_sprite_ex. */ static void _xwin_draw_sprite_ex(BITMAP *dst, BITMAP *src, int dx, int dy, int mode, int flip) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_sprite_ex(dst, src, dx, dy, mode, flip); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_sprite_ex(dst, src, dx, dy, mode, flip); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_256_sprite: * Wrapper for draw_256_sprite. */ static void _xwin_draw_256_sprite(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_256_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_256_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_sprite_v_flip: * Wrapper for draw_sprite_v_flip. */ static void _xwin_draw_sprite_v_flip(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_sprite_v_flip(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_sprite_v_flip(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_sprite_h_flip: * Wrapper for draw_sprite_h_flip. */ static void _xwin_draw_sprite_h_flip(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_sprite_h_flip(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_sprite_h_flip(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_sprite_vh_flip: * Wrapper for draw_sprite_vh_flip. */ static void _xwin_draw_sprite_vh_flip(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_sprite_vh_flip(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_sprite_vh_flip(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_trans_sprite: * Wrapper for draw_trans_sprite. */ static void _xwin_draw_trans_sprite(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_trans_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_trans_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_trans_rgba_sprite: * Wrapper for draw_trans_rgba_sprite. */ static void _xwin_draw_trans_rgba_sprite(BITMAP *dst, BITMAP *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_trans_rgba_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_trans_rgba_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_lit_sprite: * Wrapper for draw_lit_sprite. */ static void _xwin_draw_lit_sprite(BITMAP *dst, BITMAP *src, int dx, int dy, int color) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_lit_sprite(dst, src, dx, dy, color); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_lit_sprite(dst, src, dx, dy, color); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_character: * Wrapper for draw_character. */ static void _xwin_draw_character(BITMAP *dst, BITMAP *src, int dx, int dy, int color, int bg) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_character(dst, src, dx, dy, color, bg); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_character(dst, src, dx, dy, color, bg); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_glyph: * Wrapper for draw_glyph. */ static void _xwin_draw_glyph(BITMAP *dst, AL_CONST FONT_GLYPH *src, int dx, int dy, int color, int bg) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_glyph(dst, src, dx, dy, color, bg); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_glyph(dst, src, dx, dy, color, bg); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_rle_sprite: * Wrapper for draw_rle_sprite. */ static void _xwin_draw_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_rle_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_rle_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_trans_rle_sprite: * Wrapper for draw_trans_rle_sprite. */ static void _xwin_draw_trans_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_trans_rle_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_trans_rle_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_trans_rgba_rle_sprite: * Wrapper for draw_trans_rgba_rle_sprite. */ static void _xwin_draw_trans_rgba_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_trans_rgba_rle_sprite(dst, src, dx, dy); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_trans_rgba_rle_sprite(dst, src, dx, dy); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } /* _xwin_draw_lit_rle_sprite: * Wrapper for draw_lit_rle_sprite. */ static void _xwin_draw_lit_rle_sprite(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy, int color) { int dxbeg, dybeg, w, h; if (_xwin_in_gfx_call) { _xwin_vtable.draw_lit_rle_sprite(dst, src, dx, dy, color); return; } CLIP_BOX(dst, dxbeg, dybeg, w, h, dx, dy, src->w, src->h) _xwin_in_gfx_call = 1; _xwin_vtable.draw_lit_rle_sprite(dst, src, dx, dy, color); _xwin_in_gfx_call = 0; _xwin_update_video_bitmap(dst, dxbeg, dybeg, w, h); } allegro-4.4.3.1/src/x/icon.xpm0000664000175000017500000000511313437077643015014 0ustar siegesiege/* XPM */ static char *icon_xpm[] = { "48 48 6 1", " c None", ". c #080808", "+ c #FCFCFC", "@ c #486028", "# c #587834", "$ c #A4C47C", " .... .... ", " .... .... ", " .++++.. .++++.. ", " .++++.. .++++.. ", " ...... ...++.......++... ", " ...... ...++.......++... ", "..@@####............@@###....##@.. ", "..@@####............@@###....##@.. ", "..###########################..#@@.. ", "..###########################..#@@.. ", ".............................#####.. ", ".............................#####.. ", " ...#########@@.. ", " ......#####..#######.. ", " ......#####..#######.. ", " .....######.....$$#######.. ", " .....######.....$$#######.. ", " .....#####...... ..$$#######.. ", " .....#####...... ..$$#######.. ", " ..#####..... .$$##..###@@.. ", " ..#####..... .$$##..###@@.. ", " ..... .......###@@.. ", " ..... .......###@@.. ", " ..#########.@@.. ", " ..##.......@##.. ", " ..##.......@##.. ", " ...$$$$#####.. ", " ...$$$$#####.. ", " .$$$$#####.. .. ", " .$$$$#####.. .. ", " .$$$$#####.. ..@@.", " .$$$$#####.. ..@@.", " .$$..#####@@.. ..@@.", " .$$..#####@@.. ..@@.", " ..####@..##.. ..##@@.", " ..####@..##.. ..##@@.", " ..####@..####...##@@$$.", " .####@@.$$#######@@$$.. ", " .####@@.$$#######@@$$.. ", " .##@@.....$$$$$$$$$.. ", " .##@@.....$$$$$$$$$.. ", " ..##@@............ ", " ..##@@............ ", " ...######.@@.. ", " ...######.@@.. ", " ..#####@@###..@@.. ", " ..#####@@###..@@.. ", " .................. "}; allegro-4.4.3.1/src/x/xmouse.c0000664000175000017500000001730313437077643015026 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * X-Windows mouse module. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "xwin.h" #include /* TRUE if the requested mouse range extends beyond the regular * (0, 0, SCREEN_W-1, SCREEN_H-1) range. This is aimed at detecting * whether the user mouse coordinates are relative to the 'screen' * bitmap (semantics associated with scrolling) or to the video page * currently being displayed (semantics associated with page flipping). * We cannot differentiate them properly because both use the same * scroll_screen() method. */ int _xwin_mouse_extended_range = FALSE; static int mouse_minx = 0; static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int mymickey_x = 0; static int mymickey_y = 0; static int mouse_mult = -1; /* mouse acceleration multiplier */ static int mouse_div = -1; /* mouse acceleration divisor */ static int mouse_threshold = -1; /* mouse acceleration threshold */ static int last_xspeed = -1; /* latest set_mouse_speed() settings */ static int last_yspeed = -1; static int _xwin_mousedrv_init(void); static void _xwin_mousedrv_exit(void); static void _xwin_mousedrv_position(int x, int y); static void _xwin_mousedrv_set_range(int x1, int y1, int x2, int y2); static void _xwin_mousedrv_set_speed(int xspeed, int yspeed); static void _xwin_mousedrv_get_mickeys(int *mickeyx, int *mickeyy); static int _xwin_select_system_cursor(AL_CONST int cursor); static void _xwin_set_mouse_speed(int xspeed, int yspeed); static MOUSE_DRIVER mouse_xwin = { MOUSE_XWINDOWS, empty_string, empty_string, "X-Windows mouse", _xwin_mousedrv_init, _xwin_mousedrv_exit, NULL, NULL, _xwin_mousedrv_position, _xwin_mousedrv_set_range, _xwin_mousedrv_set_speed, _xwin_mousedrv_get_mickeys, NULL, _xwin_enable_hardware_cursor, _xwin_select_system_cursor }; /* list the available drivers */ _DRIVER_INFO _xwin_mouse_driver_list[] = { { MOUSE_XWINDOWS, &mouse_xwin, TRUE }, { 0, NULL, 0 } }; /* _xwin_mousedrv_handler: * Mouse "interrupt" handler for mickey-mode driver. */ static void _xwin_mousedrv_handler(int x, int y, int z, int w, int buttons) { _mouse_b = buttons; mymickey_x += x; mymickey_y += y; _mouse_x += x; _mouse_y += y; _mouse_z += z; _mouse_w += w; if ((_mouse_x < mouse_minx) || (_mouse_x > mouse_maxx) || (_mouse_y < mouse_miny) || (_mouse_y > mouse_maxy)) { _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); } _handle_mouse_input(); } /* _xwin_mousedrv_init: * Initializes the mickey-mode driver. */ static int _xwin_mousedrv_init(void) { int num_buttons; unsigned char map[8]; num_buttons = _xwin_get_pointer_mapping(map, sizeof(map)); num_buttons = CLAMP(2, num_buttons, 3); last_xspeed = -1; last_yspeed = -1; XLOCK(); _xwin_mouse_interrupt = _xwin_mousedrv_handler; XUNLOCK(); return num_buttons; } /* _xwin_mousedrv_exit: * Shuts down the mickey-mode driver. */ static void _xwin_mousedrv_exit(void) { XLOCK(); if (mouse_mult >= 0) XChangePointerControl(_xwin.display, 1, 1, mouse_mult, mouse_div, mouse_threshold); _xwin_mouse_interrupt = 0; XUNLOCK(); } /* _xwin_mousedrv_position: * Sets the position of the mickey-mode mouse. */ static void _xwin_mousedrv_position(int x, int y) { XLOCK(); _mouse_x = x; _mouse_y = y; mymickey_x = mymickey_y = 0; if (_xwin.hw_cursor_ok) XWarpPointer(_xwin.display, _xwin.window, _xwin.window, 0, 0, _xwin.window_width, _xwin.window_height, x, y); XUNLOCK(); _xwin_set_warped_mouse_mode(FALSE); } /* _xwin_mousedrv_set_range: * Sets the range of the mickey-mode mouse. */ static void _xwin_mousedrv_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; if ((mouse_maxx >= SCREEN_W) || (mouse_maxy >= SCREEN_H)) _xwin_mouse_extended_range = TRUE; else _xwin_mouse_extended_range = FALSE; XLOCK(); _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); XUNLOCK(); } /* _xwin_mousedrv_set_speed: * Sets the speed of the mouse cursor. We don't set the speed if the cursor * isn't in the window, but we remember the setting so it will be set the * next time the cursor enters the window. */ static void _xwin_mousedrv_set_speed(int xspeed, int yspeed) { if (_mouse_on) { _xwin_set_mouse_speed(xspeed, yspeed); } last_xspeed = xspeed; last_yspeed = yspeed; } /* _xwin_mousedrv_get_mickeys: * Reads the mickey-mode count. */ static void _xwin_mousedrv_get_mickeys(int *mickeyx, int *mickeyy) { int temp_x = mymickey_x; int temp_y = mymickey_y; mymickey_x -= temp_x; mymickey_y -= temp_y; *mickeyx = temp_x; *mickeyy = temp_y; _xwin_set_warped_mouse_mode(TRUE); } /* _xwin_select_system_cursor: * Select an OS native cursor */ static int _xwin_select_system_cursor(AL_CONST int cursor) { switch(cursor) { case MOUSE_CURSOR_ARROW: _xwin.cursor_shape = XC_left_ptr; break; case MOUSE_CURSOR_BUSY: _xwin.cursor_shape = XC_watch; break; case MOUSE_CURSOR_QUESTION: _xwin.cursor_shape = XC_question_arrow; break; case MOUSE_CURSOR_EDIT: _xwin.cursor_shape = XC_xterm; break; default: return 0; } XLOCK(); if (_xwin.cursor != None) { XUndefineCursor(_xwin.display, _xwin.window); XFreeCursor(_xwin.display, _xwin.cursor); } _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); XUNLOCK(); return cursor; } /* _xwin_set_mouse_speed: * The actual function that sets the speed of the mouse cursor. * Each step slows down or speeds the mouse up by 0.5x. */ static void _xwin_set_mouse_speed(int xspeed, int yspeed) { int speed; int hundredths; XLOCK(); if (mouse_mult < 0) XGetPointerControl(_xwin.display, &mouse_mult, &mouse_div, &mouse_threshold); speed = MAX(1, (xspeed + yspeed) / 2); if (mouse_div == 0) hundredths = mouse_mult * 100; else hundredths = (mouse_mult * 100 / mouse_div); hundredths -= (speed - 2) * 50; if (hundredths < 0) hundredths = 0; XChangePointerControl(_xwin.display, 1, 1, hundredths, 100, mouse_threshold); XUNLOCK(); } /* _xwin_mouse_leave_notify: * Reset the mouse speed to its original value when the cursor leave the * Allegro window. */ void _xwin_mouse_leave_notify(void) { if (mouse_mult >= 0) { XLOCK(); XChangePointerControl(_xwin.display, 1, 1, mouse_mult, mouse_div, mouse_threshold); XUNLOCK(); } } /* _xwin_mouse_enter_notify: * Restore the mouse speed setting when the mouse cursor re-enters the * Allegro window. */ void _xwin_mouse_enter_notify(void) { if (last_xspeed >= 0) { _xwin_set_mouse_speed(last_xspeed, last_yspeed); } } allegro-4.4.3.1/src/x/xwin.h0000664000175000017500000000630413437077643014477 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Wrappers for Xlib functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_xwin_h #define __bma_xwin_h #include "xalleg.h" /* Defined in xmouse.c */ AL_VAR(int, _xwin_mouse_extended_range); /* Defined in xwin.c. */ AL_VAR(int, _xwin_last_line); AL_VAR(int, _xwin_in_gfx_call); /* The allegro X11 icon */ AL_VAR(void *, allegro_icon); AL_FUNC(void, _xwin_set_warped_mouse_mode, (int permanent)); AL_FUNC(int, _xwin_open_display, (char *name)); AL_FUNC(void, _xwin_close_display, (void)); AL_FUNC(int, _xwin_create_window, (void)); AL_FUNC(void, _xwin_destroy_window, (void)); AL_FUNC(BITMAP*, _xwin_create_screen, (GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int fullscreen)); AL_FUNC(void, _xwin_destroy_screen, (void)); AL_FUNC(void, _xwin_set_palette_range, (AL_CONST PALETTE p, int from, int to, int vsync)); AL_FUNC(void, _xwin_flush_buffers, (void)); AL_FUNC(void, _xwin_vsync, (void)); AL_FUNC(void, _xwin_handle_input, (void)); AL_FUNC(void, _xwin_enable_hardware_cursor, (int mode)); AL_FUNC(void, _xwin_redraw_window, (int x, int y, int w, int h)); AL_FUNC(int, _xwin_scroll_screen, (int x, int y)); AL_FUNC(void, _xwin_update_screen, (int x, int y, int w, int h)); AL_FUNC(void, _xwin_set_window_title, (AL_CONST char *name)); AL_FUNC(void, _xwin_change_keyboard_control, (int led, int on)); AL_FUNC(int, _xwin_get_pointer_mapping, (unsigned char map[], int nmap)); AL_FUNC(void, _xwin_init_keyboard_tables, (void)); #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR AL_FUNC(int, _xwin_set_mouse_sprite, (struct BITMAP *sprite, int x, int y)); AL_FUNC(int, _xwin_show_mouse, (struct BITMAP *bmp, int x, int y)); AL_FUNC(void, _xwin_hide_mouse, (void)); AL_FUNC(void, _xwin_move_mouse, (int x, int y)); #endif AL_FUNC(BITMAP*, _xdga_create_screen, (GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int fullscreen)); AL_FUNC(void, _xdga_destroy_screen, (void)); AL_FUNC(void, _xdga_set_palette_range, (AL_CONST PALETTE p, int from, int to, int vsync)); AL_FUNC(int, _xdga_scroll_screen, (int x, int y)); AL_FUNC(GFX_MODE_LIST*, _xwin_fetch_mode_list, (void)); /* Defined in xvtable.c. */ AL_FUNC(void, _xwin_replace_vtable, (struct GFX_VTABLE *vtable)); AL_FUNC(void, _xwin_drawing_mode, (void)); AL_FUNC(void, _xwin_lock, (BITMAP *bmp)); AL_FUNC(void, _xwin_unlock, (BITMAP *bmp)); /* Defined in xkeyboard.c. */ AL_FUNC(void, _xwin_keyboard_handler, (XKeyEvent *event, int dga2_hack)); AL_FUNC(void, _xwin_get_keyboard_mapping, (void)); AL_FUNC(void, _xwin_keyboard_focus_handler, (XFocusChangeEvent *event)); /* Defined in xmouse.c. */ AL_FUNC(void, _xwin_mouse_leave_notify, (void)); AL_FUNC(void, _xwin_mouse_enter_notify, (void)); #endif /* !__bma_xwin_h */ allegro-4.4.3.1/src/x/xwin.c0000664000175000017500000030263113437077643014474 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Wrappers for Xlib functions. * * By Michael Bukin. * * Video mode switching by Peter Wang and Benjamin Stover. * * X icon selection by Evert Glebbeek * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "xwin.h" #include #include #include #include #include #ifdef ALLEGRO_XWINDOWS_WITH_SHM #include #include #include #endif #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE #include #endif #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR #include #endif #ifdef ALLEGRO_XWINDOWS_WITH_XPM #include #endif #include "icon.xpm" #define XWIN_DEFAULT_WINDOW_TITLE "Allegro application" #define XWIN_DEFAULT_APPLICATION_NAME "allegro" #define XWIN_DEFAULT_APPLICATION_CLASS "Allegro" struct _xwin_type _xwin = { 0, /* display */ 0, /* lock count */ 0, /* screen */ None, /* window */ None, /* gc */ 0, /* visual */ None, /* colormap */ 0, /* ximage */ #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR None, /* ARGB cursor image */ XcursorFalse,/* Are ARGB cursors supported? */ #endif None, /* cursor */ XC_heart, /* cursor_shape */ 1, /* hw_cursor_ok */ 0, /* screen_to_buffer */ 0, /* set_colors */ 0, /* screen_data */ 0, /* screen_line */ 0, /* buffer_line */ 0, /* scroll_x */ 0, /* scroll_y */ 320, /* window_width */ 200, /* window_height */ 8, /* window_depth */ 320, /* screen_width */ 200, /* screen_height */ 8, /* screen_depth */ 320, /* virtual width */ 200, /* virtual_height */ 0, /* mouse_warped */ { 0 }, /* keycode_to_scancode */ 0, /* matching formats */ 0, /* fast_visual_depth */ 0, /* visual_is_truecolor */ 1, /* rsize */ 1, /* gsize */ 1, /* bsize */ 0, /* rshift */ 0, /* gshift */ 0, /* bshift */ { 0 }, /* cmap */ { 0 }, /* rmap */ { 0 }, /* gmap */ { 0 }, /* bmap */ #ifdef ALLEGRO_XWINDOWS_WITH_SHM { 0, 0, 0, 0 }, /* shminfo */ #endif 0, /* use_shm */ 0, /* in_dga_mode */ 0, /* keyboard_grabbed */ 0, /* mouse_grabbed */ #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE 0, /* modesinfo */ 0, /* num_modes */ 0, /* mode_switched */ 0, /* override_redirected */ #endif XWIN_DEFAULT_WINDOW_TITLE, /* window_title */ XWIN_DEFAULT_APPLICATION_NAME, /* application_name */ XWIN_DEFAULT_APPLICATION_CLASS, /* application_class */ FALSE, /* drawing_mode_ok */ #ifdef ALLEGRO_MULTITHREADED NULL, /* mutex */ #endif NULL, /* window close hook */ #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE 0, /* orig_modeinfo */ #endif None, /* fs_window */ None /* wm_window */ }; void *allegro_icon = icon_xpm; int _xwin_last_line = -1; int _xwin_in_gfx_call = 0; static COLORCONV_BLITTER_FUNC *blitter_func = NULL; static int use_bgr_palette_hack = FALSE; /* use BGR hack for color conversion palette? */ #ifndef ALLEGRO_MULTITHREADED int _xwin_missed_input; #endif #define X_MAX_EVENTS 50 #define MOUSE_WARP_DELAY 200 static char _xwin_driver_desc[256] = EMPTY_STRING; /* This is used to intercept window closing requests. */ static Atom wm_delete_window; #define PREFIX_I "al-xwin INFO: " #define PREFIX_W "al-xwin WARNING: " #define PREFIX_E "al-xwin ERROR: " /* Forward declarations for private functions. */ static int _xwin_private_open_display(char *name); static int _xwin_private_create_window(void); static void _xwin_private_destroy_window(void); static void _xwin_private_select_screen_to_buffer_function(void); static void _xwin_private_select_set_colors_function(void); static void _xwin_private_setup_driver_desc(GFX_DRIVER *drv); static BITMAP *_xwin_private_create_screen(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int fullscreen); static void _xwin_private_destroy_screen(void); static BITMAP *_xwin_private_create_screen_bitmap(GFX_DRIVER *drv, unsigned char *frame_buffer, int bytes_per_buffer_line); static void _xwin_private_create_mapping_tables(void); static void _xwin_private_create_mapping(unsigned long *map, int ssize, int dsize, int dshift); static int _xwin_private_display_is_local(void); static int _xwin_private_create_ximage(int w, int h); static void _xwin_private_destroy_ximage(void); static void _xwin_private_prepare_visual(void); static int _xwin_private_matching_formats(void); static void _xwin_private_hack_shifts(void); static int _xwin_private_colorconv_usable(void); static int _xwin_private_fast_visual_depth(void); static void _xwin_private_set_matching_colors(AL_CONST PALETTE p, int from, int to); static void _xwin_private_set_truecolor_colors(AL_CONST PALETTE p, int from, int to); static void _xwin_private_set_palette_colors(AL_CONST PALETTE p, int from, int to); static void _xwin_private_set_palette_range(AL_CONST PALETTE p, int from, int to); static void _xwin_private_set_window_defaults(void); static void _xwin_private_flush_buffers(void); static void _xwin_private_process_event(XEvent *event); static void _xwin_private_set_warped_mouse_mode(int permanent); static void _xwin_private_redraw_window(int x, int y, int w, int h); static int _xwin_private_scroll_screen(int x, int y); static void _xwin_private_update_screen(int x, int y, int w, int h); static void _xwin_private_set_window_title(AL_CONST char *name); static void _xwin_private_set_window_name(AL_CONST char *name, AL_CONST char *group); static int _xwin_private_get_pointer_mapping(unsigned char map[], int nmap); static void _xwin_private_fast_colorconv(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_8_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_8_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_8_to_24(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_8_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_15_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_15_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_15_to_24(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_15_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_16_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_16_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_16_to_24(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_16_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_24_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_24_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_24_to_24(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_24_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_32_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_32_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_32_to_24(int sx, int sy, int sw, int sh); static void _xwin_private_fast_truecolor_32_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_slow_truecolor_8(int sx, int sy, int sw, int sh); static void _xwin_private_slow_truecolor_15(int sx, int sy, int sw, int sh); static void _xwin_private_slow_truecolor_16(int sx, int sy, int sw, int sh); static void _xwin_private_slow_truecolor_24(int sx, int sy, int sw, int sh); static void _xwin_private_slow_truecolor_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_8_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_8_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_8_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_15_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_15_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_15_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_16_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_16_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_16_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_24_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_24_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_24_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_32_to_8(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_32_to_16(int sx, int sy, int sw, int sh); static void _xwin_private_fast_palette_32_to_32(int sx, int sy, int sw, int sh); static void _xwin_private_slow_palette_8(int sx, int sy, int sw, int sh); static void _xwin_private_slow_palette_15(int sx, int sy, int sw, int sh); static void _xwin_private_slow_palette_16(int sx, int sy, int sw, int sh); static void _xwin_private_slow_palette_24(int sx, int sy, int sw, int sh); static void _xwin_private_slow_palette_32(int sx, int sy, int sw, int sh); #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE static void _xvidmode_private_set_fullscreen(int w, int h, int *vidmode_width, int *vidmode_height); static void _xvidmode_private_unset_fullscreen(void); #endif uintptr_t _xwin_write_line(BITMAP *bmp, int line); void _xwin_unwrite_line(BITMAP *bmp); #ifndef ALLEGRO_NO_ASM uintptr_t _xwin_write_line_asm(BITMAP *bmp, int line); void _xwin_unwrite_line_asm(BITMAP *bmp); #endif /* _xwin_open_display: * Wrapper for XOpenDisplay. */ static int _xwin_private_open_display(char *name) { if (_xwin.display != 0) return -1; _xwin.display = XOpenDisplay(name); _xwin.screen = ((_xwin.display == 0) ? 0 : XDefaultScreen(_xwin.display)); return ((_xwin.display != 0) ? 0 : -1); } int _xwin_open_display(char *name) { int result; XLOCK(); result = _xwin_private_open_display(name); XUNLOCK(); return result; } /* _xwin_close_display: * Wrapper for XCloseDisplay. */ void _xwin_close_display(void) { Display *dpy; if (!_unix_bg_man->multi_threaded) { XLOCK(); } if (_xwin.display != 0) { _xwin_destroy_window(); dpy = _xwin.display; _xwin.display = 0; XCloseDisplay(dpy); } if (!_unix_bg_man->multi_threaded) { XUNLOCK(); } } /* _xwin_hide_x_mouse: * Create invisible X cursor. */ static void _xwin_hide_x_mouse(void) { unsigned long gcmask; XGCValues gcvalues; Pixmap pixmap; XUndefineCursor(_xwin.display, _xwin.window); if (_xwin.cursor != None) { XFreeCursor(_xwin.display, _xwin.cursor); _xwin.cursor = None; } #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR if (_xwin.xcursor_image != None) { XcursorImageDestroy(_xwin.xcursor_image); _xwin.xcursor_image = None; } #endif pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1); if (pixmap != None) { GC temp_gc; XColor color; gcmask = GCFunction | GCForeground | GCBackground; gcvalues.function = GXcopy; gcvalues.foreground = 0; gcvalues.background = 0; temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues); XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0); XFreeGC(_xwin.display, temp_gc); color.pixel = 0; color.red = color.green = color.blue = 0; color.flags = DoRed | DoGreen | DoBlue; _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); XFreePixmap(_xwin.display, pixmap); } else { _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); } } /* _xwin_wait_mapped: * Wait for a window to become mapped. */ static void _xwin_wait_mapped(Window win) { /* Note: * The busy loop below is just a hack to work around my broken X11. * A call to XMaskEvent will block indefinitely and no Allegro * programs (which create a window) will start up at all. Replacing * XMaskEvent with a busy loop calling XCheckMaskEvent repeatedly * somehow works though.. */ while (1) { XEvent e; if (XCheckTypedEvent(_xwin.display, MapNotify, &e)) { if (e.xmap.event == win) break; } rest(1); } } /* _xwin_create_window: * We use 3 windows: * - fs_window (for fullscreen) * - wm_window (window managed) * - window (the real window) * * Two of which will be created here: wm_window and window. The fullscreen * window gets (re)created when needed, because reusing it causes trouble see * http://sourceforge.net/tracker/index.php?func=detail&aid=1441740&group_id=5665&atid=105665 * The real window uses wm_window as parent initially and will be reparented * to the (freshly created) fullscreen window when requested and reparented * back again in screen_destroy. * * Idea/concept of three windows borrowed from SDL. But somehow SDL manages * to reuse the fullscreen window too. */ static int _xwin_private_create_window(void) { unsigned long gcmask; XGCValues gcvalues; XSetWindowAttributes setattr; XWindowAttributes getattr; if (_xwin.display == 0) return -1; _mouse_on = FALSE; /* Create the managed window. */ setattr.background_pixel = XBlackPixel(_xwin.display, _xwin.screen); setattr.border_pixel = XBlackPixel(_xwin.display, _xwin.screen); setattr.event_mask = (KeyPressMask | KeyReleaseMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | ExposureMask | PropertyChangeMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask /*| MappingNotifyMask (SubstructureRedirectMask?)*/); _xwin.wm_window = XCreateWindow(_xwin.display, XDefaultRootWindow(_xwin.display), 0, 0, 320, 200, 0, CopyFromParent, InputOutput, CopyFromParent, CWBackPixel | CWBorderPixel | CWEventMask, &setattr); /* Get associated visual and window depth (bits per pixel). */ XGetWindowAttributes(_xwin.display, _xwin.wm_window, &getattr); _xwin.visual = getattr.visual; _xwin.window_depth = getattr.depth; /* Create and install colormap. */ if ((_xwin.visual->class == PseudoColor) || (_xwin.visual->class == GrayScale) || (_xwin.visual->class == DirectColor)) { _xwin.colormap = XCreateColormap(_xwin.display, _xwin.wm_window, _xwin.visual, AllocAll); } else { _xwin.colormap = XCreateColormap(_xwin.display, _xwin.wm_window, _xwin.visual, AllocNone); } XSetWindowColormap(_xwin.display, _xwin.wm_window, _xwin.colormap); XInstallColormap(_xwin.display, _xwin.colormap); /* Create the real / drawing window (reuses setattr). */ setattr.colormap = _xwin.colormap; _xwin.window = XCreateWindow(_xwin.display, _xwin.wm_window, 0, 0, 320, 200, 0, CopyFromParent, InputOutput, CopyFromParent, CWBackPixel | CWBorderPixel | CWEventMask | CWColormap, &setattr); /* Map the real / drawing window it won't appear untill the parent does */ XMapWindow(_xwin.display, _xwin.window); /* Set WM_DELETE_WINDOW atom in WM_PROTOCOLS property (to get window_delete requests). */ wm_delete_window = XInternAtom(_xwin.display, "WM_DELETE_WINDOW", False); XSetWMProtocols(_xwin.display, _xwin.wm_window, &wm_delete_window, 1); /* Set default window parameters. */ (*_xwin_window_defaultor)(); /* Create graphics context. */ gcmask = GCFunction | GCForeground | GCBackground | GCFillStyle | GCPlaneMask; gcvalues.function = GXcopy; gcvalues.foreground = setattr.border_pixel; gcvalues.background = setattr.border_pixel; gcvalues.fill_style = FillSolid; gcvalues.plane_mask = AllPlanes; _xwin.gc = XCreateGC(_xwin.display, _xwin.window, gcmask, &gcvalues); /* Create invisible X cursor. */ _xwin_hide_x_mouse(); #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR /* Detect if ARGB cursors are supported */ _xwin.support_argb_cursor = XcursorSupportsARGB(_xwin.display); #endif _xwin.hw_cursor_ok = 0; return 0; } int _xwin_create_window(void) { int result; XLOCK(); result = (*_xwin_window_creator)(); XUNLOCK(); return result; } /* _xwin_destroy_window: * Wrapper for XDestroyWindow. */ static void _xwin_private_destroy_window(void) { _xwin_private_destroy_screen(); if (_xwin.cursor != None) { XUndefineCursor(_xwin.display, _xwin.window); XFreeCursor(_xwin.display, _xwin.cursor); _xwin.cursor = None; } #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR if (_xwin.xcursor_image != None) { XcursorImageDestroy(_xwin.xcursor_image); _xwin.xcursor_image = None; } #endif _xwin.visual = 0; if (_xwin.gc != None) { XFreeGC(_xwin.display, _xwin.gc); _xwin.gc = None; } if (_xwin.colormap != None) { XUninstallColormap(_xwin.display, _xwin.colormap); XFreeColormap(_xwin.display, _xwin.colormap); _xwin.colormap = None; } if (_xwin.window != None) { XUnmapWindow(_xwin.display, _xwin.window); XDestroyWindow(_xwin.display, _xwin.window); _xwin.window = None; } if (_xwin.wm_window != None) { XDestroyWindow(_xwin.display, _xwin.wm_window); _xwin.wm_window = None; } } void _xwin_destroy_window(void) { XLOCK(); _xwin_private_destroy_window(); XUNLOCK(); } typedef void (*_XWIN_SCREEN_TO_BUFFER)(int x, int y, int w, int h); static _XWIN_SCREEN_TO_BUFFER _xwin_screen_to_buffer_function[5][10] = { { _xwin_private_slow_truecolor_8, _xwin_private_fast_truecolor_8_to_8, _xwin_private_fast_truecolor_8_to_16, _xwin_private_fast_truecolor_8_to_24, _xwin_private_fast_truecolor_8_to_32, _xwin_private_slow_palette_8, _xwin_private_fast_palette_8_to_8, _xwin_private_fast_palette_8_to_16, 0, _xwin_private_fast_palette_8_to_32 }, { _xwin_private_slow_truecolor_15, _xwin_private_fast_truecolor_15_to_8, _xwin_private_fast_truecolor_15_to_16, _xwin_private_fast_truecolor_15_to_24, _xwin_private_fast_truecolor_15_to_32, _xwin_private_slow_palette_15, _xwin_private_fast_palette_15_to_8, _xwin_private_fast_palette_15_to_16, 0, _xwin_private_fast_palette_15_to_32 }, { _xwin_private_slow_truecolor_16, _xwin_private_fast_truecolor_16_to_8, _xwin_private_fast_truecolor_16_to_16, _xwin_private_fast_truecolor_16_to_24, _xwin_private_fast_truecolor_16_to_32, _xwin_private_slow_palette_16, _xwin_private_fast_palette_16_to_8, _xwin_private_fast_palette_16_to_16, 0, _xwin_private_fast_palette_16_to_32 }, { _xwin_private_slow_truecolor_24, _xwin_private_fast_truecolor_24_to_8, _xwin_private_fast_truecolor_24_to_16, _xwin_private_fast_truecolor_24_to_24, _xwin_private_fast_truecolor_24_to_32, _xwin_private_slow_palette_24, _xwin_private_fast_palette_24_to_8, _xwin_private_fast_palette_24_to_16, 0, _xwin_private_fast_palette_24_to_32 }, { _xwin_private_slow_truecolor_32, _xwin_private_fast_truecolor_32_to_8, _xwin_private_fast_truecolor_32_to_16, _xwin_private_fast_truecolor_32_to_24, _xwin_private_fast_truecolor_32_to_32, _xwin_private_slow_palette_32, _xwin_private_fast_palette_32_to_8, _xwin_private_fast_palette_32_to_16, 0, _xwin_private_fast_palette_32_to_32 }, }; /* _xwin_select_screen_to_buffer_function: * Select which function should be used for updating frame buffer with screen data. */ static void _xwin_private_select_screen_to_buffer_function(void) { int i, j; if (_xwin.matching_formats) { _xwin.screen_to_buffer = 0; } else { switch (_xwin.screen_depth) { case 8: i = 0; break; case 15: i = 1; break; case 16: i = 2; break; case 24: i = 3; break; case 32: i = 4; break; default: i = 0; break; } switch (_xwin.fast_visual_depth) { case 0: j = 0; break; case 8: j = 1; break; case 16: j = 2; break; case 24: j = 3; break; case 32: j = 4; break; default: j = 0; break; } if (!_xwin.visual_is_truecolor) j += 5; if (_xwin_private_colorconv_usable()) { TRACE(PREFIX_I "Using generic color conversion blitter (%u, %u).\n", _xwin.screen_depth, _xwin.fast_visual_depth); blitter_func = _get_colorconv_blitter(_xwin.screen_depth, _xwin.fast_visual_depth); _xwin.screen_to_buffer = _xwin_private_fast_colorconv; } else { _xwin.screen_to_buffer = _xwin_screen_to_buffer_function[i][j]; } } } /* _xwin_select_set_colors_function: * Select which function should be used for setting hardware colors. */ static void _xwin_private_select_set_colors_function(void) { if (_xwin.screen_depth != 8) { _xwin.set_colors = 0; } else { if (_xwin.matching_formats) { _xwin.set_colors = _xwin_private_set_matching_colors; } else if (_xwin.visual_is_truecolor) { _xwin.set_colors = _xwin_private_set_truecolor_colors; } else { _xwin.set_colors = _xwin_private_set_palette_colors; } } } /* _xwin_setup_driver_desc: * Sets up the X-Windows driver description string. */ static void _xwin_private_setup_driver_desc(GFX_DRIVER *drv) { char tmp1[256], tmp2[128], tmp3[128], tmp4[128]; /* Prepare driver description. */ if (_xwin.matching_formats) { uszprintf(_xwin_driver_desc, sizeof(_xwin_driver_desc), uconvert_ascii("X-Windows graphics, in matching, %d bpp %s", tmp1), _xwin.window_depth, uconvert_ascii("real depth", tmp2)); } else { uszprintf(_xwin_driver_desc, sizeof(_xwin_driver_desc), uconvert_ascii("X-Windows graphics, in %s %s, %d bpp %s", tmp1), uconvert_ascii((_xwin.fast_visual_depth ? "fast" : "slow"), tmp2), uconvert_ascii((_xwin.visual_is_truecolor ? "truecolor" : "paletted"), tmp3), _xwin.window_depth, uconvert_ascii("real depth", tmp4)); } drv->desc = _xwin_driver_desc; } /* _xwin_create_screen: * Creates screen data and other resources. */ static BITMAP *_xwin_private_create_screen(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int fullscreen) { if (_xwin.window == None) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("No window")); return 0; } /* Choose convenient size. */ if ((w == 0) && (h == 0)) { w = 320; h = 200; } if (vw < w) vw = w; if (vh < h) vh = h; if (1 #ifdef ALLEGRO_COLOR8 && (depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (depth != 15) && (depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return 0; } /* Save dimensions. */ _xwin.window_width = w; _xwin.window_height = h; _xwin.screen_width = w; _xwin.screen_height = h; _xwin.screen_depth = depth; _xwin.virtual_width = vw; _xwin.virtual_height = vh; /* Resize the (real) window */ XResizeWindow(_xwin.display, _xwin.window, w, h); if (fullscreen) { XSetWindowAttributes setattr; /* Local width and height vars used for fullscreen window size and for * storing the video_mode size which is then used to center the window. */ int fs_width = DisplayWidth(_xwin.display, _xwin.screen); int fs_height = DisplayHeight(_xwin.display, _xwin.screen); /* Create the fullscreen window. */ setattr.override_redirect = True; setattr.background_pixel = XBlackPixel(_xwin.display, _xwin.screen); setattr.border_pixel = XBlackPixel(_xwin.display, _xwin.screen); setattr.event_mask = StructureNotifyMask; setattr.colormap = _xwin.colormap; _xwin.fs_window = XCreateWindow(_xwin.display, XDefaultRootWindow(_xwin.display), 0, 0, fs_width, fs_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWBackPixel | CWColormap | CWBorderPixel | CWEventMask, &setattr); /* Map the fullscreen window. */ XMapRaised(_xwin.display, _xwin.fs_window); _xwin_wait_mapped(_xwin.fs_window); /* Make sure we got to the top of the window stack. */ XRaiseWindow(_xwin.display, _xwin.fs_window); /* Reparent the real window. */ XReparentWindow(_xwin.display, _xwin.window, _xwin.fs_window, 0, 0); /* Grab the keyboard and mouse. */ if (XGrabKeyboard(_xwin.display, XDefaultRootWindow(_xwin.display), False, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not grab keyboard")); return 0; } _xwin.keyboard_grabbed = 1; if (XGrabPointer(_xwin.display, _xwin.window, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime) != GrabSuccess) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not grab mouse")); return 0; } _xwin.mouse_grabbed = 1; #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE /* Try to switch video mode. This must be done after the pointer is * grabbed, because otherwise it can be outside the window negating the * XF86VidModeSetViewPort done in set_fullscreen. This makes the old * center the window hack unnescesarry. Notice that since the XF86VM * extension requests do not go through the regular X output buffer? We * need to make sure that all above requests are processed first. */ XSync(_xwin.display, False); _xvidmode_private_set_fullscreen(w, h, &fs_width, &fs_height); #endif /* Center the window (if necessary). */ if ((fs_width != w) || (fs_height != h)) XMoveWindow(_xwin.display, _xwin.window, (fs_width - w) / 2, (fs_height - h) / 2); /* Last: center the cursor. */ XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, w / 2, h / 2); } else { XSizeHints *hints = XAllocSizeHints();; /* Resize managed window. */ XResizeWindow(_xwin.display, _xwin.wm_window, w, h); /* Set size and position hints for Window Manager. */ if (hints) { hints->flags = PMinSize | PMaxSize | PBaseSize; hints->min_width = hints->max_width = hints->base_width = w; hints->min_height = hints->max_height = hints->base_height = h; XSetWMNormalHints(_xwin.display, _xwin.wm_window, hints); XFree(hints); } /* Map the window managed window. */ XMapWindow(_xwin.display, _xwin.wm_window); _xwin_wait_mapped(_xwin.wm_window); } /* Create XImage with the size of virtual screen. */ if (_xwin_private_create_ximage(vw, vh) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not create XImage")); return 0; } /* Prepare visual for further use. */ _xwin_private_prepare_visual(); /* Test that frame buffer is fast (can be accessed directly). */ _xwin.fast_visual_depth = _xwin_private_fast_visual_depth(); /* Create screen bitmap from frame buffer. */ return _xwin_private_create_screen_bitmap(drv, (unsigned char *)_xwin.ximage->data + _xwin.ximage->xoffset, _xwin.ximage->bytes_per_line); } BITMAP *_xwin_create_screen(GFX_DRIVER *drv, int w, int h, int vw, int vh, int depth, int fullscreen) { BITMAP *bmp; XLOCK(); bmp = _xwin_private_create_screen(drv, w, h, vw, vh, depth, fullscreen); if (bmp == 0) { _xwin_private_destroy_screen(); } XUNLOCK(); return bmp; } /* _xwin_destroy_screen: * Destroys screen resources. */ static void _xwin_private_destroy_screen(void) { if (_xwin.buffer_line != 0) { _AL_FREE(_xwin.buffer_line); _xwin.buffer_line = 0; } if (_xwin.screen_line != 0) { _AL_FREE(_xwin.screen_line); _xwin.screen_line = 0; } if (_xwin.screen_data != 0) { _AL_FREE(_xwin.screen_data); _xwin.screen_data = 0; } _xwin_private_destroy_ximage(); if (_xwin.mouse_grabbed) { XUngrabPointer(_xwin.display, CurrentTime); _xwin.mouse_grabbed = 0; } if (_xwin.keyboard_grabbed) { XUngrabKeyboard(_xwin.display, CurrentTime); _xwin.keyboard_grabbed = 0; } #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE _xvidmode_private_unset_fullscreen(); #endif /* whack color-conversion blitter */ if (blitter_func) { _release_colorconv_blitter(blitter_func); blitter_func = NULL; } if (_xwin.fs_window != None) { /* Reparent the real window! */ XReparentWindow(_xwin.display, _xwin.window, _xwin.wm_window, 0, 0); XUnmapWindow(_xwin.display, _xwin.fs_window); XDestroyWindow(_xwin.display, _xwin.fs_window); _xwin.fs_window = None; } else { XUnmapWindow(_xwin.display, _xwin.wm_window); } (*_xwin_window_defaultor)(); } void _xwin_destroy_screen(void) { XLOCK(); _xwin_private_destroy_screen(); XUNLOCK(); } /* _xwin_create_screen_bitmap: * Create screen bitmap from frame buffer. */ static BITMAP *_xwin_private_create_screen_bitmap(GFX_DRIVER *drv, unsigned char *frame_buffer, int bytes_per_buffer_line) { int line; int bytes_per_screen_line; BITMAP *bmp; /* Test that Allegro and X-Windows pixel formats are the same. */ _xwin.matching_formats = _xwin_private_matching_formats(); /* Create mapping tables for color components. */ _xwin_private_create_mapping_tables(); /* Determine how to update frame buffer with screen data. */ _xwin_private_select_screen_to_buffer_function(); /* Determine how to set colors in "hardware". */ _xwin_private_select_set_colors_function(); /* Create line accelerators for screen data. */ _xwin.screen_line = _AL_MALLOC_ATOMIC(_xwin.virtual_height * sizeof(unsigned char*)); if (_xwin.screen_line == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return 0; } /* If formats match, then use frame buffer as screen data, otherwise malloc. */ if (_xwin.matching_formats) { bytes_per_screen_line = bytes_per_buffer_line; _xwin.screen_data = 0; _xwin.screen_line[0] = frame_buffer; } else { bytes_per_screen_line = _xwin.virtual_width * BYTES_PER_PIXEL(_xwin.screen_depth); _xwin.screen_data = _AL_MALLOC_ATOMIC(_xwin.virtual_height * bytes_per_screen_line); if (_xwin.screen_data == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return 0; } _xwin.screen_line[0] = _xwin.screen_data; } /* Initialize line starts. */ for (line = 1; line < _xwin.virtual_height; line++) _xwin.screen_line[line] = _xwin.screen_line[line - 1] + bytes_per_screen_line; /* Create line accelerators for frame buffer. */ if (!_xwin.matching_formats && _xwin.fast_visual_depth) { _xwin.buffer_line = _AL_MALLOC(_xwin.virtual_height * sizeof(unsigned char*)); if (_xwin.buffer_line == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return 0; } _xwin.buffer_line[0] = frame_buffer; for (line = 1; line < _xwin.virtual_height; line++) _xwin.buffer_line[line] = _xwin.buffer_line[line - 1] + bytes_per_buffer_line; } /* Create bitmap. */ bmp = _make_bitmap(_xwin.virtual_width, _xwin.virtual_height, (uintptr_t) (_xwin.screen_line[0]), drv, _xwin.screen_depth, bytes_per_screen_line); if (bmp == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return 0; } /* Fixup bitmap fields. */ drv->w = bmp->cr = _xwin.screen_width; drv->h = bmp->cb = _xwin.screen_height; drv->vid_mem = _xwin.virtual_width * _xwin.virtual_height * BYTES_PER_PIXEL(_xwin.screen_depth); /* Need some magic for updating frame buffer. */ #ifndef ALLEGRO_NO_ASM bmp->write_bank = _xwin_write_line_asm; bmp->vtable->unwrite_bank = _xwin_unwrite_line_asm; #else bmp->write_bank = _xwin_write_line; bmp->vtable->unwrite_bank = _xwin_unwrite_line; #endif /* Replace entries in vtable with magical wrappers. */ _xwin_replace_vtable(bmp->vtable); /* The drawing mode may not be ok for direct updates anymore. */ _xwin_drawing_mode(); /* Initialize other fields in _xwin structure. */ _xwin_last_line = -1; _xwin_in_gfx_call = 0; _xwin.scroll_x = 0; _xwin.scroll_y = 0; /* Setup driver description string. */ _xwin_private_setup_driver_desc(drv); return bmp; } /* _xwin_create_mapping_tables: * Create mapping between Allegro color component and X-Windows color component. */ static void _xwin_private_create_mapping_tables(void) { if (!_xwin.matching_formats) { if (_xwin.visual_is_truecolor) { switch (_xwin.screen_depth) { case 8: /* Will be modified later in set_palette. */ _xwin_private_create_mapping(_xwin.rmap, 256, 0, 0); _xwin_private_create_mapping(_xwin.gmap, 256, 0, 0); _xwin_private_create_mapping(_xwin.bmap, 256, 0, 0); break; case 15: _xwin_private_create_mapping(_xwin.rmap, 32, _xwin.rsize, _xwin.rshift); _xwin_private_create_mapping(_xwin.gmap, 32, _xwin.gsize, _xwin.gshift); _xwin_private_create_mapping(_xwin.bmap, 32, _xwin.bsize, _xwin.bshift); break; case 16: _xwin_private_create_mapping(_xwin.rmap, 32, _xwin.rsize, _xwin.rshift); _xwin_private_create_mapping(_xwin.gmap, 64, _xwin.gsize, _xwin.gshift); _xwin_private_create_mapping(_xwin.bmap, 32, _xwin.bsize, _xwin.bshift); break; case 24: case 32: _xwin_private_create_mapping(_xwin.rmap, 256, _xwin.rsize, _xwin.rshift); _xwin_private_create_mapping(_xwin.gmap, 256, _xwin.gsize, _xwin.gshift); _xwin_private_create_mapping(_xwin.bmap, 256, _xwin.bsize, _xwin.bshift); break; } } else { int i; /* Might be modified later in set_palette. */ for (i = 0; i < 256; i++) _xwin.rmap[i] = _xwin.gmap[i] = _xwin.bmap[i] = 0; } } } /* _xwin_create_mapping: * Create mapping between Allegro color component and X-Windows color component. */ static void _xwin_private_create_mapping(unsigned long *map, int ssize, int dsize, int dshift) { int i, smax, dmax; smax = ssize - 1; dmax = dsize - 1; for (i = 0; i < ssize; i++) map[i] = ((dmax * i) / smax) << dshift; for (; i < 256; i++) map[i] = map[i % ssize]; } /* _xwin_display_is_local: * Tests that display connection is local. * (Note: this is duplicated in xdga2.c). */ static int _xwin_private_display_is_local(void) { char *name; if (_xwin.display == 0) return 0; /* Get display name and test for local display. */ name = XDisplayName(0); return (((name == 0) || (name[0] == ':') || (strncmp(name, "unix:", 5) == 0)) ? 1 : 0); } /* _xwin_create_ximage: * Create XImage for accessing window. */ static int _xwin_private_create_ximage(int w, int h) { XImage *image = 0; /* I'm mage or I'm old? */ if (_xwin.display == 0) return -1; #ifdef ALLEGRO_XWINDOWS_WITH_SHM if (_xwin_private_display_is_local() && XShmQueryExtension(_xwin.display)) _xwin.use_shm = 1; else _xwin.use_shm = 0; #else _xwin.use_shm = 0; #endif #ifdef ALLEGRO_XWINDOWS_WITH_SHM if (_xwin.use_shm) { /* Try to create shared memory XImage. */ image = XShmCreateImage(_xwin.display, _xwin.visual, _xwin.window_depth, ZPixmap, 0, &_xwin.shminfo, w, h); do { if (image != 0) { /* Create shared memory segment. */ _xwin.shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT | 0777); if (_xwin.shminfo.shmid != -1) { /* Attach shared memory to our address space. */ _xwin.shminfo.shmaddr = image->data = shmat(_xwin.shminfo.shmid, 0, 0); if (_xwin.shminfo.shmaddr != (char*) -1) { _xwin.shminfo.readOnly = True; /* Attach shared memory to the X-server address space. */ if (XShmAttach(_xwin.display, &_xwin.shminfo)) { XSync(_xwin.display, False); break; } shmdt(_xwin.shminfo.shmaddr); } shmctl(_xwin.shminfo.shmid, IPC_RMID, 0); } XDestroyImage(image); image = 0; } _xwin.use_shm = 0; } while (0); } #endif if (image == 0) { /* Try to create ordinary XImage. */ #if 0 Pixmap pixmap; pixmap = XCreatePixmap(_xwin.display, _xwin.window, w, h, _xwin.window_depth); if (pixmap != None) { image = XGetImage(_xwin.display, pixmap, 0, 0, w, h, AllPlanes, ZPixmap); XFreePixmap(_xwin.display, pixmap); } #else image = XCreateImage(_xwin.display, _xwin.visual, _xwin.window_depth, ZPixmap, 0, 0, w, h, 32, 0); if (image != 0) { image->data = _AL_MALLOC_ATOMIC(image->bytes_per_line * image->height); if (image->data == 0) { XDestroyImage(image); image = 0; } } #endif } _xwin.ximage = image; return ((image != 0) ? 0 : -1); } /* _xwin_destroy_ximage: * Destroy XImage. */ static void _xwin_private_destroy_ximage(void) { if (_xwin.ximage != 0) { #ifdef ALLEGRO_XWINDOWS_WITH_SHM if (_xwin.use_shm) { XShmDetach(_xwin.display, &_xwin.shminfo); shmdt(_xwin.shminfo.shmaddr); shmctl(_xwin.shminfo.shmid, IPC_RMID, 0); } #endif XDestroyImage(_xwin.ximage); _xwin.ximage = 0; } } /* _xwin_prepare_visual: * Prepare visual for further use. */ static void _xwin_private_prepare_visual(void) { int i, r, g, b; int rmax, gmax, bmax; unsigned long mask; XColor color; if ((_xwin.visual->class == TrueColor) || (_xwin.visual->class == DirectColor)) { /* Use TrueColor and DirectColor visuals as truecolor. */ /* Red shift and size. */ for (mask = _xwin.visual->red_mask, i = 0; (mask & 1) != 1; mask >>= 1) i++; _xwin.rshift = i; for (i = 0; mask != 0; mask >>= 1) i++; _xwin.rsize = 1 << i; /* Green shift and size. */ for (mask = _xwin.visual->green_mask, i = 0; (mask & 1) != 1; mask >>= 1) i++; _xwin.gshift = i; for (i = 0; mask != 0; mask >>= 1) i++; _xwin.gsize = 1 << i; /* Blue shift and size. */ for (mask = _xwin.visual->blue_mask, i = 0; (mask & 1) != 1; mask >>= 1) i++; _xwin.bshift = i; for (i = 0; mask != 0; mask >>= 1) i++; _xwin.bsize = 1 << i; /* Convert DirectColor visual into true color visual. */ if (_xwin.visual->class == DirectColor) { color.flags = DoRed; rmax = _xwin.rsize - 1; gmax = _xwin.gsize - 1; bmax = _xwin.bsize - 1; for (i = 0; i < _xwin.rsize; i++) { color.pixel = i << _xwin.rshift; color.red = ((rmax <= 0) ? 0 : ((i * 65535L) / rmax)); XStoreColor(_xwin.display, _xwin.colormap, &color); } color.flags = DoGreen; for (i = 0; i < _xwin.gsize; i++) { color.pixel = i << _xwin.gshift; color.green = ((gmax <= 0) ? 0 : ((i * 65535L) / gmax)); XStoreColor(_xwin.display, _xwin.colormap, &color); } color.flags = DoBlue; for (i = 0; i < _xwin.bsize; i++) { color.pixel = i << _xwin.bshift; color.blue = ((bmax <= 0) ? 0 : ((i * 65535L) / bmax)); XStoreColor(_xwin.display, _xwin.colormap, &color); } } _xwin.visual_is_truecolor = 1; } else if ((_xwin.visual->class == PseudoColor) || (_xwin.visual->class == GrayScale)) { /* Convert read-write palette visual into true color visual. */ b = _xwin.window_depth / 3; r = (_xwin.window_depth - b) / 2; g = _xwin.window_depth - r - b; _xwin.rsize = 1 << r; _xwin.gsize = 1 << g; _xwin.bsize = 1 << b; _xwin.rshift = g + b; _xwin.gshift = b; _xwin.bshift = 0; _xwin.visual_is_truecolor = 1; rmax = _xwin.rsize - 1; gmax = _xwin.gsize - 1; bmax = _xwin.bsize - 1; color.flags = DoRed | DoGreen | DoBlue; for (r = 0; r < _xwin.rsize; r++) { for (g = 0; g < _xwin.gsize; g++) { for (b = 0; b < _xwin.bsize; b++) { color.pixel = (r << _xwin.rshift) | (g << _xwin.gshift) | (b << _xwin.bshift); color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax)); color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax)); color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax)); XStoreColor(_xwin.display, _xwin.colormap, &color); } } } } else { /* All other visual types are paletted. */ _xwin.rsize = 1; _xwin.bsize = 1; _xwin.gsize = 1; _xwin.rshift = 0; _xwin.gshift = 0; _xwin.bshift = 0; _xwin.visual_is_truecolor = 0; /* Make fixed palette and create mapping RRRRGGGGBBBB -> palette index. */ for (r = 0; r < 16; r++) { for (g = 0; g < 16; g++) { for (b = 0; b < 16; b++) { color.red = (r * 65535L) / 15; color.green = (g * 65535L) / 15; color.blue = (b * 65535L) / 15; XAllocColor(_xwin.display, _xwin.colormap, &color); _xwin.cmap[(r << 8) | (g << 4) | b] = color.pixel; } } } } } /* _xwin_matching_formats: * Find if color formats match. */ static int _xwin_private_matching_formats(void) { if (_xwin.fast_visual_depth == 0) return 0; if (_xwin.screen_depth == 8) { /* For matching 8 bpp modes visual must be PseudoColor or GrayScale. */ if (((_xwin.visual->class != PseudoColor) && (_xwin.visual->class != GrayScale)) || (_xwin.fast_visual_depth != 8) || (_xwin.window_depth != 8)) return 0; } else if ((_xwin.visual->class != TrueColor) && (_xwin.visual->class != DirectColor)) { /* For matching true color modes visual must be TrueColor or DirectColor. */ return 0; } else if (_xwin.screen_depth == 15) { if ((_xwin.fast_visual_depth != 16) || (_xwin.rsize != 32) || (_xwin.gsize != 32) || (_xwin.bsize != 32) || ((_xwin.rshift != 0) && (_xwin.rshift != 10)) || ((_xwin.bshift != 0) && (_xwin.bshift != 10)) || (_xwin.gshift != 5)) return 0; _rgb_r_shift_15 = _xwin.rshift; _rgb_g_shift_15 = _xwin.gshift; _rgb_b_shift_15 = _xwin.bshift; } else if (_xwin.screen_depth == 16) { if ((_xwin.fast_visual_depth != 16) || (_xwin.rsize != 32) || (_xwin.gsize != 64) || (_xwin.bsize != 32) || ((_xwin.rshift != 0) && (_xwin.rshift != 11)) || ((_xwin.bshift != 0) && (_xwin.bshift != 11)) || (_xwin.gshift != 5)) return 0; _rgb_r_shift_16 = _xwin.rshift; _rgb_g_shift_16 = _xwin.gshift; _rgb_b_shift_16 = _xwin.bshift; } else if (_xwin.screen_depth == 24){ if ((_xwin.fast_visual_depth != 24) || (_xwin.rsize != 256) || (_xwin.gsize != 256) || (_xwin.bsize != 256) || ((_xwin.rshift != 0) && (_xwin.rshift != 16)) || ((_xwin.bshift != 0) && (_xwin.bshift != 16)) || (_xwin.gshift != 8)) return 0; _rgb_r_shift_24 = _xwin.rshift; _rgb_g_shift_24 = _xwin.gshift; _rgb_b_shift_24 = _xwin.bshift; } else if (_xwin.screen_depth == 32) { if ((_xwin.fast_visual_depth != 32) || (_xwin.rsize != 256) || (_xwin.gsize != 256) || (_xwin.bsize != 256) || ((_xwin.rshift != 0) && (_xwin.rshift != 16)) || ((_xwin.bshift != 0) && (_xwin.bshift != 16)) || (_xwin.gshift != 8)) return 0; _rgb_r_shift_32 = _xwin.rshift; _rgb_g_shift_32 = _xwin.gshift; _rgb_b_shift_32 = _xwin.bshift; } else { /* How did you get in here? */ return 0; } return 1; } /* _xwin_private_hack_shifts: * Make Allegro draw in BGR format if X uses BGR instead of RGB. */ static void _xwin_private_hack_shifts(void) { switch(_xwin.screen_depth) { case 8: use_bgr_palette_hack = TRUE; break; case 15: _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; break; case 16: _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; break; case 24: _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; break; case 32: _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; break; } } /* _xwin_private_colorconv_usable: * Find out if generic color conversion blitter can be used. */ static int _xwin_private_colorconv_usable(void) { use_bgr_palette_hack = FALSE; /* make sure this is initialized */ if (_xwin.fast_visual_depth == 0) { return 0; } else if (_xwin.fast_visual_depth == 8) { #if 0 /* TODO: check this out later. */ /* For usable 8 bpp modes visual must be PseudoColor or GrayScale. */ if ((_xwin.visual->class == PseudoColor) || (_xwin.visual->class == GrayScale)) return 1; #else return 0; #endif } else if ((_xwin.visual->class != TrueColor) && (_xwin.visual->class != DirectColor)) { /* For usable true color modes visual must be TrueColor or DirectColor. */ return 0; } else if ((_xwin.fast_visual_depth == 16) && (_xwin.rsize == 32) && ((_xwin.gsize == 32) || (_xwin.gsize == 64)) && (_xwin.bsize == 32) && ((_xwin.rshift == 0) || (_xwin.rshift == 10) || (_xwin.rshift == 11)) && ((_xwin.bshift == 0) || (_xwin.bshift == 10) || (_xwin.bshift == 11)) && (_xwin.gshift == 5)) { if (_xwin.bshift == 0) _xwin_private_hack_shifts(); return 1; } else if ((_xwin.fast_visual_depth == 24) && (_xwin.rsize == 256) && (_xwin.gsize == 256) && (_xwin.bsize == 256) && ((_xwin.rshift == 0) || (_xwin.rshift == 16)) && ((_xwin.bshift == 0) || (_xwin.bshift == 16)) && (_xwin.gshift == 8)) { if (_xwin.bshift == 0) _xwin_private_hack_shifts(); return 1; } else if ((_xwin.fast_visual_depth == 32) && (_xwin.rsize == 256) && (_xwin.gsize == 256) && (_xwin.bsize == 256) && ((_xwin.rshift == 0) || (_xwin.rshift == 16)) && ((_xwin.bshift == 0) || (_xwin.bshift == 16)) && (_xwin.gshift == 8)) { if (_xwin.bshift == 0) _xwin_private_hack_shifts(); return 1; } /* Too bad... Muahahaha! */ return 0; } /* _xwin_fast_visual_depth: * Find which depth is fast (when XImage can be accessed directly). */ static int _xwin_private_fast_visual_depth(void) { int ok, x, sizex; int test_depth; uint8_t *p8; uint16_t *p16; uint32_t *p32; if (_xwin.ximage == 0) return 0; /* Use first line of XImage for test. */ p8 = (uint8_t *) _xwin.ximage->data + _xwin.ximage->xoffset; p16 = (uint16_t*) p8; p32 = (uint32_t*) p8; sizex = _xwin.ximage->bytes_per_line - _xwin.ximage->xoffset; if ((_xwin.window_depth < 1) || (_xwin.window_depth > 32)) { return 0; } else if (_xwin.window_depth > 16) { test_depth = 32; sizex /= sizeof (uint32_t); } else if (_xwin.window_depth > 8) { test_depth = 16; sizex /= sizeof (uint16_t); } else { test_depth = 8; } if (sizex > _xwin.ximage->width) sizex = _xwin.ximage->width; /* Need at least two pixels wide line for test. */ if (sizex < 2) return 0; ok = 1; for (x = 0; x < sizex; x++) { int bit; for (bit = -1; bit < _xwin.window_depth; bit++) { unsigned long color = ((bit < 0) ? 0 : ((unsigned long) 1 << bit)); /* Write color through XImage API. */ XPutPixel(_xwin.ximage, x, 0, color); /* Read color with direct access. */ switch (test_depth) { case 8: if (p8[x] != color) ok = 0; break; case 16: if (p16[x] != color) ok = 0; break; case 32: if (p32[x] != color) ok = 0; break; default: ok = 0; break; } XPutPixel(_xwin.ximage, x, 0, 0); if (!ok) return 0; } } return test_depth; } /* _xwin_enable_hardware_cursor: * enable the hardware cursor; this disables the mouse mickey warping hack */ void _xwin_enable_hardware_cursor(int mode) { #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR if (_xwin.support_argb_cursor) { _xwin.hw_cursor_ok = mode; } else #endif { _xwin.hw_cursor_ok = 0; } /* Switch to non-warped mode */ if (_xwin.hw_cursor_ok) { _xwin.mouse_warped = 0; /* Move X-cursor to Allegro cursor. */ XLOCK(); XWarpPointer(_xwin.display, _xwin.window, _xwin.window, 0, 0, _xwin.window_width, _xwin.window_height, _mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0), _mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0)); XUNLOCK(); } } #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR /* _xwin_set_mouse_sprite: * Set custom X cursor (if supported). */ int _xwin_set_mouse_sprite(struct BITMAP *sprite, int xfocus, int yfocus) { #define GET_PIXEL_DATA(depth, getpix) \ case depth: \ c = 0; \ for (iy = 0; iy < sprite->h; iy++) { \ for(ix = 0; ix < sprite->w; ix++) { \ col = getpix(sprite, ix, iy); \ if (col == (MASK_COLOR_ ## depth)) { \ r = g = b = a = 0; \ } \ else { \ r = getr ## depth(col); \ g = getg ## depth(col); \ b = getb ## depth(col); \ a = 255; \ } \ _xwin.xcursor_image->pixels[c++] = \ (a<<24)|(r<<16)|(g<<8)|(b); \ } \ } if (!_xwin.support_argb_cursor) { return -1; } if (_xwin.xcursor_image != None) { XLOCK(); XcursorImageDestroy(_xwin.xcursor_image); XUNLOCK(); _xwin.xcursor_image = None; } if (sprite) { int ix, iy; int r = 0, g = 0, b = 0, a = 0, c, col; _xwin.xcursor_image = XcursorImageCreate(sprite->w, sprite->h); if (_xwin.xcursor_image == None) { return -1; } switch (bitmap_color_depth(sprite)) { GET_PIXEL_DATA(8, _getpixel) break; GET_PIXEL_DATA(15, _getpixel15) break; GET_PIXEL_DATA(16, _getpixel16) break; GET_PIXEL_DATA(24, _getpixel24) break; GET_PIXEL_DATA(32, _getpixel32) break; } /* End switch */ _xwin.xcursor_image->xhot = xfocus; _xwin.xcursor_image->yhot = yfocus; return 0; } return -1; #undef GET_PIXEL_DATA } /* _xwin_show_mouse: * Show the custom X cursor (if supported) */ int _xwin_show_mouse(struct BITMAP *bmp, int x, int y) { /* Only draw on screen */ if (!is_same_bitmap(bmp, screen)) return -1; if (!_xwin.support_argb_cursor) { return -1; } if (_xwin.xcursor_image == None) { return -1; } /* Hardware cursor is disabled (mickey mode) */ if (!_xwin.hw_cursor_ok) { return -1; } XLOCK(); if (_xwin.cursor != None) { XUndefineCursor(_xwin.display, _xwin.window); XFreeCursor(_xwin.display, _xwin.cursor); } _xwin.cursor = XcursorImageLoadCursor(_xwin.display, _xwin.xcursor_image); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); XUNLOCK(); return 0; } /* _xwin_hide_mouse: * Hide the custom X cursor (if supported) */ void _xwin_hide_mouse(void) { if (_xwin.support_argb_cursor) { XLOCK(); _xwin_hide_x_mouse(); XUNLOCK(); } return; } /* _xwin_move_mouse: * Get mouse move notification. Not that we need it... */ void _xwin_move_mouse(int x, int y) { } #endif /* ALLEGRO_XWINDOWS_WITH_XCURSOR */ /* * Functions for copying screen data to frame buffer. */ static void _xwin_private_fast_colorconv(int sx, int sy, int sw, int sh) { GRAPHICS_RECT src_rect, dest_rect; /* set up source and destination rectangles */ src_rect.height = sh; src_rect.width = sw; src_rect.pitch = _xwin.screen_line[1] - _xwin.screen_line[0]; src_rect.data = _xwin.screen_line[sy] + sx * BYTES_PER_PIXEL(_xwin.screen_depth); dest_rect.height = sh; dest_rect.width = sw; dest_rect.pitch = _xwin.buffer_line[1] - _xwin.buffer_line[0]; dest_rect.data = _xwin.buffer_line[sy] + sx * BYTES_PER_PIXEL(_xwin.fast_visual_depth); /* Update frame buffer with screen contents. */ ASSERT(blitter_func); blitter_func(&src_rect, &dest_rect); } #ifdef ALLEGRO_LITTLE_ENDIAN #define DEFAULT_RGB_R_POS_24 (DEFAULT_RGB_R_SHIFT_24/8) #define DEFAULT_RGB_G_POS_24 (DEFAULT_RGB_G_SHIFT_24/8) #define DEFAULT_RGB_B_POS_24 (DEFAULT_RGB_B_SHIFT_24/8) #elif defined ALLEGRO_BIG_ENDIAN #define DEFAULT_RGB_R_POS_24 (2-DEFAULT_RGB_R_SHIFT_24/8) #define DEFAULT_RGB_G_POS_24 (2-DEFAULT_RGB_G_SHIFT_24/8) #define DEFAULT_RGB_B_POS_24 (2-DEFAULT_RGB_B_SHIFT_24/8) #else #error endianess not defined #endif #define MAKE_FAST_TRUECOLOR(name,stype,dtype,rshift,gshift,bshift,rmask,gmask,bmask) \ static void name(int sx, int sy, int sw, int sh) \ { \ int y, x; \ for (y = sy; y < (sy + sh); y++) { \ stype *s = (stype*) (_xwin.screen_line[y]) + sx; \ dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \ for (x = sw - 1; x >= 0; x--) { \ unsigned long color = *s++; \ *d++ = (_xwin.rmap[(color >> (rshift)) & (rmask)] \ | _xwin.gmap[(color >> (gshift)) & (gmask)] \ | _xwin.bmap[(color >> (bshift)) & (bmask)]); \ } \ } \ } #define MAKE_FAST_TRUECOLOR24(name,dtype) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + 3 * sx; \ dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \ for (x = sw - 1; x >= 0; s += 3, x--) { \ *d++ = (_xwin.rmap[s[DEFAULT_RGB_R_POS_24]] \ | _xwin.gmap[s[DEFAULT_RGB_G_POS_24]] \ | _xwin.bmap[s[DEFAULT_RGB_B_POS_24]]); \ } \ } \ } #define MAKE_FAST_TRUECOLOR_TO24(name,stype,rshift,gshift,bshift,rmask,gmask,bmask) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ stype *s = (stype*) (_xwin.screen_line[y]) + sx; \ unsigned char *d = _xwin.buffer_line[y] + 3 * sx; \ for (x = sw - 1; x >= 0; d += 3, x--) { \ unsigned long color = *s++; \ color = (_xwin.rmap[(color >> (rshift)) & (rmask)] \ | _xwin.gmap[(color >> (gshift)) & (gmask)] \ | _xwin.bmap[(color >> (bshift)) & (bmask)]); \ WRITE3BYTES(d, color); \ } \ } \ } #define MAKE_FAST_TRUECOLOR24_TO24(name) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + 3 * sx; \ unsigned char *d = _xwin.buffer_line[y] + 3 * sx; \ for (x = sw - 1; x >= 0; s += 3, d += 3, x--) { \ unsigned long color = _xwin.rmap[s[DEFAULT_RGB_R_POS_24]] \ | _xwin.gmap[s[DEFAULT_RGB_G_POS_24]] \ | _xwin.bmap[s[DEFAULT_RGB_B_POS_24]]; \ WRITE3BYTES(d, color); \ } \ } \ } MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_8_to_8, unsigned char, unsigned char, 0, 0, 0, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_8_to_16, unsigned char, unsigned short, 0, 0, 0, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_8_to_32, unsigned char, uint32_t, 0, 0, 0, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_15_to_8, unsigned short, unsigned char, 0, 5, 10, 0x1F, 0x1F, 0x1F); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_15_to_16, unsigned short, unsigned short, 0, 5, 10, 0x1F, 0x1F, 0x1F); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_15_to_32, unsigned short, uint32_t, 0, 5, 10, 0x1F, 0x1F, 0x1F); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_16_to_8, unsigned short, unsigned char, 0, 5, 11, 0x1F, 0x3F, 0x1F); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_16_to_16, unsigned short, unsigned short, 0, 5, 11, 0x1F, 0x3F, 0x1F); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_16_to_32, unsigned short, uint32_t, 0, 5, 11, 0x1F, 0x3F, 0x1F); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_32_to_8, uint32_t, unsigned char, 0, 8, 16, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_32_to_16, uint32_t, unsigned short, 0, 8, 16, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR(_xwin_private_fast_truecolor_32_to_32, uint32_t, uint32_t, 0, 8, 16, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR24(_xwin_private_fast_truecolor_24_to_8, unsigned char); MAKE_FAST_TRUECOLOR24(_xwin_private_fast_truecolor_24_to_16, unsigned short); MAKE_FAST_TRUECOLOR24(_xwin_private_fast_truecolor_24_to_32, uint32_t); MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_8_to_24, unsigned char, 0, 0, 0, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_15_to_24, unsigned short, 0, 5, 10, 0x1F, 0x1F, 0x1F); MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_16_to_24, unsigned short, 0, 5, 11, 0x1F, 0x3F, 0x1F); MAKE_FAST_TRUECOLOR_TO24(_xwin_private_fast_truecolor_32_to_24, uint32_t, 0, 8, 16, 0xFF, 0xFF, 0xFF); MAKE_FAST_TRUECOLOR24_TO24(_xwin_private_fast_truecolor_24_to_24); #define MAKE_FAST_PALETTE8(name,dtype) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + sx; \ dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \ for (x = sw - 1; x >= 0; x--) { \ unsigned long color = *s++; \ *d++ = _xwin.cmap[(_xwin.rmap[color] \ | _xwin.gmap[color] \ | _xwin.bmap[color])]; \ } \ } \ } #define MAKE_FAST_PALETTE(name,stype,dtype,rshift,gshift,bshift) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ stype *s = (stype*) (_xwin.screen_line[y]) + sx; \ dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \ for (x = sw - 1; x >= 0; x--) { \ unsigned long color = *s++; \ *d++ = _xwin.cmap[((((color >> (rshift)) & 0x0F) << 8) \ | (((color >> (gshift)) & 0x0F) << 4) \ | ((color >> (bshift)) & 0x0F))]; \ } \ } \ } #define MAKE_FAST_PALETTE24(name,dtype) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + 3 * sx; \ dtype *d = (dtype*) (_xwin.buffer_line[y]) + sx; \ for (x = sw - 1; x >= 0; s += 3, x--) { \ *d++ = _xwin.cmap[((((unsigned long) s[DEFAULT_RGB_R_POS_24] << 4) & 0xF00) \ | ((unsigned long) s[DEFAULT_RGB_G_POS_24] & 0xF0) \ | (((unsigned long) s[DEFAULT_RGB_B_POS_24] >> 4) & 0x0F))];\ } \ } \ } MAKE_FAST_PALETTE8(_xwin_private_fast_palette_8_to_8, unsigned char); MAKE_FAST_PALETTE8(_xwin_private_fast_palette_8_to_16, unsigned short); MAKE_FAST_PALETTE8(_xwin_private_fast_palette_8_to_32, uint32_t); MAKE_FAST_PALETTE(_xwin_private_fast_palette_15_to_8, unsigned short, unsigned char, 1, 6, 11); MAKE_FAST_PALETTE(_xwin_private_fast_palette_15_to_16, unsigned short, unsigned short, 1, 6, 11); MAKE_FAST_PALETTE(_xwin_private_fast_palette_15_to_32, unsigned short, uint32_t, 1, 6, 11); MAKE_FAST_PALETTE(_xwin_private_fast_palette_16_to_8, unsigned short, unsigned char, 1, 7, 12); MAKE_FAST_PALETTE(_xwin_private_fast_palette_16_to_16, unsigned short, unsigned short, 1, 7, 12); MAKE_FAST_PALETTE(_xwin_private_fast_palette_16_to_32, unsigned short, uint32_t, 1, 7, 12); MAKE_FAST_PALETTE(_xwin_private_fast_palette_32_to_8, uint32_t, unsigned char, 4, 12, 20); MAKE_FAST_PALETTE(_xwin_private_fast_palette_32_to_16, uint32_t, unsigned short, 4, 12, 20); MAKE_FAST_PALETTE(_xwin_private_fast_palette_32_to_32, uint32_t, uint32_t, 4, 12, 20); MAKE_FAST_PALETTE24(_xwin_private_fast_palette_24_to_8, unsigned char); MAKE_FAST_PALETTE24(_xwin_private_fast_palette_24_to_16, unsigned short); MAKE_FAST_PALETTE24(_xwin_private_fast_palette_24_to_32, uint32_t); #define MAKE_SLOW_TRUECOLOR(name,stype,rshift,gshift,bshift,rmask,gmask,bmask) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ stype *s = (stype*) (_xwin.screen_line[y]) + sx; \ for (x = sx; x < (sx + sw); x++) { \ unsigned long color = *s++; \ XPutPixel (_xwin.ximage, x, y, \ (_xwin.rmap[(color >> (rshift)) & (rmask)] \ | _xwin.gmap[(color >> (gshift)) & (gmask)] \ | _xwin.bmap[(color >> (bshift)) & (bmask)])); \ } \ } \ } #define MAKE_SLOW_TRUECOLOR24(name) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + 3 * sx; \ for (x = sx; x < (sx + sw); s += 3, x++) { \ XPutPixel(_xwin.ximage, x, y, \ (_xwin.rmap[s[DEFAULT_RGB_R_POS_24]] \ | _xwin.gmap[s[DEFAULT_RGB_G_POS_24]] \ | _xwin.bmap[s[DEFAULT_RGB_B_POS_24]])); \ } \ } \ } MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_8, unsigned char, 0, 0, 0, 0xFF, 0xFF, 0xFF); MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_15, unsigned short, 0, 5, 10, 0x1F, 0x1F, 0x1F); MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_16, unsigned short, 0, 5, 11, 0x1F, 0x3F, 0x1F); MAKE_SLOW_TRUECOLOR(_xwin_private_slow_truecolor_32, uint32_t, 0, 8, 16, 0xFF, 0xFF, 0xFF); MAKE_SLOW_TRUECOLOR24(_xwin_private_slow_truecolor_24); #define MAKE_SLOW_PALETTE8(name) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + sx; \ for (x = sx; x < (sx + sw); x++) { \ unsigned long color = *s++; \ XPutPixel(_xwin.ximage, x, y, \ _xwin.cmap[(_xwin.rmap[color] \ | _xwin.gmap[color] \ | _xwin.bmap[color])]); \ } \ } \ } #define MAKE_SLOW_PALETTE(name,stype,rshift,gshift,bshift) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ stype *s = (stype*) (_xwin.screen_line[y]) + sx; \ for (x = sx; x < (sx + sw); x++) { \ unsigned long color = *s++; \ XPutPixel(_xwin.ximage, x, y, \ _xwin.cmap[((((color >> (rshift)) & 0x0F) << 8) \ | (((color >> (gshift)) & 0x0F) << 4) \ | ((color >> (bshift)) & 0x0F))]); \ } \ } \ } #define MAKE_SLOW_PALETTE24(name) \ static void name(int sx, int sy, int sw, int sh) \ { \ int x, y; \ for (y = sy; y < (sy + sh); y++) { \ unsigned char *s = _xwin.screen_line[y] + 3 * sx; \ for (x = sx; x < (sx + sw); s += 3, x++) { \ XPutPixel(_xwin.ximage, x, y, \ _xwin.cmap[((((unsigned long) s[DEFAULT_RGB_R_POS_24] << 4) & 0xF00) \ | ((unsigned long) s[DEFAULT_RGB_G_POS_24] & 0xF0) \ | (((unsigned long) s[DEFAULT_RGB_B_POS_24] >> 4) & 0x0F))]); \ } \ } \ } MAKE_SLOW_PALETTE8(_xwin_private_slow_palette_8); MAKE_SLOW_PALETTE(_xwin_private_slow_palette_15, unsigned short, 1, 6, 11); MAKE_SLOW_PALETTE(_xwin_private_slow_palette_16, unsigned short, 1, 7, 12); MAKE_SLOW_PALETTE(_xwin_private_slow_palette_32, uint32_t, 4, 12, 20); MAKE_SLOW_PALETTE24(_xwin_private_slow_palette_24); /* * Functions for setting "hardware" colors in 8bpp modes. */ static void _xwin_private_set_matching_colors(AL_CONST PALETTE p, int from, int to) { int i; static XColor color[256]; for (i = from; i <= to; i++) { color[i].flags = DoRed | DoGreen | DoBlue; color[i].pixel = i; color[i].red = ((p[i].r & 0x3F) * 65535L) / 0x3F; color[i].green = ((p[i].g & 0x3F) * 65535L) / 0x3F; color[i].blue = ((p[i].b & 0x3F) * 65535L) / 0x3F; } XStoreColors(_xwin.display, _xwin.colormap, color + from, to - from + 1); } static void _xwin_private_set_truecolor_colors(AL_CONST PALETTE p, int from, int to) { int i, rmax, gmax, bmax; rmax = _xwin.rsize - 1; gmax = _xwin.gsize - 1; bmax = _xwin.bsize - 1; for (i = from; i <= to; i++) { _xwin.rmap[i] = (((p[i].r & 0x3F) * rmax) / 0x3F) << _xwin.rshift; _xwin.gmap[i] = (((p[i].g & 0x3F) * gmax) / 0x3F) << _xwin.gshift; _xwin.bmap[i] = (((p[i].b & 0x3F) * bmax) / 0x3F) << _xwin.bshift; } } static void _xwin_private_set_palette_colors(AL_CONST PALETTE p, int from, int to) { int i; for (i = from; i <= to; i++) { _xwin.rmap[i] = (((p[i].r & 0x3F) * 15) / 0x3F) << 8; _xwin.gmap[i] = (((p[i].g & 0x3F) * 15) / 0x3F) << 4; _xwin.bmap[i] = (((p[i].b & 0x3F) * 15) / 0x3F); } } static void _xwin_private_set_palette_range(AL_CONST PALETTE p, int from, int to) { RGB *pal; int c; unsigned char temp; if (_xwin.set_colors != 0) { if (blitter_func) { if (use_bgr_palette_hack && (from >= 0) && (to < 256)) { pal = _AL_MALLOC_ATOMIC(sizeof(RGB)*256); ASSERT(pal); ASSERT(p); if (!pal || !p) return; /* ... in shame and disgrace */ memcpy(&pal[from], &p[from], sizeof(RGB)*(to-from+1)); for (c = from; c <= to; c++) { temp = pal[c].r; pal[c].r = pal[c].b; pal[c].b = temp; } _set_colorconv_palette(pal, from, to); _AL_FREE(pal); } else { _set_colorconv_palette(p, from, to); } } /* Set "hardware" colors. */ (*(_xwin.set_colors))(p, from, to); /* Update XImage and window. */ if (!_xwin.matching_formats) _xwin_private_update_screen(0, 0, _xwin.virtual_width, _xwin.virtual_height); } } void _xwin_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) { if (vsync) { _xwin_vsync(); } XLOCK(); _xwin_private_set_palette_range(p, from, to); XUNLOCK(); } /* _xwin_set_window_defaults: * Set default window parameters. */ static void _xwin_private_set_window_defaults(void) { XClassHint hint; XWMHints wm_hints; if (_xwin.wm_window == None) return; /* Set window title. */ XStoreName(_xwin.display, _xwin.wm_window, _xwin.window_title); /* Set hints. */ hint.res_name = _xwin.application_name; hint.res_class = _xwin.application_class; XSetClassHint(_xwin.display, _xwin.wm_window, &hint); wm_hints.flags = InputHint | StateHint | WindowGroupHint; wm_hints.input = True; wm_hints.initial_state = NormalState; wm_hints.window_group = _xwin.wm_window; #ifdef ALLEGRO_XWINDOWS_WITH_XPM if (allegro_icon) { wm_hints.flags |= IconPixmapHint | IconMaskHint; XpmCreatePixmapFromData(_xwin.display, _xwin.wm_window, allegro_icon, &wm_hints.icon_pixmap, &wm_hints.icon_mask, NULL); } #endif XSetWMHints(_xwin.display, _xwin.wm_window, &wm_hints); } /* _xwin_flush_buffers: * Flush input and output X-buffers. */ static void _xwin_private_flush_buffers(void) { if (_xwin.display != 0) XSync(_xwin.display, False); } void _xwin_flush_buffers(void) { XLOCK(); _xwin_private_flush_buffers(); XUNLOCK(); } /* _xwin_vsync: * Emulation of vsync. */ void _xwin_vsync(void) { if (_timer_installed) { int prev = retrace_count; XLOCK(); XSync(_xwin.display, False); XUNLOCK(); do { rest(1); } while (retrace_count == prev); } else { /* This does not wait for the VBI - but it waits until X11 has * synchronized, i.e. until actual changes are visible. So it * has a similar effect. */ XLOCK(); XSync(_xwin.display, False); XUNLOCK(); } } /* _xwin_process_event: * Process one event. */ static void _xwin_private_process_event(XEvent *event) { int dx, dy, dz = 0, dw = 0; static int mouse_buttons = 0; static int mouse_savedx = 0; static int mouse_savedy = 0; static int mouse_warp_now = 0; static int mouse_was_warped = 0; switch (event->type) { case KeyPress: _xwin_keyboard_handler(&event->xkey, FALSE); break; case KeyRelease: _xwin_keyboard_handler(&event->xkey, FALSE); break; case FocusIn: _switch_in(); _xwin_keyboard_focus_handler(&event->xfocus); break; case FocusOut: _switch_out(); _xwin_keyboard_focus_handler(&event->xfocus); break; case ButtonPress: /* Mouse button pressed. */ if (event->xbutton.button == Button1) mouse_buttons |= 1; else if (event->xbutton.button == Button3) mouse_buttons |= 2; else if (event->xbutton.button == Button2) mouse_buttons |= 4; else if (event->xbutton.button == Button4) { dz = 1; } else if (event->xbutton.button == Button5) { dz = -1; } else if (event->xbutton.button == 6) { dw = -1; } else if (event->xbutton.button == 7) { dw = 1; } else if (event->xbutton.button == 8) mouse_buttons |= 8; else if (event->xbutton.button == 9) mouse_buttons |= 16; if (_xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(0, 0, dz, dw, mouse_buttons); break; case ButtonRelease: /* Mouse button released. */ if (event->xbutton.button == Button1) mouse_buttons &= ~1; else if (event->xbutton.button == Button3) mouse_buttons &= ~2; else if (event->xbutton.button == Button2) mouse_buttons &= ~4; else if (event->xbutton.button == 8) mouse_buttons &= ~8; else if (event->xbutton.button == 9) mouse_buttons &= ~16; if (_xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons); break; case MotionNotify: /* Mouse moved. */ dx = event->xmotion.x - mouse_savedx; dy = event->xmotion.y - mouse_savedy; /* Discard some events after warp. */ if (mouse_was_warped && ((dx != 0) || (dy != 0)) && (mouse_was_warped++ < 16)) break; mouse_savedx = event->xmotion.x; mouse_savedy = event->xmotion.y; mouse_was_warped = 0; if (!_xwin.mouse_warped) { /* Move Allegro cursor to X-cursor. */ dx = event->xmotion.x - (_mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0)); dy = event->xmotion.y - (_mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0)); } if (((dx != 0) || (dy != 0)) && _xwin_mouse_interrupt) { if (_xwin.mouse_warped && (mouse_warp_now++ & 4)) { /* Warp X-cursor to the center of the window. */ mouse_savedx = _xwin.window_width / 2; mouse_savedy = _xwin.window_height / 2; mouse_was_warped = 1; XWarpPointer(_xwin.display, _xwin.window, _xwin.window, 0, 0, _xwin.window_width, _xwin.window_height, mouse_savedx, mouse_savedy); } /* Move Allegro cursor. */ (*_xwin_mouse_interrupt)(dx, dy, 0, 0, mouse_buttons); } break; case EnterNotify: /* Mouse entered window. */ _mouse_on = TRUE; _xwin_mouse_enter_notify(); mouse_savedx = event->xcrossing.x; mouse_savedy = event->xcrossing.y; mouse_was_warped = 0; if (!_xwin.mouse_warped) { /* Move Allegro cursor to X-cursor. */ dx = event->xcrossing.x - (_mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0)); dy = event->xcrossing.y - (_mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0)); if (((dx != 0) || (dy != 0)) && _xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(dx, dy, 0, 0, mouse_buttons); } else if (_xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons); break; case LeaveNotify: _mouse_on = FALSE; if (_xwin_mouse_interrupt) (*_xwin_mouse_interrupt)(0, 0, 0, 0, mouse_buttons); _xwin_mouse_leave_notify(); break; case Expose: /* Request to redraw part of the window. */ (*_xwin_window_redrawer)(event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); break; case MappingNotify: /* Keyboard mapping changed. */ if (event->xmapping.request == MappingKeyboard) _xwin_get_keyboard_mapping(); break; case ClientMessage: /* Window close request */ if ((Atom)event->xclient.data.l[0] == wm_delete_window) { if (_xwin.close_button_callback) _xwin.close_button_callback(); } break; } } /* _xwin_handle_input: * Handle events from the queue. */ void _xwin_private_handle_input(void) { int i, events, events_queued; static XEvent event[X_MAX_EVENTS + 1]; /* +1 for possible extra event, see below. */ if (_xwin.display == 0) return; /* Switch mouse to non-warped mode if mickeys were not used recently (~2 seconds). */ if (_xwin.mouse_warped && (_xwin.mouse_warped++ > MOUSE_WARP_DELAY)) { _xwin.mouse_warped = 0; /* Move X-cursor to Allegro cursor. */ XWarpPointer(_xwin.display, _xwin.window, _xwin.window, 0, 0, _xwin.window_width, _xwin.window_height, _mouse_x - (_xwin_mouse_extended_range ? _xwin.scroll_x : 0), _mouse_y - (_xwin_mouse_extended_range ? _xwin.scroll_y : 0)); } /* Flush X-buffers. */ _xwin_private_flush_buffers(); /* How much events are available in the queue. */ events = events_queued = XEventsQueued(_xwin.display, QueuedAlready); if (events <= 0) return; /* Limit amount of events we read at once. */ if (events > X_MAX_EVENTS) events = X_MAX_EVENTS; /* Read pending events. */ for (i = 0; i < events; i++) XNextEvent(_xwin.display, &event[i]); /* Can't have a KeyRelease as last event, since it might be only half * of a key repeat pair. Also see comment below. */ if (events_queued > events && event[i - 1].type == KeyRelease) { XNextEvent(_xwin.display, &event[i]); events++; } /* Process all events. */ for (i = 0; i < events; i++) { /* Hack to make Allegro's key[] array work despite of key repeat. * If a KeyRelease is sent at the same time as a KeyPress following * it with the same keycode, we ignore the release event. */ if (event[i].type == KeyRelease && (i + 1) < events) { if (event[i + 1].type == KeyPress) { if (event[i].xkey.keycode == event[i + 1].xkey.keycode && event[i].xkey.time == event[i + 1].xkey.time) continue; } } _xwin_private_process_event(&event[i]); } } void _xwin_handle_input(void) { #ifndef ALLEGRO_MULTITHREADED if (_xwin.lock_count) { ++_xwin_missed_input; return; } #endif XLOCK(); if (_xwin_input_handler) _xwin_input_handler(); else _xwin_private_handle_input(); XUNLOCK(); } /* _xwin_set_warped_mouse_mode: * Switch mouse handling into warped mode. */ static void _xwin_private_set_warped_mouse_mode(int permanent) { /* Don't enable warp mode if the hardware cursor is being displayed */ if (!_xwin.hw_cursor_ok) _xwin.mouse_warped = ((permanent) ? 1 : (MOUSE_WARP_DELAY*7/8)); } void _xwin_set_warped_mouse_mode(int permanent) { XLOCK(); _xwin_private_set_warped_mouse_mode(permanent); XUNLOCK(); } /* _xwin_redraw_window: * Redraws part of the window. */ static void _xwin_private_redraw_window(int x, int y, int w, int h) { if (_xwin.window == None) return; /* Clip updated region. */ if (x >= _xwin.screen_width) return; if (x < 0) { w += x; x = 0; } if (w >= (_xwin.screen_width - x)) w = _xwin.screen_width - x; if (w <= 0) return; if (y >= _xwin.screen_height) return; if (y < 0) { h += y; y = 0; } if (h >= (_xwin.screen_height - y)) h = _xwin.screen_height - y; if (h <= 0) return; if (!_xwin.ximage) XFillRectangle(_xwin.display, _xwin.window, _xwin.gc, x, y, w, h); else { #ifdef ALLEGRO_XWINDOWS_WITH_SHM if (_xwin.use_shm) XShmPutImage(_xwin.display, _xwin.window, _xwin.gc, _xwin.ximage, x + _xwin.scroll_x, y + _xwin.scroll_y, x, y, w, h, False); else #endif XPutImage(_xwin.display, _xwin.window, _xwin.gc, _xwin.ximage, x + _xwin.scroll_x, y + _xwin.scroll_y, x, y, w, h); } } void _xwin_redraw_window(int x, int y, int w, int h) { _xwin_lock(NULL); (*_xwin_window_redrawer)(x, y, w, h); _xwin_unlock(NULL); } /* _xwin_scroll_screen: * Scroll visible screen in window. */ static int _xwin_private_scroll_screen(int x, int y) { _xwin.scroll_x = x; _xwin.scroll_y = y; (*_xwin_window_redrawer)(0, 0, _xwin.screen_width, _xwin.screen_height); _xwin_private_flush_buffers(); return 0; } int _xwin_scroll_screen(int x, int y) { int result; if (x < 0) x = 0; else if (x >= (_xwin.virtual_width - _xwin.screen_width)) x = _xwin.virtual_width - _xwin.screen_width; if (y < 0) y = 0; else if (y >= (_xwin.virtual_height - _xwin.screen_height)) y = _xwin.virtual_height - _xwin.screen_height; if ((_xwin.scroll_x == x) && (_xwin.scroll_y == y)) return 0; _xwin_lock(NULL); result = _xwin_private_scroll_screen(x, y); _xwin_unlock(NULL); return result; } /* _xwin_update_screen: * Update part of the screen. */ static void _xwin_private_update_screen(int x, int y, int w, int h) { /* Update frame buffer with screen contents. */ if (_xwin.screen_to_buffer != 0) { /* Clip updated region. */ if (x >= _xwin.virtual_width) return; if (x < 0) { w += x; x = 0; } if (w >= (_xwin.virtual_width - x)) w = _xwin.virtual_width - x; if (w <= 0) return; if (y >= _xwin.virtual_height) return; if (y < 0) { h += y; y = 0; } if (h >= (_xwin.virtual_height - y)) h = _xwin.virtual_height - y; if (h <= 0) return; (*(_xwin.screen_to_buffer))(x, y, w, h); } /* Update window. */ (*_xwin_window_redrawer)(x - _xwin.scroll_x, y - _xwin.scroll_y, w, h); } void _xwin_update_screen(int x, int y, int w, int h) { _xwin_lock(NULL); _xwin_private_update_screen(x, y, w, h); _xwin_unlock(NULL); } /* _xwin_set_window_title: * Wrapper for XStoreName. */ static void _xwin_private_set_window_title(AL_CONST char *name) { if (!name) _al_sane_strncpy(_xwin.window_title, XWIN_DEFAULT_WINDOW_TITLE, sizeof(_xwin.window_title)); else _al_sane_strncpy(_xwin.window_title, name, sizeof(_xwin.window_title)); if (_xwin.wm_window != None) XStoreName(_xwin.display, _xwin.wm_window, _xwin.window_title); } void _xwin_set_window_title(AL_CONST char *name) { XLOCK(); _xwin_private_set_window_title(name); XUNLOCK(); } /* _xwin_sysdrv_set_window_name: * Sets window name and group. */ static void _xwin_private_set_window_name(AL_CONST char *name, AL_CONST char *group) { XClassHint hint; if (!name) _al_sane_strncpy(_xwin.application_name, XWIN_DEFAULT_APPLICATION_NAME, sizeof(_xwin.application_name)); else _al_sane_strncpy(_xwin.application_name, name, sizeof(_xwin.application_name)); if (!group) _al_sane_strncpy(_xwin.application_class, XWIN_DEFAULT_APPLICATION_CLASS, sizeof(_xwin.application_class)); else _al_sane_strncpy(_xwin.application_class, group, sizeof(_xwin.application_class)); if (_xwin.window != None) { hint.res_name = _xwin.application_name; hint.res_class = _xwin.application_class; XSetClassHint(_xwin.display, _xwin.window, &hint); } } void xwin_set_window_name(AL_CONST char *name, AL_CONST char *group) { char tmp1[128], tmp2[128]; do_uconvert(name, U_CURRENT, tmp1, U_ASCII, sizeof(tmp1)); do_uconvert(group, U_CURRENT, tmp2, U_ASCII, sizeof(tmp2)); XLOCK(); _xwin_private_set_window_name(tmp1, tmp2); XUNLOCK(); } /* _xwin_get_pointer_mapping: * Wrapper for XGetPointerMapping. */ static int _xwin_private_get_pointer_mapping(unsigned char map[], int nmap) { return ((_xwin.display == 0) ? -1 : XGetPointerMapping(_xwin.display, map, nmap)); } int _xwin_get_pointer_mapping(unsigned char map[], int nmap) { int num; XLOCK(); num = _xwin_private_get_pointer_mapping(map, nmap); XUNLOCK(); return num; } /* _xwin_write_line: * Update last selected line and select new line. */ uintptr_t _xwin_write_line(BITMAP *bmp, int line) { int new_line = line + bmp->y_ofs; if ((new_line != _xwin_last_line) && (!_xwin_in_gfx_call) && (_xwin_last_line >= 0)) _xwin_update_screen(0, _xwin_last_line, _xwin.virtual_width, 1); _xwin_last_line = new_line; return (uintptr_t) (bmp->line[line]); } /* _xwin_unwrite_line: * Update last selected line. */ void _xwin_unwrite_line(BITMAP *bmp) { if ((!_xwin_in_gfx_call) && (_xwin_last_line >= 0)) _xwin_update_screen(0, _xwin_last_line, _xwin.virtual_width, 1); _xwin_last_line = -1; } /* * Support for XF86VidMode extension. */ #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE /* qsort comparison function for sorting the modes */ static int cmpmodes(const void *va, const void *vb) { const XF86VidModeModeInfo *a = *(const XF86VidModeModeInfo **)va; const XF86VidModeModeInfo *b = *(const XF86VidModeModeInfo **)vb; if (a->hdisplay == b->hdisplay) return b->vdisplay - a->vdisplay; else return b->hdisplay - a->hdisplay; } /* _xvidmode_private_set_fullscreen: * Attempt to switch to a better matching video mode. * Matching code for non exact match (smallest bigger res) rather shamelessly * taken from SDL. */ static void _xvidmode_private_set_fullscreen(int w, int h, int *vidmode_width, int *vidmode_height) { int vid_event_base, vid_error_base; int vid_major_version, vid_minor_version; int i; /* Test that display is local. */ if (!_xwin_private_display_is_local()) return; /* Test for presence of VidMode extension. */ if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base, &vid_error_base) || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version, &vid_minor_version)) return; /* Get list of modelines. */ if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, &_xwin.num_modes, &_xwin.modesinfo)) return; /* Remember the mode to restore. */ _xwin.orig_modeinfo = _xwin.modesinfo[0]; /* Search for an exact matching video mode. */ for (i = 0; i < _xwin.num_modes; i++) { if ((_xwin.modesinfo[i]->hdisplay == w) && (_xwin.modesinfo[i]->vdisplay == h)) break; } /* Search for a non exact match (smallest bigger res). */ if (i == _xwin.num_modes) { int best_width = 0, best_height = 0; qsort(_xwin.modesinfo, _xwin.num_modes, sizeof(void *), cmpmodes); for (i = _xwin.num_modes-1; i > 0; i--) { if (!best_width) { if ((_xwin.modesinfo[i]->hdisplay >= w) && (_xwin.modesinfo[i]->vdisplay >= h)) { best_width = _xwin.modesinfo[i]->hdisplay; best_height = _xwin.modesinfo[i]->vdisplay; } } else { if ((_xwin.modesinfo[i]->hdisplay != best_width) || (_xwin.modesinfo[i]->vdisplay != best_height)) { i++; break; } } } } /* Switch video mode. */ if ((_xwin.modesinfo[i] == _xwin.orig_modeinfo) || !XF86VidModeSwitchToMode(_xwin.display, _xwin.screen, _xwin.modesinfo[i])) { *vidmode_width = _xwin.orig_modeinfo->hdisplay; *vidmode_height = _xwin.orig_modeinfo->vdisplay; _xwin.orig_modeinfo = NULL; } else { *vidmode_width = _xwin.modesinfo[i]->hdisplay; *vidmode_height = _xwin.modesinfo[i]->vdisplay; /* Only kept / set for compatibility with apps which check this. */ _xwin.mode_switched = 1; } /* Lock mode switching. */ XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True); /* Set viewport. */ XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0); } /* free_modelines: * Free mode lines. */ static void free_modelines(XF86VidModeModeInfo **modesinfo, int num_modes) { int i; for (i = 0; i < num_modes; i++) if (modesinfo[i]->privsize > 0) XFree(modesinfo[i]->private); XFree(modesinfo); } /* _xvidmode_private_unset_fullscreen: * Restore original video mode and window attributes. */ static void _xvidmode_private_unset_fullscreen(void) { if (_xwin.num_modes > 0) { /* Unlock mode switching. */ XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False); if (_xwin.orig_modeinfo) { /* Restore the original video mode. */ XF86VidModeSwitchToMode(_xwin.display, _xwin.screen, _xwin.orig_modeinfo); _xwin.orig_modeinfo = 0; /* only kept / set for compatibility with apps which check this */ _xwin.mode_switched = 0; } /* Free modelines. */ free_modelines(_xwin.modesinfo, _xwin.num_modes); _xwin.num_modes = 0; _xwin.modesinfo = 0; } } #endif /* _xwin_private_fetch_mode_list: * Generates a list of valid video modes. */ static GFX_MODE_LIST *_xwin_private_fetch_mode_list(void) { int num_modes = 1, num_bpp = 0; GFX_MODE_LIST *mode_list; int i, j; #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE int has_vidmode = 0; int vid_event_base, vid_error_base; int vid_major_version, vid_minor_version; XF86VidModeModeInfo **modesinfo; /* Test that display is local. */ if (_xwin_private_display_is_local() && /* Test for presence of VidMode extension. */ XF86VidModeQueryExtension(_xwin.display, &vid_event_base, &vid_error_base) && XF86VidModeQueryVersion(_xwin.display, &vid_major_version, &vid_minor_version) && /* Get list of modelines. */ XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, &num_modes, &modesinfo)) has_vidmode = 1; #endif /* Calculate the number of color depths we have to support. */ #ifdef ALLEGRO_COLOR8 num_bpp++; #endif #ifdef ALLEGRO_COLOR16 num_bpp += 2; /* 15, 16 */ #endif #ifdef ALLEGRO_COLOR24 num_bpp++; #endif #ifdef ALLEGRO_COLOR32 num_bpp++; #endif if (num_bpp == 0) /* ha! */ return 0; /* Allocate space for mode list. */ mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) { #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE if (has_vidmode) free_modelines(modesinfo, num_modes); #endif return 0; } mode_list->mode = _AL_MALLOC(sizeof(GFX_MODE) * ((num_modes * num_bpp) + 1)); if (!mode_list->mode) { _AL_FREE(mode_list); #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE if (has_vidmode) free_modelines(modesinfo, num_modes); #endif return 0; } /* Fill in mode list. */ j = 0; for (i = 0; i < num_modes; i++) { #define ADD_SCREEN_MODE(BPP) \ mode_list->mode[j].width = DisplayWidth(_xwin.display, _xwin.screen); \ mode_list->mode[j].height = DisplayHeight(_xwin.display, _xwin.screen); \ mode_list->mode[j].bpp = BPP; \ j++ #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE #define ADD_VIDMODE_MODE(BPP) \ mode_list->mode[j].width = modesinfo[i]->hdisplay; \ mode_list->mode[j].height = modesinfo[i]->vdisplay; \ mode_list->mode[j].bpp = BPP; \ j++ #define ADD_MODE(BPP) \ if (has_vidmode) { \ ADD_VIDMODE_MODE(BPP); \ } else { \ ADD_SCREEN_MODE(BPP); \ } #else #define ADD_MODE(BPP) ADD_SCREEN_MODE(BPP) #endif #ifdef ALLEGRO_COLOR8 ADD_MODE(8); #endif #ifdef ALLEGRO_COLOR16 ADD_MODE(15); ADD_MODE(16); #endif #ifdef ALLEGRO_COLOR24 ADD_MODE(24); #endif #ifdef ALLEGRO_COLOR32 ADD_MODE(32); #endif } mode_list->mode[j].width = 0; mode_list->mode[j].height = 0; mode_list->mode[j].bpp = 0; mode_list->num_modes = j; #ifdef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE if (has_vidmode) free_modelines(modesinfo, num_modes); #endif return mode_list; } /* _xwin_fetch_mode_list: * Fetch mode list. */ GFX_MODE_LIST *_xwin_fetch_mode_list(void) { GFX_MODE_LIST *list; XLOCK(); list = _xwin_private_fetch_mode_list(); XUNLOCK(); return list; } /* Hook functions */ int (*_xwin_window_creator)(void) = &_xwin_private_create_window; void (*_xwin_window_defaultor)(void) = &_xwin_private_set_window_defaults; void (*_xwin_window_redrawer)(int, int, int, int) = &_xwin_private_redraw_window; void (*_xwin_input_handler)(void) = 0; void (*_xwin_keyboard_callback)(int, int) = 0; allegro-4.4.3.1/src/x/xwins.s0000664000175000017500000000243413437077643014675 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * X-windows bank switching code. These routines will be called * with a line number in %eax and a pointer to the bitmap in %edx. * The bank switcher should select the appropriate bank for the * line, and replace %eax with a pointer to the start of the line. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro/platform/alunixac.h" #include "../i386/asmdefs.inc" .text #ifndef ALLEGRO_NO_ASM /* Use only with ASM calling convention. */ FUNC(_xwin_write_line_asm) pushl %ecx pushl %eax pushl %edx call GLOBL(_xwin_write_line) popl %edx popl %ecx /* preserve %eax */ popl %ecx ret FUNC(_xwin_unwrite_line_asm) pushl %ecx pushl %eax pushl %edx call GLOBL(_xwin_unwrite_line) popl %edx popl %eax popl %ecx ret #endif allegro-4.4.3.1/src/x/xdga2s.s0000664000175000017500000000257113437077643014717 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DGA2 bank switching code. These routines will be called * with a line number in %eax and a pointer to the bitmap in %edx. * The bank switcher should select the appropriate bank for the * line, and replace %eax with a pointer to the start of the line. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro/platform/alunixac.h" #include "../i386/asmdefs.inc" .text #if (!defined ALLEGRO_NO_ASM) && (defined ALLEGRO_XWINDOWS_WITH_XF86DGA2) #if (!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE) FUNC (_xdga2_write_line_asm) /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked pushl %ecx pushl %eax pushl %edx call GLOBL(_xdga2_lock) popl %edx popl %eax popl %ecx Locked: /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret #endif #endif allegro-4.4.3.1/src/vtable32.c0000664000175000017500000000460713437077643014664 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Table of functions for drawing onto 32 bit linear bitmaps. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_COLOR32 void _linear_draw_sprite32_end(void); void _linear_blit32_end(void); GFX_VTABLE __linear_vtable32 = { 32, MASK_COLOR_32, _stub_unbank_switch, NULL, NULL, NULL, NULL, NULL, _linear_getpixel32, _linear_putpixel32, _linear_vline32, _linear_hline32, _linear_hline32, _normal_line, _fast_line, _normal_rectfill, _soft_triangle, _linear_draw_sprite32, _linear_draw_256_sprite32, _linear_draw_sprite_v_flip32, _linear_draw_sprite_h_flip32, _linear_draw_sprite_vh_flip32, _linear_draw_trans_sprite32, _linear_draw_trans_sprite32, _linear_draw_lit_sprite32, _linear_draw_rle_sprite32, _linear_draw_trans_rle_sprite32, _linear_draw_trans_rle_sprite32, _linear_draw_lit_rle_sprite32, _linear_draw_character32, _linear_draw_glyph32, _linear_blit32, _linear_blit32, _linear_blit32, _linear_blit32, _linear_blit32, _linear_blit32, _linear_blit_backward32, _blit_between_formats, _linear_masked_blit32, _linear_clear_to_color32, _pivot_scaled_sprite_flip, NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) _soft_draw_gouraud_sprite, _linear_draw_sprite32_end, _linear_blit32_end, _soft_polygon, _soft_rect, _soft_circle, _soft_circlefill, _soft_ellipse, _soft_ellipsefill, _soft_arc, _soft_spline, _soft_floodfill, _soft_polygon3d, _soft_polygon3d_f, _soft_triangle3d, _soft_triangle3d_f, _soft_quad3d, _soft_quad3d_f, _linear_draw_sprite_ex32 }; #endif allegro-4.4.3.1/src/dispsw.c0000664000175000017500000002716413437077643014556 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Display switching interface. * * By George Foot. * * State saving routines added by Shawn Hargreaves. * * Switch callbacks support added by Lorenzo Petrone, * based on code by Stefan Schimanski. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_DOS static int switch_mode = SWITCH_NONE; #else static int switch_mode = SWITCH_PAUSE; #endif /* remember things about the way our bitmaps are set up */ typedef struct BITMAP_INFORMATION { BITMAP *bmp; /* the bitmap */ BITMAP *other; /* replacement during switches */ struct BITMAP_INFORMATION *sibling; /* linked list of siblings */ struct BITMAP_INFORMATION *child; /* tree of sub-bitmaps */ void *acquire, *release; /* need to bodge the vtable, too */ int blit_on_restore; /* whether the bitmap contents need to be copied back */ } BITMAP_INFORMATION; static BITMAP_INFORMATION *info_list = NULL; int _dispsw_status = SWITCH_NONE; #define MAX_SWITCH_CALLBACKS 8 static void (*switch_in_cb[MAX_SWITCH_CALLBACKS])(void) = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static void (*switch_out_cb[MAX_SWITCH_CALLBACKS])(void) = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* set_display_switch_mode: * Sets the display switch mode. Returns zero and unregisters * all callbacks on success, returns non-zero on failure. */ int set_display_switch_mode(int mode) { int ret, i; if ((!system_driver)) return -1; /* platforms that don't support switching allow SWITCH_NONE */ if (!system_driver->set_display_switch_mode) { if (mode == SWITCH_NONE) return 0; else return -1; } ret = system_driver->set_display_switch_mode(mode); if (ret == 0) { /* unregister all callbacks */ for (i=0; iset_display_switch_mode)) return -1; for (i=0; ibmp == bmp) { *head_ret = head; return info; } if (info->child) { kid = find_switch_bitmap(&info->child, bmp, head_ret); if (kid) return kid; } head = &info->sibling; info = *head; } return NULL; } /* _register_switch_bitmap: * Lists this bitmap as an interesting thing to remember during console * switches. */ void _register_switch_bitmap(BITMAP *bmp, BITMAP *parent) { BITMAP_INFORMATION *info, *parent_info, **head; if (system_driver->display_switch_lock) system_driver->display_switch_lock(TRUE, FALSE); if (parent) { /* add a sub-bitmap */ parent_info = find_switch_bitmap(&info_list, parent, &head); if (!parent_info) goto getout; info = _AL_MALLOC(sizeof(BITMAP_INFORMATION)); if (!info) goto getout; info->bmp = bmp; info->other = NULL; info->sibling = parent_info->child; info->child = NULL; info->acquire = NULL; info->release = NULL; info->blit_on_restore = FALSE; parent_info->child = info; } else { /* add a new top-level bitmap: must be in the foreground for this! */ ASSERT(_dispsw_status == SWITCH_NONE); info = _AL_MALLOC(sizeof(BITMAP_INFORMATION)); if (!info) goto getout; info->bmp = bmp; info->other = NULL; info->sibling = info_list; info->child = NULL; info->acquire = NULL; info->release = NULL; info->blit_on_restore = FALSE; info_list = info; } getout: if (system_driver->display_switch_lock) system_driver->display_switch_lock(FALSE, FALSE); } /* _unregister_switch_bitmap: * Removes a bitmap from the list of things that need to be saved. */ void _unregister_switch_bitmap(BITMAP *bmp) { BITMAP_INFORMATION *info, **head; if (system_driver->display_switch_lock) system_driver->display_switch_lock(TRUE, FALSE); info = find_switch_bitmap(&info_list, bmp, &head); if (!info) goto getout; /* all the sub-bitmaps should be destroyed before we get to here */ ASSERT(!info->child); /* it's not cool to destroy things that have important state */ ASSERT(!info->other); *head = info->sibling; _AL_FREE(info); getout: if (system_driver->display_switch_lock) system_driver->display_switch_lock(FALSE, FALSE); } /* reconstruct_kids: * Recursive helper to rebuild any sub-bitmaps to point at their new * parents. */ static void reconstruct_kids(BITMAP *parent, BITMAP_INFORMATION *info) { int x, y, i; while (info) { info->bmp->vtable = parent->vtable; info->bmp->write_bank = parent->write_bank; info->bmp->read_bank = parent->read_bank; info->bmp->seg = parent->seg; info->bmp->id = parent->id | BMP_ID_SUB; x = info->bmp->x_ofs - parent->x_ofs; y = info->bmp->y_ofs - parent->y_ofs; if (is_planar_bitmap(info->bmp)) x /= 4; x *= BYTES_PER_PIXEL(bitmap_color_depth(info->bmp)); for (i=0; ibmp->h; i++) info->bmp->line[i] = parent->line[y+i] + x; reconstruct_kids(info->bmp, info->child); info = info->sibling; } } /* fudge_bitmap: * Makes b2 be similar to b1 (duplicate clip settings, ID, etc). */ static void fudge_bitmap(BITMAP *b1, BITMAP *b2, int copy) { int s, x1, y1, x2, y2; set_clip_state(b2, FALSE); if (copy) blit(b1, b2, 0, 0, 0, 0, b1->w, b1->h); get_clip_rect(b1, &x1, &y1, &x2, &y2); s = get_clip_state(b1); set_clip_rect(b2, x1, y1, x2, y2); set_clip_state(b2, s); } /* swap_bitmap_contents: * Now remember boys and girls, don't try this at home! */ static void swap_bitmap_contents(BITMAP *b1, BITMAP *b2) { int size = sizeof(BITMAP) + sizeof(char *) * b1->h; unsigned char *s = (unsigned char *)b1; unsigned char *d = (unsigned char *)b2; unsigned char t; int c; for (c=0; cother = create_bitmap_ex(bitmap_color_depth(info->bmp), info->bmp->w, info->bmp->h); if (!info->other) return; copy = (switch_mode != SWITCH_AMNESIA) && (switch_mode != SWITCH_BACKAMNESIA); fudge_bitmap(info->bmp, info->other, copy); info->blit_on_restore = copy; info->acquire = info->other->vtable->acquire; info->release = info->other->vtable->release; info->other->vtable->acquire = info->bmp->vtable->acquire; info->other->vtable->release = info->bmp->vtable->release; #define INTERESTING_ID_BITS (BMP_ID_VIDEO | BMP_ID_SYSTEM | \ BMP_ID_SUB | BMP_ID_MASK) info->other->id = (info->bmp->id & INTERESTING_ID_BITS) | (info->other->id & ~INTERESTING_ID_BITS); swap_bitmap_contents(info->bmp, info->other); } /* _save_switch_state: * Saves the graphics state before a console switch. */ void _save_switch_state(int switch_mode) { BITMAP_INFORMATION *info = info_list; int hadmouse; if (!screen) return; if (_al_linker_mouse && is_same_bitmap(*(_al_linker_mouse->mouse_screen_ptr), screen)) { _al_linker_mouse->show_mouse(NULL); hadmouse = TRUE; } else hadmouse = FALSE; while (info) { save_bitmap_state(info, switch_mode); reconstruct_kids(info->bmp, info->child); info = info->sibling; } _dispsw_status = switch_mode; if (hadmouse) _al_linker_mouse->show_mouse(screen); } /* restore_bitmap_state: * The King's Men are quite good at doing this with bitmaps... */ static void restore_bitmap_state(BITMAP_INFORMATION *info) { if (info->other) { swap_bitmap_contents(info->other, info->bmp); info->other->vtable->acquire = info->acquire; info->other->vtable->release = info->release; info->other->id &= ~INTERESTING_ID_BITS; fudge_bitmap(info->other, info->bmp, info->blit_on_restore); destroy_bitmap(info->other); info->other = NULL; } else clear_bitmap(info->bmp); } /* _restore_switch_state: * Restores the graphics state after a console switch. */ void _restore_switch_state(void) { BITMAP_INFORMATION *info = info_list; int hadmouse, hadtimer; if (!screen) return; if (_al_linker_mouse && is_same_bitmap(*(_al_linker_mouse->mouse_screen_ptr), screen)) { _al_linker_mouse->show_mouse(NULL); hadmouse = TRUE; } else hadmouse = FALSE; hadtimer = _timer_installed; _timer_installed = FALSE; while (info) { restore_bitmap_state(info); reconstruct_kids(info->bmp, info->child); info = info->sibling; } _dispsw_status = SWITCH_NONE; if (bitmap_color_depth(screen) == 8) { if (_got_prev_current_palette) gfx_driver->set_palette(_prev_current_palette, 0, 255, FALSE); else gfx_driver->set_palette(_current_palette, 0, 255, FALSE); } if (hadmouse) _al_linker_mouse->show_mouse(screen); _timer_installed = hadtimer; } allegro-4.4.3.1/src/readfont.c0000664000175000017500000001055513437077643015043 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Top level font reading routines. * * By Evert Glebbeek. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" typedef struct FONT_TYPE_INFO { char *ext; FONT *(*load)(AL_CONST char *filename, RGB *pal, void *param); struct FONT_TYPE_INFO *next; } FONT_TYPE_INFO; static FONT_TYPE_INFO *font_type_list = NULL; /* register_font_file_type: * Informs Allegro of a new font file type, telling it how to load files of * this format. */ void register_font_file_type(AL_CONST char *ext, FONT *(*load)(AL_CONST char *filename, RGB *pal, void *param)) { char tmp[32], *aext; FONT_TYPE_INFO *iter = font_type_list; aext = uconvert_toascii(ext, tmp); if (strlen(aext) == 0) return; if (!iter) iter = font_type_list = _AL_MALLOC(sizeof(struct FONT_TYPE_INFO)); else { for (iter = font_type_list; iter->next; iter = iter->next); iter = iter->next = _AL_MALLOC(sizeof(struct FONT_TYPE_INFO)); } if (iter) { iter->load = load; iter->ext = _al_strdup(aext); iter->next = NULL; } } /* load_font: * Loads a font from disk. Will try to load a font from a bitmap if all else * fails. */ FONT *load_font(AL_CONST char *filename, RGB *pal, void *param) { char tmp[32], *aext; FONT_TYPE_INFO *iter; ASSERT(filename); aext = uconvert_toascii(get_extension(filename), tmp); for (iter = font_type_list; iter; iter = iter->next) { if (stricmp(iter->ext, aext) == 0) { if (iter->load) return iter->load(filename, pal, param); return NULL; } } /* Try to load the file as a bitmap image and grab the font from there */ return load_bitmap_font(filename, pal, param); } /* register_font_file_type_exit: * Free list of registered bitmap file types. */ static void register_font_file_type_exit(void) { FONT_TYPE_INFO *iter = font_type_list, *next; while (iter) { next = iter->next; _AL_FREE(iter->ext); _AL_FREE(iter); iter = next; } font_type_list = NULL; /* If we are using a destructor, then we only want to prune the list * down to valid modules. So we clean up as usual, but then reinstall * the internal modules. */ #ifdef ALLEGRO_USE_CONSTRUCTOR _register_font_file_type_init(); #endif _remove_exit_func(register_font_file_type_exit); } /* _register_font_file_type_init: * Register built-in font file types. */ void _register_font_file_type_init(void) { char buf[32]; _add_exit_func(register_font_file_type_exit, "register_font_file_type_exit"); register_font_file_type(uconvert_ascii("dat", buf), load_dat_font); register_font_file_type(uconvert_ascii("fnt", buf), load_grx_or_bios_font); register_font_file_type(uconvert_ascii("txt", buf), load_txt_font); } #ifdef ALLEGRO_USE_CONSTRUCTOR CONSTRUCTOR_FUNCTION(static void font_filetype_constructor(void)); DESTRUCTOR_FUNCTION(static void font_filetype_destructor(void)); /* font_filetype_constructor: * Register font filetype functions if this object file is linked * in. This isn't called if the load_font() function isn't used * in a program, thus saving a little space in statically linked * programs. */ void font_filetype_constructor(void) { _register_font_file_type_init(); } /* font_filetype_destructor: * Since we only want to destroy the whole list when we *actually* * quit, not just when allegro_exit() is called, we need to use a * destructor to accomplish this. */ static void font_filetype_destructor(void) { FONT_TYPE_INFO *iter = font_type_list, *next; while (iter) { next = iter->next; _AL_FREE(iter->ext); _AL_FREE(iter); iter = next; } font_type_list = NULL; _remove_exit_func(register_font_file_type_exit); } #endif allegro-4.4.3.1/src/fontgrx.c0000664000175000017500000000540413437077643014725 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * * GRX font file reader by Mark Wodrich. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* magic number for GRX format font files */ #define FONTMAGIC 0x19590214L /* load_grx_font: * Loads a GRX font from the file named filename. The palette and param * parameters are ignored by this function. */ FONT *load_grx_font(AL_CONST char *filename, RGB *pal, void *param) { PACKFILE *pack; FONT *f; FONT_MONO_DATA *mf; FONT_GLYPH **gl; int w, h, num, i; int* wtab = 0; ASSERT(filename); pack = pack_fopen(filename, F_READ); if (!pack) return NULL; if (pack_igetl(pack) != FONTMAGIC) { pack_fclose(pack); return NULL; } pack_igetl(pack); f = _AL_MALLOC(sizeof(FONT)); mf = _AL_MALLOC(sizeof(FONT_MONO_DATA)); f->data = mf; f->vtable = font_vtable_mono; mf->next = NULL; w = pack_igetw(pack); h = pack_igetw(pack); f->height = h; mf->begin = pack_igetw(pack); mf->end = pack_igetw(pack) + 1; num = mf->end - mf->begin; gl = mf->glyphs = _AL_MALLOC(sizeof(FONT_GLYPH*) * num); if (pack_igetw(pack) == 0) { for (i = 0; i < 38; i++) pack_getc(pack); wtab = _AL_MALLOC_ATOMIC(sizeof(int) * num); for (i = 0; i < num; i++) wtab[i] = pack_igetw(pack); } else { for (i = 0; i < 38; i++) pack_getc(pack); } for(i = 0; i < num; i++) { int sz; if (wtab) w = wtab[i]; sz = ((w + 7) / 8) * h; gl[i] = _AL_MALLOC(sizeof(FONT_GLYPH) + sz); gl[i]->w = w; gl[i]->h = h; pack_fread(gl[i]->dat, sz, pack); } pack_fclose(pack); if (wtab) _AL_FREE(wtab); return f; } /* load_grx_or_bios_font: * Loads a GRX or bios font from the file named filename. */ FONT *load_grx_or_bios_font(AL_CONST char *filename, RGB *pal, void *param) { PACKFILE *f; FONT *font = NULL; char tmp[16]; int id; ASSERT(filename); if (ustricmp(get_extension(filename), uconvert_ascii("fnt", tmp)) == 0) { f = pack_fopen(filename, F_READ); if (!f) return NULL; id = pack_igetl(f); pack_fclose(f); if (id == FONTMAGIC) font = load_grx_font(filename, pal, param); else font = load_bios_font(filename, pal, param); } return font; } allegro-4.4.3.1/src/readbmp.c0000664000175000017500000001455013437077643014652 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Top level bitmap reading routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" typedef struct BITMAP_TYPE_INFO { char *ext; BITMAP *(*load)(AL_CONST char *filename, RGB *pal); int (*save)(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal); struct BITMAP_TYPE_INFO *next; } BITMAP_TYPE_INFO; static BITMAP_TYPE_INFO *bitmap_type_list = NULL; /* register_bitmap_file_type: * Informs Allegro of a new image file type, telling it how to load and * save files of this format (either function may be NULL). */ void register_bitmap_file_type(AL_CONST char *ext, BITMAP *(*load)(AL_CONST char *filename, RGB *pal), int (*save)(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal)) { char tmp[32], *aext; BITMAP_TYPE_INFO *iter = bitmap_type_list; aext = uconvert_toascii(ext, tmp); if (strlen(aext) == 0) return; if (!iter) iter = bitmap_type_list = _AL_MALLOC(sizeof(struct BITMAP_TYPE_INFO)); else { for (iter = bitmap_type_list; iter->next; iter = iter->next); iter = iter->next = _AL_MALLOC(sizeof(struct BITMAP_TYPE_INFO)); } if (iter) { iter->load = load; iter->save = save; iter->ext = _al_strdup(aext); iter->next = NULL; } } /* load_bitmap: * Loads a bitmap from disk. */ BITMAP *load_bitmap(AL_CONST char *filename, RGB *pal) { char tmp[32], *aext; BITMAP_TYPE_INFO *iter; ASSERT(filename); aext = uconvert_toascii(get_extension(filename), tmp); for (iter = bitmap_type_list; iter; iter = iter->next) { if (stricmp(iter->ext, aext) == 0) { if (iter->load) return iter->load(filename, pal); return NULL; } } return NULL; } /* save_bitmap: * Writes a bitmap to disk. */ int save_bitmap(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) { char tmp[32], *aext; BITMAP_TYPE_INFO *iter; ASSERT(filename); ASSERT(bmp); aext = uconvert_toascii(get_extension(filename), tmp); for (iter = bitmap_type_list; iter; iter = iter->next) { if (stricmp(iter->ext, aext) == 0) { if (iter->save) return iter->save(filename, bmp, pal); return 1; } } return 1; } /* _fixup_loaded_bitmap: * Helper function for adjusting the color depth of a loaded image. * Converts the bitmap BMP to the color depth BPP. If BMP is a 8-bit * bitmap, PAL must be the palette attached to the bitmap. If BPP is * equal to 8, the conversion is performed either by building a palette * optimized for the bitmap if PAL is not NULL (in which case PAL gets * filled in with this palette) or by using the current palette if PAL * is NULL. In any other cases, PAL is unused. */ BITMAP *_fixup_loaded_bitmap(BITMAP *bmp, PALETTE pal, int bpp) { BITMAP *b2; ASSERT(bmp); b2 = create_bitmap_ex(bpp, bmp->w, bmp->h); if (!b2) { destroy_bitmap(bmp); return NULL; } if (bpp == 8) { RGB_MAP *old_map = rgb_map; if (pal) generate_optimized_palette(bmp, pal, NULL); else pal = _current_palette; rgb_map = _AL_MALLOC(sizeof(RGB_MAP)); if (rgb_map != NULL) create_rgb_table(rgb_map, pal, NULL); blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h); if (rgb_map != NULL) _AL_FREE(rgb_map); rgb_map = old_map; } else if (bitmap_color_depth(bmp) == 8) { select_palette(pal); blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h); unselect_palette(); } else { blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h); } destroy_bitmap(bmp); return b2; } /* register_bitmap_file_type_exit: * Free list of registered bitmap file types. */ static void register_bitmap_file_type_exit(void) { BITMAP_TYPE_INFO *iter = bitmap_type_list, *next; while (iter) { next = iter->next; _AL_FREE(iter->ext); _AL_FREE(iter); iter = next; } bitmap_type_list = NULL; /* If we are using a destructor, then we only want to prune the list * down to valid modules. So we clean up as usual, but then reinstall * the internal modules. */ #ifdef ALLEGRO_USE_CONSTRUCTOR _register_bitmap_file_type_init(); #endif _remove_exit_func(register_bitmap_file_type_exit); } /* _register_bitmap_file_type_init: * Register built-in bitmap file types. */ void _register_bitmap_file_type_init(void) { char buf[32]; _add_exit_func(register_bitmap_file_type_exit, "register_bitmap_file_type_exit"); register_bitmap_file_type(uconvert_ascii("bmp", buf), load_bmp, save_bmp); register_bitmap_file_type(uconvert_ascii("lbm", buf), load_lbm, NULL); register_bitmap_file_type(uconvert_ascii("pcx", buf), load_pcx, save_pcx); register_bitmap_file_type(uconvert_ascii("tga", buf), load_tga, save_tga); } #ifdef ALLEGRO_USE_CONSTRUCTOR CONSTRUCTOR_FUNCTION(static void bitmap_filetype_constructor(void)); DESTRUCTOR_FUNCTION(static void bitmap_filetype_destructor(void)); /* bitmap_filetype_constructor: * Register bitmap filetype functions if this object file is linked * in. This isn't called if the load_bitmap() and save_bitmap() * functions aren't used in a program, thus saving a little space * in statically linked programs. */ static void bitmap_filetype_constructor(void) { _register_bitmap_file_type_init(); } /* bitmap_filetype_destructor: * Since we only want to destroy the whole list when we *actually* * quit, not just when allegro_exit() is called, we need to use a * destructor to accomplish this. */ static void bitmap_filetype_destructor(void) { BITMAP_TYPE_INFO *iter = bitmap_type_list, *next; while (iter) { next = iter->next; _AL_FREE(iter->ext); _AL_FREE(iter); iter = next; } bitmap_type_list = NULL; _remove_exit_func(register_bitmap_file_type_exit); } #endif allegro-4.4.3.1/src/gsprite.c0000664000175000017500000001011513437077643014706 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Gouraud shaded sprite renderer. * * By Patrick Hogan. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* draw_gouraud_sprite: * Draws a lit or tinted sprite, interpolating the four corner colors * over the surface of the image. */ void _soft_draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4) { fixed mc1, mc2, mh; fixed lc, rc, hc; int x1 = x; int y1 = y; int x2 = x + sprite->w; int y2 = y + sprite->h; int i, j; int pixel; uintptr_t addr; ASSERT(bmp); ASSERT(sprite); ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); bmp_select(bmp); /* set up vertical gradients for left and right sides */ mc1 = itofix(c4 - c1) / sprite->h; mc2 = itofix(c3 - c2) / sprite->h; lc = itofix(c1); rc = itofix(c2); /* check clipping */ if (bmp->clip) { if (y1 < bmp->ct) { lc += mc1 * (bmp->ct - y1); rc += mc2 * (bmp->ct - y1); y1 = bmp->ct; } y2 = MIN(y2, bmp->cb); x1 = MAX(x1, bmp->cl); x2 = MIN(x2, bmp->cr); } for (j=y1; jw; hc = lc; /* more clip checking */ if ((bmp->clip) && (x < bmp->cl)) hc += mh * (bmp->cl - x); #ifdef ALLEGRO_GFX_HAS_VGA /* modex version */ if (is_planar_bitmap(bmp)) { addr = ((unsigned long)bmp->line[j]<<2) + x1; for (i=x1; iline[j-y][i-x]) { outportw(0x3C4, (0x100<<(i&3))|2); pixel = color_map->data[fixtoi(hc)][sprite->line[j-y][i-x]]; bmp_write8(addr>>2, pixel); } hc += mh; addr++; } } else { #else { #endif /* draw routines for all linear modes */ switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: addr = bmp_write_line(bmp, j) + x1; for (i=x1; iline[j-y][i-x]) { pixel = color_map->data[fixtoi(hc)][sprite->line[j-y][i-x]]; bmp_write8(addr, pixel); } hc += mh; addr++; } break; #endif #ifdef ALLEGRO_COLOR16 case 15: case 16: addr = bmp_write_line(bmp, j) + x1*sizeof(short); for (i=x1; iline[j-y])[i-x]; if (pixel != bmp->vtable->mask_color) { if (bitmap_color_depth(bmp) == 16) pixel = _blender_func16(pixel, _blender_col_16, fixtoi(hc)); else pixel = _blender_func15(pixel, _blender_col_15, fixtoi(hc)); bmp_write16(addr, pixel); } hc += mh; addr += sizeof(short); } break; #endif #ifdef ALLEGRO_COLOR24 case 24: addr = bmp_write_line(bmp, j) + x1*3; for (i=x1; iline[j-y] + (i-x)*3)); bmp_select(bmp); if (pixel != MASK_COLOR_24) { pixel = _blender_func24(pixel, _blender_col_24, fixtoi(hc)); bmp_write24(addr, pixel); } hc += mh; addr += 3; } break; #endif #ifdef ALLEGRO_COLOR32 case 32: addr = bmp_write_line(bmp, j) + x1*sizeof(int32_t); for (i=x1; iline[j-y])[i-x]; if (pixel != MASK_COLOR_32) { pixel = _blender_func32(pixel, _blender_col_32, fixtoi(hc)); bmp_write32(addr, pixel); } hc += mh; addr += sizeof(int32_t); } break; #endif } } lc += mc1; rc += mc2; } bmp_unwrite_line(bmp); } allegro-4.4.3.1/src/vtable15.c0000664000175000017500000000462213437077643014662 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Table of functions for drawing onto 15 bit linear bitmaps. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_COLOR16 void _linear_draw_sprite16_end(void); void _linear_blit16_end(void); GFX_VTABLE __linear_vtable15 = { 15, MASK_COLOR_15, _stub_unbank_switch, NULL, NULL, NULL, NULL, NULL, _linear_getpixel16, _linear_putpixel15, _linear_vline15, _linear_hline15, _linear_hline15, _normal_line, _fast_line, _normal_rectfill, _soft_triangle, _linear_draw_sprite16, _linear_draw_256_sprite16, _linear_draw_sprite_v_flip16, _linear_draw_sprite_h_flip16, _linear_draw_sprite_vh_flip16, _linear_draw_trans_sprite15, _linear_draw_trans_rgba_sprite15, _linear_draw_lit_sprite15, _linear_draw_rle_sprite15, _linear_draw_trans_rle_sprite15, _linear_draw_trans_rgba_rle_sprite15, _linear_draw_lit_rle_sprite15, _linear_draw_character16, _linear_draw_glyph16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit_backward16, _blit_between_formats, _linear_masked_blit16, _linear_clear_to_color16, _pivot_scaled_sprite_flip, NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) _soft_draw_gouraud_sprite, _linear_draw_sprite16_end, _linear_blit16_end, _soft_polygon, _soft_rect, _soft_circle, _soft_circlefill, _soft_ellipse, _soft_ellipsefill, _soft_arc, _soft_spline, _soft_floodfill, _soft_polygon3d, _soft_polygon3d_f, _soft_triangle3d, _soft_triangle3d_f, _soft_quad3d, _soft_quad3d_f, _linear_draw_sprite_ex16 }; #endif allegro-4.4.3.1/src/dataregi.c0000664000175000017500000000454313437077643015021 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Table of datafile loader routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* list of objects, and methods for loading and destroying them */ DATAFILE_TYPE _datafile_type[MAX_DATAFILE_TYPES] = { { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL }, { DAT_END, NULL, NULL } }; /* register_datafile_object: * Registers a custom datafile object, providing functions for loading * and destroying the objects. */ void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void (*destroy)(void *data)) { int i; /* replacing an existing type? */ for (i=0; i #include "allegro.h" #include "allegro/internal/aintern.h" typedef struct FLOODED_LINE /* store segments which have been flooded */ { short flags; /* status of the segment */ short lpos, rpos; /* left and right ends of segment */ short y; /* y coordinate of the segment */ int next; /* linked list if several per line */ } FLOODED_LINE; /* Note: a 'short' is not sufficient for 'next' above in some corner cases. */ static int flood_count; /* number of flooded segments */ #define FLOOD_IN_USE 1 #define FLOOD_TODO_ABOVE 2 #define FLOOD_TODO_BELOW 4 #define FLOOD_LINE(c) (((FLOODED_LINE *)_scratch_mem) + c) /* flooder: * Fills a horizontal line around the specified position, and adds it * to the list of drawn segments. Returns the first x coordinate after * the part of the line which it has dealt with. */ static int flooder(BITMAP *bmp, int x, int y, int src_color, int dest_color) { FLOODED_LINE *p; int left = 0, right = 0; unsigned long addr; int c; /* helper for doing checks in each color depth */ #define FLOODER(bits, size) \ { \ /* check start pixel */ \ if ((int)bmp_read##bits(addr+x*size) != src_color) \ return x+1; \ \ /* work left from starting point */ \ for (left=x-1; left>=bmp->cl; left--) { \ if ((int)bmp_read##bits(addr+left*size) != src_color) \ break; \ } \ \ /* work right from starting point */ \ for (right=x+1; rightcr; right++) { \ if ((int)bmp_read##bits(addr+right*size) != src_color) \ break; \ } \ } ASSERT(bmp); if (is_linear_bitmap(bmp)) { /* use direct access for linear bitmaps */ addr = bmp_read_line(bmp, y); bmp_select(bmp); switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: FLOODER(8, 1); break; #endif #ifdef ALLEGRO_COLOR16 case 15: case 16: FLOODER(16, sizeof(short)); break; #endif #ifdef ALLEGRO_COLOR24 case 24: FLOODER(24, 3); break; #endif #ifdef ALLEGRO_COLOR32 case 32: FLOODER(32, sizeof(int32_t)); break; #endif } bmp_unwrite_line(bmp); } else { /* have to use getpixel() for mode-X */ /* check start pixel */ if (getpixel(bmp, x, y) != src_color) return x+1; /* work left from starting point */ for (left=x-1; left>=bmp->cl; left--) if (getpixel(bmp, left, y) != src_color) break; /* work right from starting point */ for (right=x+1; rightcr; right++) if (getpixel(bmp, right, y) != src_color) break; } left++; right--; /* draw the line */ bmp->vtable->hfill(bmp, left, y, right, dest_color); /* store it in the list of flooded segments */ c = y; p = FLOOD_LINE(c); if (p->flags) { while (p->next) { c = p->next; p = FLOOD_LINE(c); } p->next = c = flood_count++; _grow_scratch_mem(sizeof(FLOODED_LINE) * flood_count); p = FLOOD_LINE(c); } p->flags = FLOOD_IN_USE; p->lpos = left; p->rpos = right; p->y = y; p->next = 0; if (y > bmp->ct) p->flags |= FLOOD_TODO_ABOVE; if (y+1 < bmp->cb) p->flags |= FLOOD_TODO_BELOW; return right+2; } /* check_flood_line: * Checks a line segment, using the scratch buffer is to store a list of * segments which have already been drawn in order to minimise the required * number of tests. */ static int check_flood_line(BITMAP *bmp, int y, int left, int right, int src_color, int dest_color) { int c; FLOODED_LINE *p; int ret = FALSE; while (left <= right) { c = y; for (;;) { p = FLOOD_LINE(c); if ((left >= p->lpos) && (left <= p->rpos)) { left = p->rpos+2; break; } c = p->next; if (!c) { left = flooder(bmp, left, y, src_color, dest_color); ret = TRUE; break; } } } return ret; } /* floodfill: * Fills an enclosed area (starting at point x, y) with the specified color. */ void _soft_floodfill(BITMAP *bmp, int x, int y, int color) { int src_color; int c, done; FLOODED_LINE *p; ASSERT(bmp); /* make sure we have a valid starting point */ if ((x < bmp->cl) || (x >= bmp->cr) || (y < bmp->ct) || (y >= bmp->cb)) return; acquire_bitmap(bmp); /* what color to replace? */ src_color = getpixel(bmp, x, y); if (src_color == color) { release_bitmap(bmp); return; } /* set up the list of flooded segments */ _grow_scratch_mem(sizeof(FLOODED_LINE) * bmp->cb); flood_count = bmp->cb; p = _scratch_mem; for (c=0; cflags & FLOOD_TODO_BELOW) { p->flags &= ~FLOOD_TODO_BELOW; if (check_flood_line(bmp, p->y+1, p->lpos, p->rpos, src_color, color)) { done = FALSE; p = FLOOD_LINE(c); } } /* check above the segment? */ if (p->flags & FLOOD_TODO_ABOVE) { p->flags &= ~FLOOD_TODO_ABOVE; if (check_flood_line(bmp, p->y-1, p->lpos, p->rpos, src_color, color)) { done = FALSE; /* special case shortcut for going backwards */ if ((c < bmp->cb) && (c > 0)) c -= 2; } } } } while (!done); release_bitmap(bmp); } allegro-4.4.3.1/src/scene3d.c0000664000175000017500000005177013437077643014571 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The 3D scene renderer. * * By Calin Andrian. * * Merging into Allegro and API changes by Bertrand Coconnier. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" /* hash tables divide the screen height in (up to) HASH_NUM parts */ #define HASH_NUM 256 /* each part is made of 2^HASH_SHIFT lines */ #define HASH_SHIFT 3 /* Consequently, scanline sorting algorithm can handle up to HASH_NUM * 2^HASH_SHIFT lines */ static POLYGON_EDGE *scene_edge = NULL, *scene_inact; static POLYGON_INFO *scene_poly = NULL; static int scene_nedge = 0, scene_maxedge = 0; static int scene_npoly = 0, scene_maxpoly = 0; static BITMAP *scene_bmp; static COLOR_MAP *scene_cmap; static int scene_alpha; static int last_x, scene_y; static uintptr_t scene_addr; static float last_z; static POLYGON_EDGE **hash = NULL; float scene_gap = 100.0; /* create_scene: * Allocate memory for a scene, nedge and npoly are your estimate of how * many edges and how many polygons you will render (you cannot get over * the limit specified here). * If you use same values in succesive calls, the space will be reused. * Returns negative numbers if allocations fail, zero on success. */ int create_scene(int nedge, int npoly) { if (nedge != scene_maxedge) { /* don't realloc, we don't need */ scene_maxedge = 0; /* the old data */ if (scene_edge) _AL_FREE(scene_edge); scene_edge = _AL_MALLOC(nedge * sizeof(POLYGON_EDGE)); if (!scene_edge) return -1; } if (npoly != scene_maxpoly) { scene_maxpoly = 0; if (scene_poly) _AL_FREE(scene_poly); scene_poly = _AL_MALLOC(npoly * sizeof(POLYGON_INFO)); if (!scene_poly) { _AL_FREE(scene_edge); scene_edge = NULL; return -2; } } if (!hash) { hash = _AL_MALLOC(HASH_NUM * sizeof(POLYGON_EDGE*)); if (!hash) { _AL_FREE(scene_edge); _AL_FREE(scene_poly); return -3; } } scene_maxedge = nedge; scene_maxpoly = npoly; return 0; } /* clear_scene: * Initializes a scene. The bitmap is the bitmap you will eventually render * on. */ void clear_scene(BITMAP* bmp) { int i; ASSERT(bmp); ASSERT(hash); scene_inact = NULL; scene_bmp = bmp; scene_nedge = scene_npoly = 0; for (i=0; ix < edge->x)) { prev = pos; pos = pos->next; } } else { int i; int empty = 1, first = 1; i = edge->top >> HASH_SHIFT; ASSERT(i < HASH_NUM); if (hash[i]) { pos = hash[i]; prev = pos->prev; empty = 0; } while ((pos) && (pos->top < edge->top)) { prev = pos; pos = pos->next; first = 0; } if (first || empty) hash[i] = edge; } edge->next = pos; edge->prev = prev; if (pos) pos->prev = edge; if (prev) { prev->next = edge; return list; } else return edge; } /* poly_plane: * Computes the plane's equation coefficients A, B, C, D, in the original * space (before projection) for perspective projection: * Axz + Byz + Cz + D = 0 * This routine changed by Bertrand Coconnier in order to handle coincident * vertices in the polygon (According to Ben Davis' hack in poly3d.c). * Now the function computes the polygon area in planes xy, yz, and xz in * order to obtain the polygon normal. Plane equation coefficients are * then computed. */ static void poly_plane(V3D *vtx[], POLYGON_INFO *poly, int vc) { int i; float d; /* Vertices are persp-projected. Plane equation must be computed in * the original space, so we have to "un-persp-project" vertices. */ float z0 = fixtof(vtx[0]->z); float x0 = fixtof(vtx[0]->x) * z0; /* "un-persp-projection" */ float y0 = fixtof(vtx[0]->y) * z0; /* "un-persp-projection" */ float z = fixtof(vtx[vc-1]->z); float x = fixtof(vtx[vc-1]->x) * z; /* "un-persp-projection" */ float y = fixtof(vtx[vc-1]->y) * z; /* "un-persp-projection" */ poly->a = (z0 + z) * (y - y0); /* area in plane yz */ poly->b = (x0 + x) * (z - z0); /* area in plane zx */ poly->c = (y0 + y) * (x - x0); /* area in plane xy */ for(i=1; iz); x = fixtof(vtx[i]->x) * z; y = fixtof(vtx[i]->y) * z; poly->a += (z0 + z) * (y0 - y); /* area in plane yz */ poly->b += (x0 + x) * (z0 - z); /* area in plane zx */ poly->c += (y0 + y) * (x0 - x); /* area in plane xy */ x0 = x; y0 = y; z0 = z; } /* dot product of the plane normal (poly->a, poly->b, poly->c) with * the vector (x, y, z) */ d = poly->a * x + poly->b * y + poly->c * z; /* prepare A, B, C for extracting 1/z */ if ((d < 1e-10) && (d > -1e-10)) { if (d >= 0) d = 1e-10; else d = -1e-10; } poly->a /= d; poly->b /= d; poly->c /= d; } /* poly_plane_f: * Floating point version of poly_plane. * See poly_plane comments. */ static void poly_plane_f(V3D_f *vtx[], POLYGON_INFO *poly, int vc) { int i; float d; float z0 = vtx[0]->z; float x0 = vtx[0]->x * z0; float y0 = vtx[0]->y * z0; float z = vtx[vc-1]->z; float x = vtx[vc-1]->x * z; float y = vtx[vc-1]->y * z; poly->a = (z0 + z) * (y - y0); poly->b = (x0 + x) * (z - z0); poly->c = (y0 + y) * (x - x0); for(i=1; iz; x = vtx[i]->x * z; y = vtx[i]->y * z; poly->a += (z0 + z) * (y0 - y); poly->b += (x0 + x) * (z0 - z); poly->c += (y0 + y) * (x0 - x); x0 = x; y0 = y; z0 = z; } d = poly->a * x + poly->b * y + poly->c * z; if ((d < 1e-10) && (d > -1e-10)) { if (d >= 0) d = 1e-10; else d = -1e-10; } poly->a /= d; poly->b /= d; poly->c /= d; } /* far_z: * Compares z values of the plane to which 'edge' belongs and the plane * of 'poly', in point x, y. * Returns true if 'edge' is farther than 'poly'. */ static int far_z(int y, POLYGON_EDGE *edge, POLYGON_INFO *poly) { float z1, z2, zd; z1 = edge->dat.z; /* z2 = 1/z of the plane in the point x, y */ z2 = poly->a * fixtof(edge->x) + poly->b * y + poly->c; zd = (z2 - z1) * scene_gap; if (zd > z1) return 1; if (zd < -z1) return 0; return (z2 - z1 + 100.0 * (poly->a - edge->poly->a) > 0); } /* init_poly: * Initializes different elements in the poly structure. */ static void init_poly(int type, POLYGON_INFO *poly) { static int flag_table[] = { INTERP_Z, INTERP_Z, INTERP_Z, INTERP_Z, INTERP_Z, INTERP_Z | INTERP_THRU, INTERP_Z | INTERP_THRU, INTERP_Z | INTERP_BLEND, INTERP_Z | INTERP_BLEND, INTERP_Z | INTERP_THRU | INTERP_BLEND, INTERP_Z | INTERP_THRU | INTERP_BLEND, INTERP_Z | INTERP_THRU | INTERP_TRANS, INTERP_Z | INTERP_THRU | INTERP_TRANS, INTERP_Z | INTERP_THRU | INTERP_TRANS, INTERP_Z | INTERP_THRU | INTERP_TRANS }; poly->alt_drawer = _optim_alternative_drawer; poly->inside = 0; type &= ~POLYTYPE_ZBUF; poly->flags |= flag_table[type]; if (poly->flags & POLYTYPE_ZBUF) { poly->flags |= INTERP_THRU; } poly->cmap = color_map; poly->alpha = _blender_alpha; if (bitmap_color_depth(scene_bmp) == 8) { poly->flags &= ~INTERP_BLEND; } else { if (poly->flags & INTERP_BLEND) { poly->b15 = _blender_col_15; poly->b16 = _blender_col_16; poly->b24 = _blender_col_24; poly->b32 = _blender_col_32; } } if ((type == POLYTYPE_FLAT) && (_drawing_mode != DRAW_MODE_SOLID)) { poly->flags |= INTERP_NOSOLID; poly->dmode = _drawing_mode; switch(_drawing_mode) { case DRAW_MODE_MASKED_PATTERN: poly->flags |= INTERP_THRU; case DRAW_MODE_COPY_PATTERN: case DRAW_MODE_SOLID_PATTERN: poly->dpat = _drawing_pattern; poly->xanchor = _drawing_x_anchor; poly->yanchor = _drawing_y_anchor; break; default: poly->flags |= INTERP_THRU; poly->dpat = NULL; poly->xanchor = poly->yanchor = 0; break; } } scene_npoly++; } /* scene_polygon3d: * Put a polygon in the rendering list. Nothing is really rendered at this * moment. Should be called between clear_scene() and render_scene(). * Unlike polygon3d(), the polygon may be concave or self-intersecting. * Shapes that penetrate one another may look OK, but they are not really * handled by this code. * Note that the texture is stored as a pointer only, and you should keep * the actual bitmap until render_scene(), where it is used. * Returns zero on success, or a negative number if the polygon won't be * rendered for lack of rendering routine. */ int scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[]) { int c; V3D *v1, *v2; POLYGON_EDGE *edge; POLYGON_INFO *poly; ASSERT(scene_nedge + vc <= scene_maxedge); ASSERT(scene_npoly < scene_maxpoly); edge = &scene_edge[scene_nedge]; poly = &scene_poly[scene_npoly]; /* set up the drawing mode */ poly->drawer = _get_scanline_filler(type, &poly->flags, &poly->info, texture, scene_bmp); if (!poly->drawer) return -1; init_poly(type, poly); poly->color = vtx[0]->c; poly_plane(vtx, poly, vc); v2 = vtx[vc-1]; /* fill the edge table */ for (c=0; cflags, scene_bmp)) { edge->poly = poly; scene_inact = _add_edge_hash(scene_inact, edge, FALSE); edge++; scene_nedge++; } } return 0; } /* scene_polygon3d_f: * Floating point version of scene_polygon3d. */ int scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[]) { int c; V3D_f *v1, *v2; POLYGON_EDGE *edge; POLYGON_INFO *poly; ASSERT(scene_nedge + vc <= scene_maxedge); ASSERT(scene_npoly < scene_maxpoly); edge = &scene_edge[scene_nedge]; poly = &scene_poly[scene_npoly]; /* set up the drawing mode */ poly->drawer = _get_scanline_filler(type, &poly->flags, &poly->info, texture, scene_bmp); if (!poly->drawer) return -1; init_poly(type, poly); poly->color = vtx[0]->c; poly_plane_f(vtx, poly, vc); v2 = vtx[vc-1]; /* fill the edge table */ for (c=0; cflags, scene_bmp)) { edge->poly = poly; scene_inact = _add_edge_hash(scene_inact, edge, FALSE); edge++; scene_nedge++; } } return 0; } /* scene_segment: * Draws a piece of the scanline, corresponding to a polygon. The start and * end values for x are taken from e01 and e02, the polygon style from poly. */ static void scene_segment(POLYGON_EDGE *e01, POLYGON_EDGE *e02, POLYGON_INFO *poly) { int x, w, gap, flags; fixed step, width; float w1, step_f; int x01 = fixceil(e01->x); int x02 = fixceil(e02->x); float z01 = e01->dat.z; POLYGON_EDGE *e1 = poly->left_edge; POLYGON_EDGE *e2 = poly->right_edge; POLYGON_SEGMENT *info = &poly->info, *dat1, *dat2; SCANLINE_FILLER drawer; if ((x01 < last_x) && (z01 < last_z)) x01 = last_x; if (scene_bmp->clip) { if (x01 < scene_bmp->cl) x01 = scene_bmp->cl; if (x02 > scene_bmp->cr) x02 = scene_bmp->cr; } if (x01 >= x02) return; if (!e2) { e2 = e02; while (e2 && (e2->poly != poly)) e2 = e2->next; if (!e2) return; poly->right_edge = e2; } x = fixceil(e1->x); w = fixceil(e2->x) - x; if (w <= 0) return; /* Subpixel and subtexel accuracy */ step = (x << 16) - e1->x; step_f = fixtof(step); width = e2->x - e1->x; w1 = 65536. / width; flags = poly->flags; dat1 = &e1->dat; dat2 = &e2->dat; if (flags & INTERP_FLAT) { info->c = poly->color; } else { if (flags & INTERP_1COL) { info->dc = fixdiv(dat2->c - dat1->c, width); info->c = dat1->c + fixmul(step, info->dc); } if (flags & INTERP_3COL) { info->dr = fixdiv(dat2->r - dat1->r, width); info->dg = fixdiv(dat2->g - dat1->g, width); info->db = fixdiv(dat2->b - dat1->b, width); info->r = dat1->r + fixmul(step, info->dr); info->g = dat1->g + fixmul(step, info->dg); info->b = dat1->b + fixmul(step, info->db); } if (flags & INTERP_FIX_UV) { info->du = fixdiv(dat2->u - dat1->u, width); info->dv = fixdiv(dat2->v - dat1->v, width); info->u = dat1->u + fixmul(step, info->du); info->v = dat1->v + fixmul(step, info->dv); } if (flags & INTERP_FLOAT_UV) { info->dfu = (dat2->fu - dat1->fu) * w1; info->dfv = (dat2->fv - dat1->fv) * w1; info->fu = dat1->fu + step_f * info->dfu; info->fv = dat1->fv + step_f * info->dfv; } } info->dz = (dat2->z - dat1->z) * w1; info->z = dat1->z + step_f * info->dz; if (x < x01) { gap = x01 - x; x = x01; w -= gap; _clip_polygon_segment_f(info, gap, poly->flags); } if (x + w >= x02) w = x02 - x; if (w <= 0) return; if ((flags & OPT_FLOAT_UV_TO_FIX) && (info->dz == 0)) { float z1 = 1. / info->z; info->u = info->fu * z1; info->v = info->fv * z1; info->du = info->dfu * z1; info->dv = info->dfv * z1; drawer = poly->alt_drawer; } else drawer = poly->drawer; color_map = poly->cmap; _blender_alpha = poly->alpha; if (flags & INTERP_BLEND) { _blender_col_15 = poly->b15; _blender_col_16 = poly->b16; _blender_col_24 = poly->b24; _blender_col_32 = poly->b32; } if (drawer == _poly_scanline_dummy) { if (flags & INTERP_NOSOLID) { drawing_mode(poly->dmode, poly->dpat, poly->xanchor, poly->yanchor); scene_bmp->vtable->hfill(scene_bmp, x, scene_y, x+w-1, poly->color); solid_mode(); } else scene_bmp->vtable->hfill(scene_bmp, x, scene_y, x+w-1, poly->color); } else { int dx = x * BYTES_PER_PIXEL(bitmap_color_depth(scene_bmp)); if (flags & INTERP_ZBUF) info->zbuf_addr = bmp_write_line(_zbuffer, scene_y) + x * sizeof(float); info->read_addr = bmp_read_line(scene_bmp, scene_y) + dx; drawer(scene_addr + dx, w, info); } } /* scene_trans_seg: * Checks whether p0 is visible either directly or through transparent * polygons on top of it. If it's visible, draws all the visible stack * with x values from e1 and e2. At entry, p is the top polygon. * Returns nonzero if something was drawn. */ static int scene_trans_seg(POLYGON_EDGE *e1, POLYGON_EDGE *e2, POLYGON_INFO *p0, POLYGON_INFO *p) { int c; if (!p) return 0; c = 1; while (1) { if (p == p0) c = 0; if (!(p->flags & INTERP_THRU) || !p->next) break; p = p->next; } if (c) return 0; /* p is first opaque or the very last */ while (p) { scene_segment(e1, e2, p); p = p->prev; } return 1; } /* render_scene: * Renders all the specified scene_polygon3d()'s on the bitmap passed to * clear_scene(). Rendering is done one scanline at a time, with no pixel * being processed more than once. Note that between clear_scene() and * render_scene() you shouldn't change the clip rectangle of the destination * bitmap. Also, all the textures passed to scene_polygon3d() are stored * as pointers only and actually used in render_scene(). */ void render_scene(void) { int p; #ifdef ALLEGRO_DOS int old87 = 0; #endif POLYGON_EDGE *edge, *start_edge = NULL; POLYGON_EDGE *active_edges = NULL, *last_edge = NULL; POLYGON_INFO *active_poly = NULL; ASSERT(scene_maxedge > 0); ASSERT(scene_maxpoly > 0); scene_cmap = color_map; scene_alpha = _blender_alpha; solid_mode(); /* set fpu to single-precision, truncate mode */ #ifdef ALLEGRO_DOS old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC); #endif acquire_bitmap(scene_bmp); bmp_select(scene_bmp); for (p=0; pct; scene_ycb; scene_y++) { scene_addr = bmp_write_line(scene_bmp, scene_y); /* check for newly active edges */ edge = scene_inact; while ((edge) && (edge->top == scene_y)) { POLYGON_EDGE *next_edge = edge->next; scene_inact = _remove_edge(scene_inact, edge); active_edges = _add_edge_hash(active_edges, edge, TRUE); edge = next_edge; } /* no edges on this line */ if (!active_edges) continue; /* fill the scanline */ last_x = INT_MIN; last_z = 0.0; for (edge=active_edges; edge; edge=edge->next) { int x = fixceil(edge->x); POLYGON_INFO *poly = edge->poly; /* one polygon changes status */ poly->inside = 1 - poly->inside; if (poly->inside) { POLYGON_INFO *pos = active_poly; POLYGON_INFO *prev = NULL; poly->left_edge = edge; poly->right_edge = NULL; /* find its place in the list */ while (pos && far_z(scene_y, edge, pos)) { prev = pos; pos = pos->next; } /* poly overlaps pos. Was pos visible ? */ if (scene_trans_seg(start_edge, edge, pos, active_poly)) { start_edge = edge; } /* link */ poly->next = pos; poly->prev = prev; if (pos) pos->prev = poly; if (prev) prev->next = poly; else { start_edge = edge; active_poly = poly; } } else { poly->right_edge = edge; /* poly ends here. Was it visible ? */ if (scene_trans_seg(start_edge, edge, poly, active_poly)) { start_edge = edge; if (x > last_x) { last_x = x; last_z = edge->dat.z; } } /* unlink */ if (poly->next) poly->next->prev = poly->prev; if (poly->prev) poly->prev->next = poly->next; else active_poly = poly->next; } /* prepare for backward scan */ last_edge = edge; } /* update edges, remove dead ones, re-sort */ edge = last_edge; active_edges = NULL; while (edge) { POLYGON_EDGE *prev_edge = edge->prev; if (scene_y < edge->bottom) { POLYGON_SEGMENT *dat = &edge->dat; int flags = edge->poly->flags; edge->x += edge->dx; dat->z += dat->dz; if (!(flags & INTERP_FLAT)) { if (flags & INTERP_1COL) dat->c += dat->dc; if (flags & INTERP_3COL) { dat->r += dat->dr; dat->g += dat->dg; dat->b += dat->db; } if (flags & INTERP_FIX_UV) { dat->u += dat->du; dat->v += dat->dv; } if (flags & INTERP_FLOAT_UV) { dat->fu += dat->dfu; dat->fv += dat->dfv; } } active_edges = _add_edge_hash(active_edges, edge, TRUE); } edge = prev_edge; } } bmp_unwrite_line(scene_bmp); release_bitmap(scene_bmp); /* reset fpu mode */ #ifdef ALLEGRO_DOS _control87(old87, MCW_PC | MCW_RC); #endif color_map = scene_cmap; _blender_alpha = scene_alpha; solid_mode(); /* mark the tables as full */ scene_nedge = scene_maxedge; scene_npoly = scene_maxpoly; } allegro-4.4.3.1/src/fontdat.c0000664000175000017500000000505013437077643014672 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Font loading routine for reading a font from a datafile. * * By Evert Glebbeek. * * See readme.txt for copyright information. */ #include #include "allegro.h" /* load_dat_font: * Loads a font from the datafile named filename. param can optionally be set * to a list of two strings, which you can use to load a specific font and * palette from a datafile by name. If pal is NULL, or the second string * argument is NULL, no palette information is returned. * If param is NULL, the first font found in the datafile will be returned * and the last palette found prior to the font will be returned. */ FONT *load_dat_font(AL_CONST char *filename, RGB *pal, void *param) { FONT *fnt; DATAFILE *df; RGB *p = NULL; char **names; int c, want_palette; ASSERT(filename); /* Load font and palette by name? */ names = param; fnt = NULL; p = NULL; /* Load font by name? */ if (names && names[0]) { df = load_datafile_object(filename, names[0]); if (!df) { return NULL; } fnt = df->dat; df->dat = NULL; unload_datafile_object(df); } /* Load palette by name? */ want_palette = TRUE; if (names && names[1]) { df = load_datafile_object(filename, names[1]); if (df) { memcpy(pal, df->dat, sizeof(PALETTE)); } unload_datafile_object(df); want_palette = FALSE; } if (!fnt || want_palette) { df = load_datafile(filename); if (!df) { return NULL; } for (c=0; df[c].type!=DAT_END; c++) { /* Only pick the last palette if no palette was named */ if (df[c].type==DAT_PALETTE && want_palette) p = df[c].dat; /* Only pick a font if no font was named */ if (df[c].type==DAT_FONT && !fnt) { fnt = df[c].dat; df[c].dat = NULL; break; } } if (p && pal && want_palette && fnt) { memcpy(pal, p, sizeof(PALETTE)); } unload_datafile(df); } return fnt; } allegro-4.4.3.1/src/quat.c0000664000175000017500000002661713437077643014221 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Quaternion manipulation routines. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include #include "allegro.h" #define FLOATSINCOS(x, s, c) _AL_SINCOS((x) * AL_PI / 128.0, s ,c) #define EPSILON (0.001) QUAT identity_quat = { 1.0, 0.0, 0.0, 0.0 }; /* quat_mul: * Multiplies two quaternions, storing the result in out. The resulting * quaternion will have the same effect as the combination of p and q, * ie. when applied to a point, (point * out) = ((point * p) * q). Any * number of rotations can be concatenated in this way. Note that quaternion * multiplication is not commutative, ie. quat_mul(p, q) != quat_mul(q, p). */ void quat_mul(AL_CONST QUAT *p, AL_CONST QUAT *q, QUAT *out) { QUAT temp; ASSERT(p); ASSERT(q); ASSERT(out); /* qp = ww' - v.v' + vxv' + wv' + w'v */ if (p == out) { temp = *p; p = &temp; } else if (q == out) { temp = *q; q = &temp; } /* w" = ww' - xx' - yy' - zz' */ out->w = (p->w * q->w) - (p->x * q->x) - (p->y * q->y) - (p->z * q->z); /* x" = wx' + xw' + yz' - zy' */ out->x = (p->w * q->x) + (p->x * q->w) + (p->y * q->z) - (p->z * q->y); /* y" = wy' + yw' + zx' - xz' */ out->y = (p->w * q->y) + (p->y * q->w) + (p->z * q->x) - (p->x * q->z); /* z" = wz' + zw' + xy' - yx' */ out->z = (p->w * q->z) + (p->z * q->w) + (p->x * q->y) - (p->y * q->x); } /* get_x_rotate_quat: * Construct X axis rotation quaternions, storing them in q. When applied to * a point, these quaternions will rotate it about the X axis by the * specified angle (given in binary, 256 degrees to a circle format). */ void get_x_rotate_quat(QUAT *q, float r) { ASSERT(q); FLOATSINCOS(r/2, q->x, q->w); q->y = 0; q->z = 0; } /* get_y_rotate_quat: * Construct Y axis rotation quaternions, storing them in q. When applied to * a point, these quaternions will rotate it about the Y axis by the * specified angle (given in binary, 256 degrees to a circle format). */ void get_y_rotate_quat(QUAT *q, float r) { ASSERT(q); FLOATSINCOS(r/2, q->y, q->w); q->x = 0; q->z = 0; } /* get_z_rotate_quat: * Construct Z axis rotation quaternions, storing them in q. When applied to * a point, these quaternions will rotate it about the Z axis by the * specified angle (given in binary, 256 degrees to a circle format). */ void get_z_rotate_quat(QUAT *q, float r) { ASSERT(q); FLOATSINCOS(r/2, q->z, q->w); q->x = 0; q->y = 0; } /* get_rotation_quat: * Constructs a quaternion which will rotate points around all three axis by * the specified amounts (given in binary, 256 degrees to a circle format). */ void get_rotation_quat(QUAT *q, float x, float y, float z) { float sx; float sy; float sz; float cx; float cy; float cz; float cycz; float sysz; ASSERT(q); FLOATSINCOS(x/2, sx, cx); FLOATSINCOS(y/2, sy, cy); FLOATSINCOS(z/2, sz, cz); sysz = sy * sz; cycz = cy * cz; q->w = (cx * cycz) + (sx * sysz); q->x = (sx * cycz) - (cx * sysz); q->y = (cx * sy * cz) + (sx * cy * sz); q->z = (cx * cy * sz) - (sx * sy * cz); } /* get_vector_rotation_quat: * Constructs a quaternion which will rotate points around the specified * x,y,z vector by the specified angle (given in binary, 256 degrees to a * circle format). */ void get_vector_rotation_quat(QUAT *q, float x, float y, float z, float a) { float l; float s; ASSERT(q); l = vector_length_f(x, y, z); /* NOTE: Passing (x, y, z) = (0, 0, 0) will cause l to equal 0 which will * cause a divide-by-zero exception. Rotating something about the * zero vector undefined. */ ASSERT(l != 0); x /= l; y /= l; z /= l; FLOATSINCOS(a/2, s, q->w); q->x = s * x; q->y = s * y; q->z = s * z; } /* quat_to_matrix: * Constructs a rotation matrix from a quaternion. */ void quat_to_matrix(AL_CONST QUAT *q, MATRIX_f *m) { float ww; float xx; float yy; float zz; float wx; float wy; float wz; float xy; float xz; float yz; ASSERT(q); ASSERT(m); /* This is the layout for converting the values in a quaternion to a * matrix. * * | ww + xx - yy - zz 2xy + 2wz 2xz - 2wy | * | 2xy - 2wz ww - xx + yy - zz 2yz - 2wx | * | 2xz + 2wy 2yz - 2wx ww + xx - yy - zz | */ ww = q->w * q->w; xx = q->x * q->x; yy = q->y * q->y; zz = q->z * q->z; wx = q->w * q->x * 2; wy = q->w * q->y * 2; wz = q->w * q->z * 2; xy = q->x * q->y * 2; xz = q->x * q->z * 2; yz = q->y * q->z * 2; m->v[0][0] = ww + xx - yy - zz; m->v[1][0] = xy - wz; m->v[2][0] = xz + wy; m->v[0][1] = xy + wz; m->v[1][1] = ww - xx + yy - zz; m->v[2][1] = yz - wx; m->v[0][2] = xz - wy; m->v[1][2] = yz + wx; m->v[2][2] = ww - xx - yy + zz; m->t[0] = 0.0; m->t[1] = 0.0; m->t[2] = 0.0; } /* matrix_to_quat: * Constructs a quaternion from a rotation matrix. Translation is discarded * during the conversion. Use get_align_matrix_f if the matrix is not * orthonormalized, because strange things may happen otherwise. */ void matrix_to_quat(AL_CONST MATRIX_f *m, QUAT *q) { float trace = m->v[0][0] + m->v[1][1] + m->v[2][2] + 1.0f; if (trace > EPSILON) { float s = 0.5f / (float)sqrt(trace); q->w = 0.25f / s; q->x = (m->v[2][1] - m->v[1][2]) * s; q->y = (m->v[0][2] - m->v[2][0]) * s; q->z = (m->v[1][0] - m->v[0][1]) * s; } else { if (m->v[0][0] > m->v[1][1] && m->v[0][0] > m->v[2][2]) { float s = 2.0f * (float)sqrt(1.0f + m->v[0][0] - m->v[1][1] - m->v[2][2]); q->x = 0.25f * s; q->y = (m->v[0][1] + m->v[1][0]) / s; q->z = (m->v[0][2] + m->v[2][0]) / s; q->w = (m->v[1][2] - m->v[2][1]) / s; } else if (m->v[1][1] > m->v[2][2]) { float s = 2.0f * (float)sqrt(1.0f + m->v[1][1] - m->v[0][0] - m->v[2][2]); q->x = (m->v[0][1] + m->v[1][0]) / s; q->y = 0.25f * s; q->z = (m->v[1][2] + m->v[2][1]) / s; q->w = (m->v[0][2] - m->v[2][0]) / s; } else { float s = 2.0f * (float)sqrt(1.0f + m->v[2][2] - m->v[0][0] - m->v[1][1]); q->x = (m->v[0][2] + m->v[2][0]) / s; q->y = (m->v[1][2] + m->v[2][1]) / s; q->z = 0.25f * s; q->w = (m->v[0][1] - m->v[1][0]) / s; } } } /* quat_conjugate: * A quaternion conjugate is analogous to a complex number conjugate, just * negate the imaginary part */ static INLINE void quat_conjugate(AL_CONST QUAT *q, QUAT *out) { ASSERT(q); ASSERT(out); /* q^* = w - x - y - z */ out->w = (q->w); out->x = -(q->x); out->y = -(q->y); out->z = -(q->z); } /* quat_normal: * A quaternion normal is the sum of the squares of the components. */ static INLINE float quat_normal(AL_CONST QUAT *q) { ASSERT(q); /* N(q) = ww + xx + yy + zz */ return ((q->w * q->w) + (q->x * q->x) + (q->y * q->y) + (q->z * q->z)); } /* quat_inverse: * A quaternion inverse is the conjugate divided by the normal. */ static INLINE void quat_inverse(AL_CONST QUAT *q, QUAT *out) { QUAT con; float norm; ASSERT(q); ASSERT(out); /* q^-1 = q^* / N(q) */ quat_conjugate(q, &con); norm = quat_normal(q); /* NOTE: If the normal is 0 then a divide-by-zero exception will occur, we * let this happen because the inverse of a zero quaternion is * undefined */ ASSERT(norm != 0); out->w = con.w / norm; out->x = con.x / norm; out->y = con.y / norm; out->z = con.z / norm; } /* apply_quat: * Multiplies the point (x, y, z) by the quaternion q, storing the result in * (*xout, *yout, *zout). This is quite a bit slower than apply_matrix_f. * So, only use it if you only need to translate a handful of points. * Otherwise it is much more efficient to call quat_to_matrix then use * apply_matrix_f. */ void apply_quat(AL_CONST QUAT *q, float x, float y, float z, float *xout, float *yout, float *zout) { QUAT v; QUAT i; QUAT t; ASSERT(q); ASSERT(xout); ASSERT(yout); ASSERT(zout); /* v' = q * v * q^-1 */ v.w = 0; v.x = x; v.y = y; v.z = z; /* NOTE: Rotating about a zero quaternion is undefined. This can be shown * by the fact that the inverse of a zero quaternion is undefined * and therefore causes an exception below. */ ASSERT(!((q->x == 0.0) && (q->y == 0.0) && (q->z == 0.0) && (q->w == 0.0))); quat_inverse(q, &i); quat_mul(&i, &v, &t); quat_mul(&t, q, &v); *xout = v.x; *yout = v.y; *zout = v.z; } /* quat_slerp: * Constructs a quaternion that represents a rotation between 'from' and * 'to'. The argument 't' can be anything between 0 and 1 and represents * where between from and to the result will be. 0 returns 'from', 1 * returns 'to', and 0.5 will return a rotation exactly in between. The * result is copied to 'out'. * * The variable 'how' can be any one of the following: * * QUAT_SHORT - This equivalent quat_interpolate, the rotation will * be less than 180 degrees * QUAT_LONG - rotation will be greater than 180 degrees * QUAT_CW - rotation will be clockwise when viewed from above * QUAT_CCW - rotation will be counterclockwise when viewed * from above * QUAT_USER - the quaternions are interpolated exactly as given */ void quat_slerp(AL_CONST QUAT *from, AL_CONST QUAT *to, float t, QUAT *out, int how) { QUAT to2; double angle; double cos_angle; double scale_from; double scale_to; double sin_angle; ASSERT(from); ASSERT(to); ASSERT(out); cos_angle = (from->x * to->x) + (from->y * to->y) + (from->z * to->z) + (from->w * to->w); if (((how == QUAT_SHORT) && (cos_angle < 0.0)) || ((how == QUAT_LONG) && (cos_angle > 0.0)) || ((how == QUAT_CW) && (from->w > to->w)) || ((how == QUAT_CCW) && (from->w < to->w))) { cos_angle = -cos_angle; to2.w = -to->w; to2.x = -to->x; to2.y = -to->y; to2.z = -to->z; } else { to2.w = to->w; to2.x = to->x; to2.y = to->y; to2.z = to->z; } if ((1.0 - ABS(cos_angle)) > EPSILON) { /* spherical linear interpolation (SLERP) */ angle = acos(cos_angle); sin_angle = sin(angle); scale_from = sin((1.0 - t) * angle) / sin_angle; scale_to = sin(t * angle) / sin_angle; } else { /* to prevent divide-by-zero, resort to linear interpolation */ scale_from = 1.0 - t; scale_to = t; } out->w = (float)((scale_from * from->w) + (scale_to * to2.w)); out->x = (float)((scale_from * from->x) + (scale_to * to2.x)); out->y = (float)((scale_from * from->y) + (scale_to * to2.y)); out->z = (float)((scale_from * from->z) + (scale_to * to2.z)); } allegro-4.4.3.1/src/math3d.c0000664000175000017500000005054613437077643014425 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Vector and matrix manipulation routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #define FLOATSINCOS(x, s, c) _AL_SINCOS((x) * AL_PI / 128.0, s ,c) #define floattan(x) tan((x) * AL_PI / 128.0) MATRIX identity_matrix = { { /* 3x3 identity */ { 1<<16, 0, 0 }, { 0, 1<<16, 0 }, { 0, 0, 1<<16 }, }, /* zero translation */ { 0, 0, 0 } }; MATRIX_f identity_matrix_f = { { /* 3x3 identity */ { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, }, /* zero translation */ { 0.0, 0.0, 0.0 } }; /* get_translation_matrix: * Constructs a 3d translation matrix. When applied to the vector * (vx, vy, vx), this will produce (vx+x, vy+y, vz+z). */ void get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z) { ASSERT(m); *m = identity_matrix; m->t[0] = x; m->t[1] = y; m->t[2] = z; } /* get_translation_matrix_f: * Floating point version of get_translation_matrix(). */ void get_translation_matrix_f(MATRIX_f *m, float x, float y, float z) { ASSERT(m); *m = identity_matrix_f; m->t[0] = x; m->t[1] = y; m->t[2] = z; } /* get_scaling_matrix: * Constructs a 3d scaling matrix. When applied to the vector * (vx, vy, vx), this will produce (vx*x, vy*y, vz*z). */ void get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z) { ASSERT(m); *m = identity_matrix; m->v[0][0] = x; m->v[1][1] = y; m->v[2][2] = z; } /* get_scaling_matrix_f: * Floating point version of get_scaling_matrix(). */ void get_scaling_matrix_f(MATRIX_f *m, float x, float y, float z) { ASSERT(m); *m = identity_matrix_f; m->v[0][0] = x; m->v[1][1] = y; m->v[2][2] = z; } /* get_x_rotate_matrix: * Constructs a 3d transformation matrix, which will rotate points around * the x axis by the specified amount (given in the Allegro fixed point, * 256 degrees to a circle format). */ void get_x_rotate_matrix(MATRIX *m, fixed r) { fixed c = fixcos(r); fixed s = fixsin(r); ASSERT(m); *m = identity_matrix; m->v[1][1] = c; m->v[1][2] = -s; m->v[2][1] = s; m->v[2][2] = c; } /* get_x_rotate_matrix_f: * Floating point version of get_x_rotate_matrix(). */ void get_x_rotate_matrix_f(MATRIX_f *m, float r) { float c, s; ASSERT(m); FLOATSINCOS(r, s, c); *m = identity_matrix_f; m->v[1][1] = c; m->v[1][2] = -s; m->v[2][1] = s; m->v[2][2] = c; } /* get_y_rotate_matrix: * Constructs a 3d transformation matrix, which will rotate points around * the y axis by the specified amount (given in the Allegro fixed point, * 256 degrees to a circle format). */ void get_y_rotate_matrix(MATRIX *m, fixed r) { fixed c = fixcos(r); fixed s = fixsin(r); ASSERT(m); *m = identity_matrix; m->v[0][0] = c; m->v[0][2] = s; m->v[2][0] = -s; m->v[2][2] = c; } /* get_y_rotate_matrix_f: * Floating point version of get_y_rotate_matrix(). */ void get_y_rotate_matrix_f(MATRIX_f *m, float r) { float c, s; ASSERT(m); FLOATSINCOS(r, s, c); *m = identity_matrix_f; m->v[0][0] = c; m->v[0][2] = s; m->v[2][0] = -s; m->v[2][2] = c; } /* get_z_rotate_matrix: * Constructs a 3d transformation matrix, which will rotate points around * the z axis by the specified amount (given in the Allegro fixed point, * 256 degrees to a circle format). */ void get_z_rotate_matrix(MATRIX *m, fixed r) { fixed c = fixcos(r); fixed s = fixsin(r); ASSERT(m); *m = identity_matrix; m->v[0][0] = c; m->v[0][1] = -s; m->v[1][0] = s; m->v[1][1] = c; } /* get_z_rotate_matrix_f: * Floating point version of get_z_rotate_matrix(). */ void get_z_rotate_matrix_f(MATRIX_f *m, float r) { float c, s; ASSERT(m); FLOATSINCOS(r, s, c); *m = identity_matrix_f; m->v[0][0] = c; m->v[0][1] = -s; m->v[1][0] = s; m->v[1][1] = c; } /* magical formulae for constructing rotation matrices */ #define MAKE_ROTATION(x, y, z) \ fixed sin_x = fixsin(x); \ fixed cos_x = fixcos(x); \ \ fixed sin_y = fixsin(y); \ fixed cos_y = fixcos(y); \ \ fixed sin_z = fixsin(z); \ fixed cos_z = fixcos(z); \ \ fixed sinx_siny = fixmul(sin_x, sin_y); \ fixed cosx_siny = fixmul(cos_x, sin_y); #define MAKE_ROTATION_f(x, y, z) \ float sin_x, cos_x; \ float sin_y, cos_y; \ float sin_z, cos_z; \ float sinx_siny, cosx_siny; \ \ FLOATSINCOS(x, sin_x, cos_x); \ FLOATSINCOS(y, sin_y, cos_y); \ FLOATSINCOS(z, sin_z, cos_z); \ \ sinx_siny = sin_x * sin_y; \ cosx_siny = cos_x * sin_y; #define R00 (fixmul(cos_y, cos_z)) #define R10 (fixmul(sinx_siny, cos_z) - fixmul(cos_x, sin_z)) #define R20 (fixmul(cosx_siny, cos_z) + fixmul(sin_x, sin_z)) #define R01 (fixmul(cos_y, sin_z)) #define R11 (fixmul(sinx_siny, sin_z) + fixmul(cos_x, cos_z)) #define R21 (fixmul(cosx_siny, sin_z) - fixmul(sin_x, cos_z)) #define R02 (-sin_y) #define R12 (fixmul(sin_x, cos_y)) #define R22 (fixmul(cos_x, cos_y)) #define R00_f (cos_y * cos_z) #define R10_f ((sinx_siny * cos_z) - (cos_x * sin_z)) #define R20_f ((cosx_siny * cos_z) + (sin_x * sin_z)) #define R01_f (cos_y * sin_z) #define R11_f ((sinx_siny * sin_z) + (cos_x * cos_z)) #define R21_f ((cosx_siny * sin_z) - (sin_x * cos_z)) #define R02_f (-sin_y) #define R12_f (sin_x * cos_y) #define R22_f (cos_x * cos_y) /* get_rotation_matrix: * Constructs a 3d transformation matrix, which will rotate points around * all three axis by the specified amounts (given in the Allegro fixed * point, 256 degrees to a circle format). */ void get_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z) { MAKE_ROTATION(x, y, z); ASSERT(m); m->v[0][0] = R00; m->v[0][1] = R01; m->v[0][2] = R02; m->v[1][0] = R10; m->v[1][1] = R11; m->v[1][2] = R12; m->v[2][0] = R20; m->v[2][1] = R21; m->v[2][2] = R22; m->t[0] = m->t[1] = m->t[2] = 0; } /* get_rotation_matrix_f: * Floating point version of get_rotation_matrix(). */ void get_rotation_matrix_f(MATRIX_f *m, float x, float y, float z) { MAKE_ROTATION_f(x, y, z); ASSERT(m); m->v[0][0] = R00_f; m->v[0][1] = R01_f; m->v[0][2] = R02_f; m->v[1][0] = R10_f; m->v[1][1] = R11_f; m->v[1][2] = R12_f; m->v[2][0] = R20_f; m->v[2][1] = R21_f; m->v[2][2] = R22_f; m->t[0] = m->t[1] = m->t[2] = 0; } /* get_align_matrix: * Aligns a matrix along an arbitrary coordinate system. */ void get_align_matrix(MATRIX *m, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup) { fixed xright, yright, zright; ASSERT(m); xfront = -xfront; yfront = -yfront; zfront = -zfront; normalize_vector(&xfront, &yfront, &zfront); cross_product(xup, yup, zup, xfront, yfront, zfront, &xright, &yright, &zright); normalize_vector(&xright, &yright, &zright); cross_product(xfront, yfront, zfront, xright, yright, zright, &xup, &yup, &zup); /* No need to normalize up here, since right and front are perpendicular and normalized. */ m->v[0][0] = xright; m->v[0][1] = xup; m->v[0][2] = xfront; m->v[1][0] = yright; m->v[1][1] = yup; m->v[1][2] = yfront; m->v[2][0] = zright; m->v[2][1] = zup; m->v[2][2] = zfront; m->t[0] = m->t[1] = m->t[2] = 0; } /* get_align_matrix_f: * Floating point version of get_align_matrix(). */ void get_align_matrix_f(MATRIX_f *m, float xfront, float yfront, float zfront, float xup, float yup, float zup) { float xright, yright, zright; ASSERT(m); xfront = -xfront; yfront = -yfront; zfront = -zfront; normalize_vector_f(&xfront, &yfront, &zfront); cross_product_f(xup, yup, zup, xfront, yfront, zfront, &xright, &yright, &zright); normalize_vector_f(&xright, &yright, &zright); cross_product_f(xfront, yfront, zfront, xright, yright, zright, &xup, &yup, &zup); /* No need to normalize up here, since right and front are perpendicular and normalized. */ m->v[0][0] = xright; m->v[0][1] = xup; m->v[0][2] = xfront; m->v[1][0] = yright; m->v[1][1] = yup; m->v[1][2] = yfront; m->v[2][0] = zright; m->v[2][1] = zup; m->v[2][2] = zfront; m->t[0] = m->t[1] = m->t[2] = 0; } /* get_vector_rotation_matrix: * Constructs a 3d transformation matrix, which will rotate points around * the specified x,y,z vector by the specified angle (given in the Allegro * fixed point, 256 degrees to a circle format), in a clockwise direction. */ void get_vector_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z, fixed a) { MATRIX_f rotation; int i, j; ASSERT(m); get_vector_rotation_matrix_f(&rotation, fixtof(x), fixtof(y), fixtof(z), fixtof(a)); for (i=0; i<3; i++) for (j=0; j<3; j++) m->v[i][j] = ftofix(rotation.v[i][j]); m->t[0] = m->t[1] = m->t[2] = 0; } /* get_vector_rotation_matrix_f: * Floating point version of get_vector_rotation_matrix(). */ void get_vector_rotation_matrix_f(MATRIX_f *m, float x, float y, float z, float a) { float c, s, cc; ASSERT(m); FLOATSINCOS(a, s, c); cc = 1 - c; normalize_vector_f(&x, &y, &z); m->v[0][0] = (cc * x * x) + c; m->v[0][1] = (cc * x * y) + (z * s); m->v[0][2] = (cc * x * z) - (y * s); m->v[1][0] = (cc * x * y) - (z * s); m->v[1][1] = (cc * y * y) + c; m->v[1][2] = (cc * z * y) + (x * s); m->v[2][0] = (cc * x * z) + (y * s); m->v[2][1] = (cc * y * z) - (x * s); m->v[2][2] = (cc * z * z) + c; m->t[0] = m->t[1] = m->t[2] = 0; } /* get_transformation_matrix: * Constructs a 3d transformation matrix, which will rotate points around * all three axis by the specified amounts (given in the Allegro fixed * point, 256 degrees to a circle format), scale the result by the * specified amount (itofix(1) for no change of scale), and then translate * to the requested x, y, z position. */ void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, fixed yrot, fixed zrot, fixed x, fixed y, fixed z) { MAKE_ROTATION(xrot, yrot, zrot); ASSERT(m); m->v[0][0] = fixmul(R00, scale); m->v[0][1] = fixmul(R01, scale); m->v[0][2] = fixmul(R02, scale); m->v[1][0] = fixmul(R10, scale); m->v[1][1] = fixmul(R11, scale); m->v[1][2] = fixmul(R12, scale); m->v[2][0] = fixmul(R20, scale); m->v[2][1] = fixmul(R21, scale); m->v[2][2] = fixmul(R22, scale); m->t[0] = x; m->t[1] = y; m->t[2] = z; } /* get_transformation_matrix_f: * Floating point version of get_transformation_matrix(). */ void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, float yrot, float zrot, float x, float y, float z) { MAKE_ROTATION_f(xrot, yrot, zrot); ASSERT(m); m->v[0][0] = R00_f * scale; m->v[0][1] = R01_f * scale; m->v[0][2] = R02_f * scale; m->v[1][0] = R10_f * scale; m->v[1][1] = R11_f * scale; m->v[1][2] = R12_f * scale; m->v[2][0] = R20_f * scale; m->v[2][1] = R21_f * scale; m->v[2][2] = R22_f * scale; m->t[0] = x; m->t[1] = y; m->t[2] = z; } /* get_camera_matrix: * Constructs a camera matrix for translating world-space objects into * a normalised view space, ready for the perspective projection. The * x, y, and z parameters specify the camera position, xfront, yfront, * and zfront is an 'in front' vector specifying which way the camera * is facing (this can be any length: normalisation is not required), * and xup, yup, and zup is the 'up' direction vector. Up is really only * a 1.5d vector, since the front vector only leaves one degree of freedom * for which way up to put the image, but it is simplest to specify it * as a full 3d direction even though a lot of the information in it is * discarded. The fov parameter specifies the field of view (ie. width * of the camera focus) in fixed point, 256 degrees to the circle format. * For typical projections, a field of view in the region 32-48 will work * well. Finally, the aspect ratio is used to scale the Y dimensions of * the image relative to the X axis, so you can use it to correct for * the proportions of the output image (set it to 1 for no scaling). */ void get_camera_matrix(MATRIX *m, fixed x, fixed y, fixed z, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup, fixed fov, fixed aspect) { MATRIX_f camera; int i, j; ASSERT(m); get_camera_matrix_f(&camera, fixtof(x), fixtof(y), fixtof(z), fixtof(xfront), fixtof(yfront), fixtof(zfront), fixtof(xup), fixtof(yup), fixtof(zup), fixtof(fov), fixtof(aspect)); for (i=0; i<3; i++) { for (j=0; j<3; j++) m->v[i][j] = ftofix(camera.v[i][j]); m->t[i] = ftofix(camera.t[i]); } } /* get_camera_matrix_f: * Floating point version of get_camera_matrix(). */ void get_camera_matrix_f(MATRIX_f *m, float x, float y, float z, float xfront, float yfront, float zfront, float xup, float yup, float zup, float fov, float aspect) { MATRIX_f camera, scale; float xside, yside, zside, width, d; ASSERT(m); /* make 'in-front' into a unit vector, and negate it */ normalize_vector_f(&xfront, &yfront, &zfront); xfront = -xfront; yfront = -yfront; zfront = -zfront; /* make sure 'up' is at right angles to 'in-front', and normalize */ d = dot_product_f(xup, yup, zup, xfront, yfront, zfront); xup -= d * xfront; yup -= d * yfront; zup -= d * zfront; normalize_vector_f(&xup, &yup, &zup); /* calculate the 'sideways' vector */ cross_product_f(xup, yup, zup, xfront, yfront, zfront, &xside, &yside, &zside); /* set matrix rotation parameters */ camera.v[0][0] = xside; camera.v[0][1] = yside; camera.v[0][2] = zside; camera.v[1][0] = xup; camera.v[1][1] = yup; camera.v[1][2] = zup; camera.v[2][0] = xfront; camera.v[2][1] = yfront; camera.v[2][2] = zfront; /* set matrix translation parameters */ camera.t[0] = -(x*xside + y*yside + z*zside); camera.t[1] = -(x*xup + y*yup + z*zup); camera.t[2] = -(x*xfront + y*yfront + z*zfront); /* construct a scaling matrix to deal with aspect ratio and FOV */ width = floattan(64.0 - fov/2); get_scaling_matrix_f(&scale, width, -aspect*width, -1.0); /* combine the camera and scaling matrices */ matrix_mul_f(&camera, &scale, m); } /* qtranslate_matrix: * Adds a position offset to an existing matrix. */ void qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z) { ASSERT(m); m->t[0] += x; m->t[1] += y; m->t[2] += z; } /* qtranslate_matrix_f: * Floating point version of qtranslate_matrix(). */ void qtranslate_matrix_f(MATRIX_f *m, float x, float y, float z) { ASSERT(m); m->t[0] += x; m->t[1] += y; m->t[2] += z; } /* qscale_matrix: * Adds a scaling factor to an existing matrix. */ void qscale_matrix(MATRIX *m, fixed scale) { int i, j; ASSERT(m); for (i=0; i<3; i++) for (j=0; j<3; j++) m->v[i][j] = fixmul(m->v[i][j], scale); } /* qscale_matrix_f: * Floating point version of qscale_matrix(). */ void qscale_matrix_f(MATRIX_f *m, float scale) { int i, j; ASSERT(m); for (i=0; i<3; i++) for (j=0; j<3; j++) m->v[i][j] *= scale; } /* matrix_mul: * Multiplies two matrices, storing the result in out (this must be * different from the two input matrices). The resulting matrix will * have the same effect as the combination of m1 and m2, ie. when * applied to a vector v, (v * out) = ((v * m1) * m2). Any number of * transformations can be concatenated in this way. */ void matrix_mul(AL_CONST MATRIX *m1, AL_CONST MATRIX *m2, MATRIX *out) { MATRIX temp; int i, j; ASSERT(m1); ASSERT(m2); ASSERT(out); if (m1 == out) { temp = *m1; m1 = &temp; } else if (m2 == out) { temp = *m2; m2 = &temp; } for (i=0; i<3; i++) { for (j=0; j<3; j++) { out->v[i][j] = fixmul(m1->v[0][j], m2->v[i][0]) + fixmul(m1->v[1][j], m2->v[i][1]) + fixmul(m1->v[2][j], m2->v[i][2]); } out->t[i] = fixmul(m1->t[0], m2->v[i][0]) + fixmul(m1->t[1], m2->v[i][1]) + fixmul(m1->t[2], m2->v[i][2]) + m2->t[i]; } } /* matrix_mul_f: * Floating point version of matrix_mul(). */ void matrix_mul_f(AL_CONST MATRIX_f *m1, AL_CONST MATRIX_f *m2, MATRIX_f *out) { MATRIX_f temp; int i, j; ASSERT(m1); ASSERT(m2); ASSERT(out); if (m1 == out) { temp = *m1; m1 = &temp; } else if (m2 == out) { temp = *m2; m2 = &temp; } for (i=0; i<3; i++) { for (j=0; j<3; j++) { out->v[i][j] = (m1->v[0][j] * m2->v[i][0]) + (m1->v[1][j] * m2->v[i][1]) + (m1->v[2][j] * m2->v[i][2]); } out->t[i] = (m1->t[0] * m2->v[i][0]) + (m1->t[1] * m2->v[i][1]) + (m1->t[2] * m2->v[i][2]) + m2->t[i]; } } /* vector_length: * Computes the length of a vector, using the son of the squaw... */ fixed vector_length(fixed x, fixed y, fixed z) { x >>= 8; y >>= 8; z >>= 8; return (fixsqrt(fixmul(x,x) + fixmul(y,y) + fixmul(z,z)) << 8); } /* vector_lengthf: * Floating point version of vector_length(). */ float vector_length_f(float x, float y, float z) { return sqrt(x*x + y*y + z*z); } /* normalize_vector: * Converts the specified vector to a unit vector, which has the same * orientation but a length of one. */ void normalize_vector(fixed *x, fixed *y, fixed *z) { fixed length = vector_length(*x, *y, *z); *x = fixdiv(*x, length); *y = fixdiv(*y, length); *z = fixdiv(*z, length); } /* normalize_vectorf: * Floating point version of normalize_vector(). */ void normalize_vector_f(float *x, float *y, float *z) { float length = 1.0 / vector_length_f(*x, *y, *z); *x *= length; *y *= length; *z *= length; } /* cross_product: * Calculates the cross product of two vectors. */ void cross_product(fixed x1, fixed y1, fixed z1, fixed x2, fixed y2, fixed z2, fixed *xout, fixed *yout, fixed *zout) { ASSERT(xout); ASSERT(yout); ASSERT(zout); *xout = fixmul(y1, z2) - fixmul(z1, y2); *yout = fixmul(z1, x2) - fixmul(x1, z2); *zout = fixmul(x1, y2) - fixmul(y1, x2); } /* cross_productf: * Floating point version of cross_product(). */ void cross_product_f(float x1, float y1, float z1, float x2, float y2, float z2, float *xout, float *yout, float *zout) { ASSERT(xout); ASSERT(yout); ASSERT(zout); *xout = (y1 * z2) - (z1 * y2); *yout = (z1 * x2) - (x1 * z2); *zout = (x1 * y2) - (y1 * x2); } /* polygon_z_normal: * Helper function for backface culling: returns the z component of the * normal vector to the polygon formed from the three vertices. */ fixed polygon_z_normal(AL_CONST V3D *v1, AL_CONST V3D *v2, AL_CONST V3D *v3) { ASSERT(v1); ASSERT(v2); ASSERT(v3); return (fixmul(v2->x-v1->x, v3->y-v2->y) - fixmul(v3->x-v2->x, v2->y-v1->y)); } /* polygon_z_normal_f: * Floating point version of polygon_z_normal(). */ float polygon_z_normal_f(AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, AL_CONST V3D_f *v3) { ASSERT(v1); ASSERT(v2); ASSERT(v3); return ((v2->x-v1->x) * (v3->y-v2->y)) - ((v3->x-v2->x) * (v2->y-v1->y)); } /* scaling factors for the perspective projection */ fixed _persp_xscale = 160 << 16; fixed _persp_yscale = 100 << 16; fixed _persp_xoffset = 160 << 16; fixed _persp_yoffset = 100 << 16; float _persp_xscale_f = 160.0; float _persp_yscale_f = 100.0; float _persp_xoffset_f = 160.0; float _persp_yoffset_f = 100.0; /* set_projection_viewport: * Sets the viewport used to scale the output of the persp_project() * function. */ void set_projection_viewport(int x, int y, int w, int h) { ASSERT(w > 0); ASSERT(h > 0); _persp_xscale = itofix(w/2); _persp_yscale = itofix(h/2); _persp_xoffset = itofix(x + w/2); _persp_yoffset = itofix(y + h/2); _persp_xscale_f = w/2; _persp_yscale_f = h/2; _persp_xoffset_f = x + w/2; _persp_yoffset_f = y + h/2; } allegro-4.4.3.1/src/fonttxt.c0000664000175000017500000000631713437077643014750 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * * TXT font file reader. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" /* load_txt_font: * Loads a scripted font. */ FONT *load_txt_font(AL_CONST char *filename, RGB *pal, void *param) { char buf[1024], *font_str, *start_str = 0, *end_str = 0; char font_filename[1024]; FONT *f, *f2, *f3, *f4; PACKFILE *pack; int begin, end, glyph_pos=32; pack = pack_fopen(filename, F_READ); if (!pack) return NULL; f = f2 = f3 = f4 = NULL; while(pack_fgets(buf, sizeof(buf)-1, pack)) { font_str = strtok(buf, " \t"); if (font_str) start_str = strtok(0, " \t"); if (start_str) end_str = strtok(0, " \t"); if (!font_str || !start_str) { if (f) destroy_font(f); if (f2) destroy_font(f2); pack_fclose(pack); return NULL; } if(font_str[0] == '-') font_str[0] = '\0'; begin = strtol(start_str, 0, 0); if (end_str) end = strtol(end_str, 0, 0); else end = -1; if(begin <= 0 || (end > 0 && end < begin)) { if (f) destroy_font(f); if (f2) destroy_font(f2); pack_fclose(pack); return NULL; } /* Load the font that needs to be merged with the current font */ if (font_str[0]) { if (f2) destroy_font(f2); if (exists(font_str)) { f2 = load_font(font_str, pal, param); } else if (is_relative_filename(font_str)) { replace_filename(font_filename, filename, font_str, sizeof(font_filename)); f2 = load_font(font_filename, pal, param); } else { f2 = NULL; } if (f2) glyph_pos=get_font_range_begin(f2, -1); } if (!f2) { if (f) destroy_font(f); pack_fclose(pack); return NULL; } if (end == -1) end = begin + get_font_range_end(f2,-1) - glyph_pos; /* transpose the font to the range given in the .txt file */ f4=extract_font_range(f2,glyph_pos,glyph_pos + (end - begin)); if (f4 && (begin != glyph_pos)) { transpose_font(f4, begin - glyph_pos); } glyph_pos += (end - begin) + 1; /* FIXME: More efficient way than to repeatedely merge into a new font? */ if (f && f4) { f3 = f; f = merge_fonts(f4, f3); destroy_font(f4); destroy_font(f3); } else { f = f4; } f3=f4=NULL; } if (f2) destroy_font(f2); pack_fclose(pack); return f; } allegro-4.4.3.1/src/color.c0000664000175000017500000004672613437077643014370 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Color manipulation routines (blending, format conversion, lighting * table construction, etc). * * By Shawn Hargreaves. * * Dave Thomson contributed the RGB <-> HSV conversion routines. * * Jan Hubicka wrote the super-fast version of create_rgb_table(). * * Michael Bevin and Sven Sandberg optimised the create_trans_table() * function. * * Sven Sandberg optimised the create_light_table() function. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" /* makecol_depth: * Converts R, G, and B values (ranging 0-255) to whatever pixel format * is required by the specified color depth. */ int makecol_depth(int color_depth, int r, int g, int b) { switch (color_depth) { case 8: return makecol8(r, g, b); case 15: return makecol15(r, g, b); case 16: return makecol16(r, g, b); case 24: return makecol24(r, g, b); case 32: return makecol32(r, g, b); } return 0; } /* makeacol_depth: * Converts R, G, B, and A values (ranging 0-255) to whatever pixel format * is required by the specified color depth. */ int makeacol_depth(int color_depth, int r, int g, int b, int a) { switch (color_depth) { case 8: return makecol8(r, g, b); case 15: return makecol15(r, g, b); case 16: return makecol16(r, g, b); case 24: return makecol24(r, g, b); case 32: return makeacol32(r, g, b, a); } return 0; } /* makecol: * Converts R, G, and B values (ranging 0-255) to whatever pixel format * is required by the current video mode. */ int makecol(int r, int g, int b) { return makecol_depth(_color_depth, r, g, b); } /* makeacol: * Converts R, G, B, and A values (ranging 0-255) to whatever pixel format * is required by the current video mode. */ int makeacol(int r, int g, int b, int a) { return makeacol_depth(_color_depth, r, g, b, a); } /* getr_depth: * Extracts the red component (ranging 0-255) from a pixel in the format * being used by the specified color depth. */ int getr_depth(int color_depth, int c) { switch (color_depth) { case 8: return getr8(c); case 15: return getr15(c); case 16: return getr16(c); case 24: return getr24(c); case 32: return getr32(c); } return 0; } /* getg_depth: * Extracts the green component (ranging 0-255) from a pixel in the format * being used by the specified color depth. */ int getg_depth(int color_depth, int c) { switch (color_depth) { case 8: return getg8(c); case 15: return getg15(c); case 16: return getg16(c); case 24: return getg24(c); case 32: return getg32(c); } return 0; } /* getb_depth: * Extracts the blue component (ranging 0-255) from a pixel in the format * being used by the specified color depth. */ int getb_depth(int color_depth, int c) { switch (color_depth) { case 8: return getb8(c); case 15: return getb15(c); case 16: return getb16(c); case 24: return getb24(c); case 32: return getb32(c); } return 0; } /* geta_depth: * Extracts the alpha component (ranging 0-255) from a pixel in the format * being used by the specified color depth. */ int geta_depth(int color_depth, int c) { if (color_depth == 32) return geta32(c); return 0; } /* getr: * Extracts the red component (ranging 0-255) from a pixel in the format * being used by the current video mode. */ int getr(int c) { return getr_depth(_color_depth, c); } /* getg: * Extracts the green component (ranging 0-255) from a pixel in the format * being used by the current video mode. */ int getg(int c) { return getg_depth(_color_depth, c); } /* getb: * Extracts the blue component (ranging 0-255) from a pixel in the format * being used by the current video mode. */ int getb(int c) { return getb_depth(_color_depth, c); } /* geta: * Extracts the alpha component (ranging 0-255) from a pixel in the format * being used by the current video mode. */ int geta(int c) { return geta_depth(_color_depth, c); } /* 1.5k lookup table for color matching */ static unsigned int col_diff[3*128]; /* bestfit_init: * Color matching is done with weighted squares, which are much faster * if we pregenerate a little lookup table... */ static void bestfit_init(void) { int i; for (i=1; i<64; i++) { int k = i * i; col_diff[0 +i] = col_diff[0 +128-i] = k * (59 * 59); col_diff[128+i] = col_diff[128+128-i] = k * (30 * 30); col_diff[256+i] = col_diff[256+128-i] = k * (11 * 11); } } /* bestfit_color: * Searches a palette for the color closest to the requested R, G, B value. */ int bestfit_color(AL_CONST PALETTE pal, int r, int g, int b) { int i, coldiff, lowest, bestfit; ASSERT(r >= 0 && r <= 63); ASSERT(g >= 0 && g <= 63); ASSERT(b >= 0 && b <= 63); if (col_diff[1] == 0) bestfit_init(); bestfit = 0; lowest = INT_MAX; /* only the transparent (pink) color can be mapped to index 0 */ if ((r == 63) && (g == 0) && (b == 63)) i = 0; else i = 1; while (ig - g) & 0x7F ]; if (coldiff < lowest) { coldiff += (col_diff + 128) [ (rgb->r - r) & 0x7F ]; if (coldiff < lowest) { coldiff += (col_diff + 256) [ (rgb->b - b) & 0x7F ]; if (coldiff < lowest) { bestfit = rgb - pal; /* faster than `bestfit = i;' */ if (coldiff == 0) return bestfit; lowest = coldiff; } } } i++; } return bestfit; } /* makecol8: * Converts R, G, and B values (ranging 0-255) to an 8 bit paletted color. * If the global rgb_map table is initialised, it uses that, otherwise * it searches through the current palette to find the best match. */ int makecol8(int r, int g, int b) { if (rgb_map) return rgb_map->data[r>>3][g>>3][b>>3]; else return bestfit_color(_current_palette, r>>2, g>>2, b>>2); } /* hsv_to_rgb: * Converts from HSV colorspace to RGB values. */ void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b) { float f, x, y, z; int i; ASSERT(s >= 0 && s <= 1); ASSERT(v >= 0 && v <= 1); v *= 255.0f; if (s == 0.0f) { /* ok since we don't divide by s, and faster */ *r = *g = *b = v + 0.5f; } else { h = fmod(h, 360.0f) / 60.0f; if (h < 0.0f) h += 6.0f; i = (int)h; f = h - i; x = v * s; y = x * f; v += 0.5f; /* round to the nearest integer below */ z = v - x; switch (i) { case 6: case 0: *r = v; *g = z + y; *b = z; break; case 1: *r = v - y; *g = v; *b = z; break; case 2: *r = z; *g = v; *b = z + y; break; case 3: *r = z; *g = v - y; *b = v; break; case 4: *r = z + y; *g = z; *b = v; break; case 5: *r = v; *g = z; *b = v - y; break; } } } /* rgb_to_hsv: * Converts an RGB value into the HSV colorspace. */ void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v) { int delta; ASSERT(r >= 0 && r <= 255); ASSERT(g >= 0 && g <= 255); ASSERT(b >= 0 && b <= 255); if (r > g) { if (b > r) { /* b>r>g */ delta = b-g; *h = 240.0f + ((r-g) * 60) / (float)delta; *s = (float)delta / (float)b; *v = (float)b * (1.0f/255.0f); } else { /* r>g and r>b */ delta = r - MIN(g, b); *h = ((g-b) * 60) / (float)delta; if (*h < 0.0f) *h += 360.0f; *s = (float)delta / (float)r; *v = (float)r * (1.0f/255.0f); } } else { if (b > g) { /* b>g>=r */ delta = b-r; *h = 240.0f + ((r-g) * 60) / (float)delta; *s = (float)delta / (float)b; *v = (float)b * (1.0f/255.0f); } else { /* g>=b and g>=r */ delta = g - MIN(r, b); if (delta == 0) { *h = 0.0f; if (g == 0) *s = *v = 0.0f; else { *s = (float)delta / (float)g; *v = (float)g * (1.0f/255.0f); } } else { *h = 120.0f + ((b-r) * 60) / (float)delta; *s = (float)delta / (float)g; *v = (float)g * (1.0f/255.0f); } } } } /* create_rgb_table: * Fills an RGB_MAP lookup table with conversion data for the specified * palette. This is the faster version by Jan Hubicka. * * Uses alg. similar to floodfill - it adds one seed per every color in * palette to its best position. Then areas around seed are filled by * same color because it is best approximation for them, and then areas * about them etc... * * It does just about 80000 tests for distances and this is about 100 * times better than normal 256*32000 tests so the calculation time * is now less than one second at all computers I tested. */ void create_rgb_table(RGB_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) { #define UNUSED 65535 #define LAST 65532 /* macro add adds to single linked list */ #define add(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \ (first != LAST ? (next[last] = (i)) : (first = (i))), \ (last = (i))) : 0) /* same but w/o checking for first element */ #define add1(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \ next[last] = (i), \ (last = (i))) : 0) /* calculates distance between two colors */ #define dist(a1, a2, a3, b1, b2, b3) \ (col_diff[ ((a2) - (b2)) & 0x7F] + \ (col_diff + 128)[((a1) - (b1)) & 0x7F] + \ (col_diff + 256)[((a3) - (b3)) & 0x7F]) /* converts r,g,b to position in array and back */ #define pos(r, g, b) \ (((r) / 2) * 32 * 32 + ((g) / 2) * 32 + ((b) / 2)) #define depos(pal, r, g, b) \ ((b) = ((pal) & 31) * 2, \ (g) = (((pal) >> 5) & 31) * 2, \ (r) = (((pal) >> 10) & 31) * 2) /* is current color better than pal1? */ #define better(r1, g1, b1, pal1) \ (((int)dist((r1), (g1), (b1), \ (pal1).r, (pal1).g, (pal1).b)) > (int)dist2) /* checking of position */ #define dopos(rp, gp, bp, ts) \ if ((rp > -1 || r > 0) && (rp < 1 || r < 61) && \ (gp > -1 || g > 0) && (gp < 1 || g < 61) && \ (bp > -1 || b > 0) && (bp < 1 || b < 61)) { \ i = first + rp * 32 * 32 + gp * 32 + bp; \ if (!data[i]) { \ data[i] = val; \ add1(i); \ } \ else if ((ts) && (data[i] != val)) { \ dist2 = (rp ? (col_diff+128)[(r+2*rp-pal[val].r) & 0x7F] : r2) + \ (gp ? (col_diff )[(g+2*gp-pal[val].g) & 0x7F] : g2) + \ (bp ? (col_diff+256)[(b+2*bp-pal[val].b) & 0x7F] : b2); \ if (better((r+2*rp), (g+2*gp), (b+2*bp), pal[data[i]])) { \ data[i] = val; \ add1(i); \ } \ } \ } int i, curr, r, g, b, val, dist2; unsigned int r2, g2, b2; unsigned short next[32*32*32]; unsigned char *data; int first = LAST; int last = LAST; int count = 0; int cbcount = 0; #define AVERAGE_COUNT 18000 if (col_diff[1] == 0) bestfit_init(); memset(next, 255, sizeof(next)); memset(table->data, 0, sizeof(char)*32*32*32); data = (unsigned char *)table->data; /* add starting seeds for floodfill */ for (i=1; i 0) && (data[first-1] == val)) { b -= 2; first--; b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; dopos(-1, 0, 0, 0); dopos( 1, 0, 0, 0); dopos( 0,-1, 0, 0); dopos( 0, 1, 0, 0); first++; } /* get next from list */ i = first; first = next[first]; next[i] = UNUSED; /* second version of loop */ if (first != LAST) { depos(first, r, g, b); val = data[first]; r2 = (col_diff+128)[((pal[val].r)-(r)) & 0x7F]; g2 = (col_diff )[((pal[val].g)-(g)) & 0x7F]; b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; dopos( 0, 0, 1, 1); dopos( 0, 0,-1, 1); dopos( 1, 0, 0, 1); dopos(-1, 0, 0, 1); dopos( 0, 1, 0, 1); dopos( 0,-1, 0, 1); if ((b < 61) && (data[first + 1] == val)) { b += 2; first++; b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7f]; dopos(-1, 0, 0, 0); dopos( 1, 0, 0, 0); dopos( 0,-1, 0, 0); dopos( 0, 1, 0, 0); first--; } i = first; first = next[first]; next[i] = UNUSED; } count++; if (count == (cbcount+1)*AVERAGE_COUNT/256) { if (cbcount < 256) { if (callback) callback(cbcount); cbcount++; } } } /* only the transparent (pink) color can be mapped to index 0 */ if ((pal[0].r == 63) && (pal[0].g == 0) && (pal[0].b == 63)) table->data[31][0][31] = 0; if (callback) while (cbcount < 256) callback(cbcount++); } /* create_light_table: * Constructs a lighting color table for the specified palette. At light * intensity 255 the table will produce the palette colors directly, and * at level 0 it will produce the specified R, G, B value for all colors * (this is specified in 0-63 VGA format). If the callback function is * not NULL, it will be called 256 times during the calculation, allowing * you to display a progress indicator. */ void create_light_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) { int r1, g1, b1, r2, g2, b2, x, y; unsigned int t1, t2; ASSERT(table); ASSERT(r >= 0 && r <= 63); ASSERT(g >= 0 && g <= 63); ASSERT(b >= 0 && b <= 63); if (rgb_map) { for (x=0; x> 25; g2 = (g1 + pal[y].g * t1) >> 25; b2 = (b1 + pal[y].b * t1) >> 25; table->data[x][y] = rgb_map->data[r2][g2][b2]; } } if (callback) (*callback)(x); } else { for (x=0; x> 24; g2 = (g1 + pal[y].g * t1) >> 24; b2 = (b1 + pal[y].b * t1) >> 24; table->data[x][y] = bestfit_color(pal, r2, g2, b2); } } if (callback) (*callback)(x); } for (y=0; ydata[255][y] = y; } /* create_trans_table: * Constructs a translucency color table for the specified palette. The * r, g, and b parameters specifiy the solidity of each color component, * ranging from 0 (totally transparent) to 255 (totally solid). Source * color #0 is a special case, and is set to leave the destination * unchanged, so that masked sprites will draw correctly. If the callback * function is not NULL, it will be called 256 times during the calculation, * allowing you to display a progress indicator. */ void create_trans_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, void (*callback)(int pos)) { int tmp[768], *q; int x, y, i, j, k; unsigned char *p; int tr, tg, tb; int add; ASSERT(table); ASSERT(r >= 0 && r <= 255); ASSERT(g >= 0 && g <= 255); ASSERT(b >= 0 && b <= 255); /* This is a bit ugly, but accounts for the solidity parameters being in the range 0-255 rather than 0-256. Given that the precision of r,g,b components is only 6 bits it shouldn't do any harm. */ if (r > 128) r++; if (g > 128) g++; if (b > 128) b++; if (rgb_map) add = 255; else add = 127; for (x=0; x<256; x++) { tmp[x*3] = pal[x].r * (256-r) + add; tmp[x*3+1] = pal[x].g * (256-g) + add; tmp[x*3+2] = pal[x].b * (256-b) + add; } for (x=1; xdata[x]; q = tmp; if (rgb_map) { for (y=0; y> 9; tg = (j + *(q++)) >> 9; tb = (k + *(q++)) >> 9; p[y] = rgb_map->data[tr][tg][tb]; } } else { for (y=0; y> 8; tg = (j + *(q++)) >> 8; tb = (k + *(q++)) >> 8; p[y] = bestfit_color(pal, tr, tg, tb); } } if (callback) (*callback)(x-1); } for (y=0; ydata[0][y] = y; table->data[y][y] = y; } if (callback) (*callback)(255); } /* create_color_table: * Creates a color mapping table, using a user-supplied callback to blend * each pair of colors. Your blend routine will be passed a pointer to the * palette and the two colors to be blended (x is the source color, y is * the destination), and should return the desired output RGB for this * combination. If the callback function is not NULL, it will be called * 256 times during the calculation, allowing you to display a progress * indicator. */ void create_color_table(COLOR_MAP *table, AL_CONST PALETTE pal, void (*blend)(AL_CONST PALETTE pal, int x, int y, RGB *rgb), void (*callback)(int pos)) { int x, y; RGB c; for (x=0; xdata[x][y] = rgb_map->data[c.r>>1][c.g>>1][c.b>>1]; else table->data[x][y] = bestfit_color(pal, c.r, c.g, c.b); } if (callback) (*callback)(x); } } /* create_blender_table: * Fills the specified color mapping table with lookup data for doing a * paletted equivalent of whatever truecolor blender mode is currently * selected. */ void create_blender_table(COLOR_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) { int x, y, c; int r, g, b; int r1, g1, b1; int r2, g2, b2; ASSERT(_blender_func24); for (x=0; x> 4); g1 = (pal[x].g << 2) | ((pal[x].g & 0x30) >> 4); b1 = (pal[x].b << 2) | ((pal[x].b & 0x30) >> 4); r2 = (pal[y].r << 2) | ((pal[y].r & 0x30) >> 4); g2 = (pal[y].g << 2) | ((pal[y].g & 0x30) >> 4); b2 = (pal[y].b << 2) | ((pal[y].b & 0x30) >> 4); c = _blender_func24(makecol24(r1, g1, b1), makecol24(r2, g2, b2), _blender_alpha); r = getr24(c); g = getg24(c); b = getb24(c); if (rgb_map) table->data[x][y] = rgb_map->data[r>>3][g>>3][b>>3]; else table->data[x][y] = bestfit_color(pal, r>>2, g>>2, b>>2); } if (callback) (*callback)(x); } } allegro-4.4.3.1/src/macosx/0000775000175000017500000000000013437077643014361 5ustar siegesiegeallegro-4.4.3.1/src/macosx/hidjoy.m0000664000175000017500000003042313437077643016027 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * HID Joystick driver routines for MacOS X. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif static int hid_joy_init(void); static void hid_joy_exit(void); static int hid_joy_poll(void); JOYSTICK_DRIVER joystick_hid = { JOYSTICK_HID, // int id; empty_string, // AL_CONST char *name; empty_string, // AL_CONST char *desc; "HID Joystick", // AL_CONST char *ascii_name; hid_joy_init, // AL_METHOD(int, init, (void)); hid_joy_exit, // AL_METHOD(void, exit, (void)); hid_joy_poll, // AL_METHOD(int, poll, (void)); NULL, // AL_METHOD(int, save_data, (void)); NULL, // AL_METHOD(int, load_data, (void)); NULL, // AL_METHOD(AL_CONST char *, calibrate_name, (int n)); NULL // AL_METHOD(int, calibrate, (int n)); }; static HID_DEVICE_COLLECTION hid_devices; /* hid_joy_init: * Initializes the HID joystick driver. */ static int hid_joy_init(void) { static char *name_stick = "stick"; static char *name_hat = "hat"; static char *name_x = "x"; static char *name_y = "y"; static char *name_b[] = { "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15", "B16" }; HID_ELEMENT *element; int i, j; hid_devices.count=hid_devices.capacity=0; hid_devices.devices=NULL; osx_hid_scan(HID_JOYSTICK, &hid_devices); osx_hid_scan(HID_GAMEPAD, &hid_devices); num_joysticks = hid_devices.count > 0 ? hid_devices.devices[hid_devices.count - 1].cur_app : 0; for (i = 0; i < num_joysticks; i++) { memset(&joy[i], 0, sizeof(joy[i])); } for (i=0; itype) { case HID_ELEMENT_BUTTON: if (element->index >= MAX_JOYSTICK_BUTTONS || element->app>=MAX_JOYSTICKS) { element->cookie=0x0; break; } if (element->name) joy[element->app].button[element->index].name = element->name; else joy[element->app].button[element->index].name = name_b[element->index]; joy[element->app].num_buttons++; break; case HID_ELEMENT_AXIS: case HID_ELEMENT_AXIS_PRIMARY_X: case HID_ELEMENT_AXIS_PRIMARY_Y: /* Changes here may need to be duplicated in case below. */ if (element->app>=MAX_JOYSTICKS || element->col>=MAX_JOYSTICK_STICKS || element->index>=MAX_JOYSTICK_AXIS) { element->cookie=0x0; break; } joy[element->app].stick[element->col].name = name_stick; joy[element->app].stick[element->col].num_axis++; if (joy[element->app].num_sticks<(element->col+1)) joy[element->app].num_sticks=element->col+1; joy[element->app].stick[element->col].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; if (element->name) joy[element->app].stick[element->col].axis[element->index].name = element->name; else joy[element->app].stick[element->col].axis[element->index].name = element->index==0 ? name_x : name_y; break; case HID_ELEMENT_STANDALONE_AXIS: /* Changes here may need to be duplicated in case directly above. */ if (element->app>=MAX_JOYSTICKS || element->col>=MAX_JOYSTICK_STICKS || element->index>=MAX_JOYSTICK_AXIS) { element->cookie=0x0; break; } joy[element->app].stick[element->col].name = name_stick; joy[element->app].stick[element->col].num_axis++; if (joy[element->app].num_sticks<(element->col+1)) joy[element->app].num_sticks=element->col+1; joy[element->app].stick[element->col].flags = JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; if (element->name) joy[element->app].stick[element->col].axis[element->index].name = element->name; else joy[element->app].stick[element->col].axis[element->index].name = element->index==0 ? name_x : name_y; break; case HID_ELEMENT_HAT: if (element->app>=MAX_JOYSTICKS || element->col >= MAX_JOYSTICK_STICKS) { element->cookie=0x0; break; } if (joy[element->app].num_sticks<(element->col+1)) joy[element->app].num_sticks=element->col+1; if (element->name) joy[element->app].stick[element->col].name = element->name; else joy[element->app].stick[element->col].name = name_hat; joy[element->app].stick[element->col].num_axis = 2; joy[element->app].stick[element->col].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[element->app].stick[element->col].axis[0].name = name_x; joy[element->app].stick[element->col].axis[1].name = name_y; break; } } } return hid_joy_poll(); } /* hid_joy_exit: * Shuts down the HID joystick driver. */ static void hid_joy_exit(void) { osx_hid_free(&hid_devices); } /* hid_joy_poll: * Polls the active joystick devices and updates internal states. */ static int hid_joy_poll(void) { HID_DEVICE *device; HID_ELEMENT *element; IOHIDEventStruct hid_event; int i, j, pos; if (num_joysticks <= 0) return -1; for (i = 0; i < hid_devices.count; i++) { device = &hid_devices.devices[i]; if (device->interface) { for (j = 0; j < device->num_elements; j++) { element = &device->element[j]; if ((element->cookie==0x0) || (*(device->interface))->getElementValue(device->interface, element->cookie, &hid_event)) continue; switch (element->type) { case HID_ELEMENT_BUTTON: joy[element->app].button[element->index].b = hid_event.value; break; case HID_ELEMENT_AXIS: case HID_ELEMENT_AXIS_PRIMARY_X: case HID_ELEMENT_AXIS_PRIMARY_Y: pos = (((hid_event.value - element->min) * 256) / (element->max - element->min + 1)) - 128; joy[element->app].stick[element->col].axis[element->index].pos = pos; joy[element->app].stick[element->col].axis[element->index].d1 = FALSE; joy[element->app].stick[element->col].axis[element->index].d2 = FALSE; if (pos < 0) joy[element->app].stick[element->col].axis[element->index].d1 = TRUE; else if (pos > 0) joy[element->app].stick[element->col].axis[element->index].d2 = TRUE; break; case HID_ELEMENT_STANDALONE_AXIS: pos = (((hid_event.value - element->min) * 255) / (element->max - element->min + 1)); joy[element->app].stick[element->col].axis[element->index].pos = pos; break; case HID_ELEMENT_HAT: switch (hid_event.value) { case 0: /* up */ joy[element->app].stick[element->col].axis[0].pos = 0; joy[element->app].stick[element->col].axis[0].d1 = 0; joy[element->app].stick[element->col].axis[0].d2 = 0; joy[element->app].stick[element->col].axis[1].pos = -128; joy[element->app].stick[element->col].axis[1].d1 = 1; joy[element->app].stick[element->col].axis[1].d2 = 0; break; case 1: /* up and right */ joy[element->app].stick[element->col].axis[0].pos = 128; joy[element->app].stick[element->col].axis[0].d1 = 0; joy[element->app].stick[element->col].axis[0].d2 = 1; joy[element->app].stick[element->col].axis[1].pos = -128; joy[element->app].stick[element->col].axis[1].d1 = 1; joy[element->app].stick[element->col].axis[1].d2 = 0; break; case 2: /* right */ joy[element->app].stick[element->col].axis[0].pos = 128; joy[element->app].stick[element->col].axis[0].d1 = 0; joy[element->app].stick[element->col].axis[0].d2 = 1; joy[element->app].stick[element->col].axis[1].pos = 0; joy[element->app].stick[element->col].axis[1].d1 = 0; joy[element->app].stick[element->col].axis[1].d2 = 0; break; case 3: /* down and right */ joy[element->app].stick[element->col].axis[0].pos = 128; joy[element->app].stick[element->col].axis[0].d1 = 0; joy[element->app].stick[element->col].axis[0].d2 = 1; joy[element->app].stick[element->col].axis[1].pos = 128; joy[element->app].stick[element->col].axis[1].d1 = 0; joy[element->app].stick[element->col].axis[1].d2 = 1; break; case 4: /* down */ joy[element->app].stick[element->col].axis[0].pos = 0; joy[element->app].stick[element->col].axis[0].d1 = 0; joy[element->app].stick[element->col].axis[0].d2 = 0; joy[element->app].stick[element->col].axis[1].pos = 128; joy[element->app].stick[element->col].axis[1].d1 = 0; joy[element->app].stick[element->col].axis[1].d2 = 1; break; case 5: /* down and left */ joy[element->app].stick[element->col].axis[0].pos = -128; joy[element->app].stick[element->col].axis[0].d1 = 1; joy[element->app].stick[element->col].axis[0].d2 = 0; joy[element->app].stick[element->col].axis[1].pos = 128; joy[element->app].stick[element->col].axis[1].d1 = 0; joy[element->app].stick[element->col].axis[1].d2 = 1; break; case 6: /* left */ joy[element->app].stick[element->col].axis[0].pos = -128; joy[element->app].stick[element->col].axis[0].d1 = 1; joy[element->app].stick[element->col].axis[0].d2 = 0; joy[element->app].stick[element->col].axis[1].pos = 0; joy[element->app].stick[element->col].axis[1].d1 = 0; joy[element->app].stick[element->col].axis[1].d2 = 0; break; case 7: /* up and left */ joy[element->app].stick[element->col].axis[0].pos = -128; joy[element->app].stick[element->col].axis[0].d1 = 1; joy[element->app].stick[element->col].axis[0].d2 = 0; joy[element->app].stick[element->col].axis[1].pos = -128; joy[element->app].stick[element->col].axis[1].d1 = 1; joy[element->app].stick[element->col].axis[1].d2 = 0; break; case 15: /* centered */ joy[element->app].stick[element->col].axis[0].pos = 0; joy[element->app].stick[element->col].axis[0].d1 = 0; joy[element->app].stick[element->col].axis[0].d2 = 0; joy[element->app].stick[element->col].axis[1].pos = 0; joy[element->app].stick[element->col].axis[1].d1 = 0; joy[element->app].stick[element->col].axis[1].d2 = 0; break; } break; } } } } return 0; } /* Local variables: */ /* c-basic-offset: 3 */ /* indent-tabs-mode: nil */ /* End: */ allegro-4.4.3.1/src/macosx/system.m0000664000175000017500000004456213437077643016076 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X system driver. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif #ifndef SCAN_DEPEND #include #include #include #endif /* These are used to warn the dock about the application */ struct CPSProcessSerNum { UInt32 lo; UInt32 hi; }; extern OSErr CPSGetCurrentProcess(struct CPSProcessSerNum *psn); extern OSErr CPSEnableForegroundOperation(struct CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); extern OSErr CPSSetFrontProcess(struct CPSProcessSerNum *psn); static int osx_sys_init(void); static void osx_sys_exit(void); static void osx_sys_message(AL_CONST char *); static void osx_sys_get_executable_name(char *, int); static int osx_sys_find_resource(char *, AL_CONST char *, int); static void osx_sys_set_window_title(AL_CONST char *); static int osx_sys_set_close_button_callback(void (*proc)(void)); static int osx_sys_set_display_switch_mode(int mode); static void osx_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); static int osx_sys_desktop_color_depth(void); static int osx_sys_get_desktop_resolution(int *width, int *height); /* Global variables */ int __crt0_argc; char **__crt0_argv; NSBundle *osx_bundle = NULL; void* osx_event_mutex; NSCursor *osx_cursor = NULL; NSCursor *osx_blank_cursor = NULL; AllegroWindow *osx_window = NULL; char osx_window_title[ALLEGRO_MESSAGE_SIZE]; void (*osx_window_close_hook)(void) = NULL; int osx_gfx_mode = OSX_GFX_NONE; int osx_emulate_mouse_buttons = FALSE; int osx_window_first_expose = FALSE; int osx_skip_events_processing = FALSE; void* osx_skip_events_processing_mutex; static RETSIGTYPE (*old_sig_abrt)(int num); static RETSIGTYPE (*old_sig_fpe)(int num); static RETSIGTYPE (*old_sig_ill)(int num); static RETSIGTYPE (*old_sig_segv)(int num); static RETSIGTYPE (*old_sig_term)(int num); static RETSIGTYPE (*old_sig_int)(int num); static RETSIGTYPE (*old_sig_quit)(int num); static unsigned char *cursor_data = NULL; static NSBitmapImageRep *cursor_rep = NULL; static NSImage *cursor_image = NULL; SYSTEM_DRIVER system_macosx = { SYSTEM_MACOSX, empty_string, empty_string, "MacOS X", osx_sys_init, osx_sys_exit, osx_sys_get_executable_name, osx_sys_find_resource, osx_sys_set_window_title, osx_sys_set_close_button_callback, osx_sys_message, NULL, /* AL_METHOD(void, assert, (AL_CONST char *msg)); */ NULL, /* AL_METHOD(void, save_console_state, (void)); */ NULL, /* AL_METHOD(void, restore_console_state, (void)); */ NULL, /* AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); */ NULL, /* AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); */ NULL, /* AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); */ NULL, /* AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); */ NULL, /* AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(void, read_hardware_palette, (void)); */ NULL, /* AL_METHOD(void, set_palette_range, (AL_CONST struct RGB *p, int from, int to, int retracesync)); */ NULL, /* AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); */ osx_sys_set_display_switch_mode, NULL, /* AL_METHOD(void, display_switch_lock, (int lock, int foreground)); */ osx_sys_desktop_color_depth, osx_sys_get_desktop_resolution, osx_sys_get_gfx_safe_mode, _unix_yield_timeslice, _unix_create_mutex, _unix_destroy_mutex, _unix_lock_mutex, _unix_unlock_mutex, NULL, /* AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); */ }; /* osx_signal_handler: * Used to trap various signals, to make sure things get shut down cleanly. */ static RETSIGTYPE osx_signal_handler(int num) { _unix_unlock_mutex(osx_event_mutex); _unix_unlock_mutex(osx_window_mutex); allegro_exit(); _unix_destroy_mutex(osx_event_mutex); _unix_destroy_mutex(osx_window_mutex); fprintf(stderr, "Shutting down Allegro due to signal #%d\n", num); raise(num); } /* osx_event_handler: * Event handling function; gets repeatedly called inside a dedicated thread. */ void osx_event_handler() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSEvent *event; NSDate *distant_past = [NSDate distantPast]; NSPoint point; NSRect frame, view; int dx = 0, dy = 0, dz = 0; int mx=_mouse_x; int my=_mouse_y; static int buttons = 0; int event_type; BOOL gotmouseevent = NO; while ((event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: distant_past inMode: NSDefaultRunLoopMode dequeue: YES]) != nil) { _unix_lock_mutex(osx_skip_events_processing_mutex); int skip_events_processing = osx_skip_events_processing; _unix_unlock_mutex(osx_skip_events_processing_mutex); if ((skip_events_processing) || (osx_gfx_mode == OSX_GFX_NONE)) { [NSApp sendEvent: event]; continue; } view = NSMakeRect(0, 0, gfx_driver->w, gfx_driver->h); point = [event locationInWindow]; if (osx_window) { frame = [[osx_window contentView] frame]; } else { frame = [[NSScreen mainScreen] frame]; } event_type = [event type]; switch (event_type) { case NSKeyDown: if (_keyboard_installed) osx_keyboard_handler(TRUE, event); if ([event modifierFlags] & NSCommandKeyMask) [NSApp sendEvent: event]; break; case NSKeyUp: if (_keyboard_installed) osx_keyboard_handler(FALSE, event); if ([event modifierFlags] & NSCommandKeyMask) [NSApp sendEvent: event]; break; case NSFlagsChanged: if (_keyboard_installed) osx_keyboard_modifiers([event modifierFlags]); break; case NSLeftMouseDown: case NSOtherMouseDown: case NSRightMouseDown: if (![NSApp isActive]) { /* App is regaining focus */ if (_mouse_installed) { if ((osx_window) && (NSPointInRect(point, view))) { mx = point.x; my = frame.size.height - point.y; buttons = 0; _mouse_on = TRUE; } } if (osx_window) [osx_window invalidateCursorRectsForView: [osx_window contentView]]; if (_keyboard_installed) osx_keyboard_focused(TRUE, 0); _switch_in(); gotmouseevent = YES; [NSApp sendEvent: event]; break; } /* fallthrough */ case NSLeftMouseUp: case NSOtherMouseUp: case NSRightMouseUp: if (osx_emulate_mouse_buttons) { if (event_type == NSLeftMouseDown) { if ((!osx_window) || (NSPointInRect(point, view))) { buttons = 0x1; if (key[KEY_ALT]) buttons = 0x4; if (key[KEY_LCONTROL]) buttons = 0x2; } } else if (event_type == NSLeftMouseUp) buttons &= ~0x7; } else { if ((!osx_window) || (NSPointInRect(point, view))) { /* Deliver mouse downs only if cursor is on the window */ buttons |= ((event_type == NSLeftMouseDown) ? 0x1 : 0); buttons |= ((event_type == NSRightMouseDown) ? 0x2 : 0); buttons |= ((event_type == NSOtherMouseDown) ? 0x4 : 0); } buttons &= ~((event_type == NSLeftMouseUp) ? 0x1 : 0); buttons &= ~((event_type == NSRightMouseUp) ? 0x2 : 0); buttons &= ~((event_type == NSOtherMouseUp) ? 0x4 : 0); } gotmouseevent = YES; [NSApp sendEvent: event]; break; case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: case NSMouseMoved: dx += [event deltaX]; dy += [event deltaY]; mx=point.x; my=frame.size.height-point.y; [NSApp sendEvent: event]; gotmouseevent = YES; break; case NSScrollWheel: dz += [event deltaY]; gotmouseevent = YES; break; case NSMouseEntered: if (([event trackingNumber] == osx_mouse_tracking_rect) && ([NSApp isActive])) { if (_mouse_installed) { mx = point.x; my = frame.size.height - point.y; buttons = 0; _mouse_on = TRUE; gotmouseevent = YES; } } [NSApp sendEvent: event]; break; case NSMouseExited: if ([event trackingNumber] == osx_mouse_tracking_rect) { if (_mouse_installed) { _mouse_on = FALSE; gotmouseevent = YES; } } [NSApp sendEvent: event]; break; case NSAppKitDefined: switch ([event subtype]) { case NSApplicationActivatedEventType: if (osx_window) { [osx_window invalidateCursorRectsForView: [osx_window contentView]]; if (_keyboard_installed) osx_keyboard_focused(TRUE, 0); } _switch_in(); break; case NSApplicationDeactivatedEventType: if (osx_window && _keyboard_installed) osx_keyboard_focused(FALSE, 0); _switch_out(); break; case NSWindowMovedEventType: /* This is needed to ensure the shadow gets drawn when the window is * created. It's weird, but when the window is created on another * thread, sometimes its shadow doesn't get drawn. The same applies * to the cursor rectangle, which doesn't seem to be set at window * creation (it works once you move the mouse though). */ if ((osx_window) && (osx_window_first_expose)) { osx_window_first_expose = FALSE; [osx_window setHasShadow: NO]; [osx_window setHasShadow: YES]; [osx_window invalidateCursorRectsForView: [osx_window contentView]]; } break; } [NSApp sendEvent: event]; break; default: [NSApp sendEvent: event]; break; } } if (gotmouseevent == YES) osx_mouse_handler(mx, my, dx, dy, dz, buttons); [pool release]; } /* osx_tell_dock: * Tell the dock about us; the origins of this hack are unknown, but it's * currently the only way to make a Cocoa app to work when started from a * console. * For the future, (10.3 and above) investigate TranformProcessType in the * HIServices framework. */ static void osx_tell_dock(void) { struct CPSProcessSerNum psn; if ((!CPSGetCurrentProcess(&psn)) && (!CPSEnableForegroundOperation(&psn, 0x03, 0x3C, 0x2C, 0x1103)) && (!CPSSetFrontProcess(&psn))) [NSApplication sharedApplication]; } /* osx_bootstrap_ok: * Check if the current bootstrap context is privilege. If it's not, we can't * use NSApplication, and instead have to go directly to main. * Returns 1 if ok, 0 if not. */ int osx_bootstrap_ok(void) { static int _ok = -1; mach_port_t bp; kern_return_t ret; CFMachPortRef cfport; /* If have tested once, just return that answer */ if (_ok >= 0) return _ok; cfport = CFMachPortCreate(NULL, NULL, NULL, NULL); task_get_bootstrap_port(mach_task_self(), &bp); ret = bootstrap_register(bp, "bootstrap-ok-test", CFMachPortGetPort(cfport)); CFRelease(cfport); _ok = (ret == KERN_SUCCESS) ? 1 : 0; return _ok; } /* osx_sys_init: * Initalizes the MacOS X system driver. */ static int osx_sys_init(void) { long result; /* If we're in the 'dead bootstrap' environment, the Mac driver won't work. */ if (!osx_bootstrap_ok()) { return -1; } /* Install emergency-exit signal handlers */ old_sig_abrt = signal(SIGABRT, osx_signal_handler); old_sig_fpe = signal(SIGFPE, osx_signal_handler); old_sig_ill = signal(SIGILL, osx_signal_handler); old_sig_segv = signal(SIGSEGV, osx_signal_handler); old_sig_term = signal(SIGTERM, osx_signal_handler); old_sig_int = signal(SIGINT, osx_signal_handler); old_sig_quit = signal(SIGQUIT, osx_signal_handler); if (osx_bundle == NULL) { /* If in a bundle, the dock will recognise us automatically */ osx_tell_dock(); } /* Setup OS type & version */ os_type = OSTYPE_MACOSX; Gestalt(gestaltSystemVersion, &result); os_version = (((result >> 12) & 0xf) * 10) + ((result >> 8) & 0xf); os_revision = (result >> 4) & 0xf; os_multitasking = TRUE; /* Setup a blank cursor */ cursor_data = calloc(1, 16 * 16 * 4); cursor_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &cursor_data pixelsWide: 16 pixelsHigh: 16 bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 64 bitsPerPixel: 32]; cursor_image = [[NSImage alloc] initWithSize: NSMakeSize(16, 16)]; [cursor_image addRepresentation: cursor_rep]; osx_blank_cursor = [[NSCursor alloc] initWithImage: cursor_image hotSpot: NSMakePoint(0, 0)]; osx_cursor = osx_blank_cursor; osx_gfx_mode = OSX_GFX_NONE; set_display_switch_mode(SWITCH_BACKGROUND); set_window_title([[[NSProcessInfo processInfo] processName] cString]); return 0; } /* osx_sys_exit: * Shuts down the system driver. */ static void osx_sys_exit(void) { signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); signal(SIGQUIT, old_sig_quit); if (osx_blank_cursor) [osx_blank_cursor release]; if (cursor_image) [cursor_image release]; if (cursor_rep) [cursor_rep release]; if (cursor_data) free(cursor_data); osx_cursor = NULL; cursor_image = NULL; cursor_rep = NULL; cursor_data = NULL; } /* osx_sys_get_executable_name: * Returns the full path to the application executable name. Note that if the * exe is inside a bundle, this returns the full path of the bundle. */ static void osx_sys_get_executable_name(char *output, int size) { if (osx_bundle) do_uconvert([[osx_bundle bundlePath] lossyCString], U_ASCII, output, U_CURRENT, size); else do_uconvert(__crt0_argv[0], U_ASCII, output, U_CURRENT, size); } /* osx_sys_find_resource: * Searches the resource in the bundle resource path if the app is in a * bundle, otherwise calls the unix resource finder routine. */ static int osx_sys_find_resource(char *dest, AL_CONST char *resource, int size) { const char *path; char buf[256], tmp[256]; if (osx_bundle) { path = [[osx_bundle resourcePath] cString]; append_filename(buf, uconvert_ascii(path, tmp), resource, sizeof(buf)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } } return _unix_find_resource(dest, resource, size); } /* osx_sys_message: * Displays a message using an alert panel. */ static void osx_sys_message(AL_CONST char *msg) { char tmp[ALLEGRO_MESSAGE_SIZE]; NSString *ns_title, *ns_msg; fputs(uconvert_toascii(msg, tmp), stderr); do_uconvert(msg, U_CURRENT, tmp, U_UTF8, ALLEGRO_MESSAGE_SIZE); ns_title = [NSString stringWithUTF8String: osx_window_title]; ns_msg = [NSString stringWithUTF8String: tmp]; NSRunAlertPanel(ns_title, ns_msg, nil, nil, nil); } /* osx_sys_set_window_title: * Sets the title for both the application menu and the window if present. */ static void osx_sys_set_window_title(AL_CONST char *title) { char tmp[ALLEGRO_MESSAGE_SIZE]; if (osx_window_title != title) _al_sane_strncpy(osx_window_title, title, ALLEGRO_MESSAGE_SIZE); do_uconvert(title, U_CURRENT, tmp, U_UTF8, ALLEGRO_MESSAGE_SIZE); NSString *ns_title = [NSString stringWithUTF8String: tmp]; if (osx_window) [osx_window setTitle: ns_title]; } /* osx_sys_set_close_button_callback: * Sets the window close callback. Also used when user hits Command-Q or * selects "Quit" from the application menu. */ static int osx_sys_set_close_button_callback(void (*proc)(void)) { osx_window_close_hook = proc; return 0; } /* osx_sys_set_display_switch_mode: * Sets the current display switch mode. */ static int osx_sys_set_display_switch_mode(int mode) { if (mode != SWITCH_BACKGROUND) return -1; return 0; } /* osx_sys_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void osx_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_QUARTZ_WINDOW; mode->width = 320; mode->height = 200; mode->bpp = 8; } /* osx_sys_desktop_color_depth: * Queries the desktop color depth. */ static int osx_sys_desktop_color_depth(void) { CFDictionaryRef mode = NULL; int color_depth; mode = CGDisplayCurrentMode(kCGDirectMainDisplay); if (!mode) return -1; CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel), kCFNumberSInt32Type, &color_depth); return color_depth == 16 ? 15 : color_depth; } /* osx_sys_get_desktop_resolution: * Queries the desktop resolution. */ static int osx_sys_get_desktop_resolution(int *width, int *height) { CFDictionaryRef mode = NULL; mode = CGDisplayCurrentMode(kCGDirectMainDisplay); if (!mode) return -1; CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayWidth), kCFNumberSInt32Type, width); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayHeight), kCFNumberSInt32Type, height); return 0; } allegro-4.4.3.1/src/macosx/pcpu.m0000664000175000017500000000175713437077643015520 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PowerPC CPU detection routines, by Peter Hull. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifndef SCAN_DEPEND #include #endif void check_cpu() { const NXArchInfo* info=NXGetLocalArchInfo(); cpu_family=info->cputype; cpu_model=info->cpusubtype; cpu_capabilities=CPU_ID|CPU_FPU; /* confident that this info is correct */ do_uconvert(info->name, U_ASCII, cpu_vendor, U_CURRENT, _AL_CPU_VENDOR_SIZE); } allegro-4.4.3.1/src/macosx/qzmouse.m0000664000175000017500000002454013437077643016247 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X mouse driver. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error Something is wrong with the makefile #endif static int osx_mouse_init(void); static void osx_mouse_exit(void); static void osx_mouse_position(int, int); static void osx_mouse_set_range(int, int, int, int); static void osx_mouse_get_mickeys(int *, int *); static void osx_enable_hardware_cursor(AL_CONST int mode); static int osx_select_system_cursor(AL_CONST int cursor); MOUSE_DRIVER mouse_macosx = { MOUSE_MACOSX, empty_string, empty_string, "MacOS X mouse", osx_mouse_init, osx_mouse_exit, NULL, // AL_METHOD(void, poll, (void)); NULL, // AL_METHOD(void, timer_poll, (void)); osx_mouse_position, osx_mouse_set_range, NULL, // AL_METHOD(void, set_speed, (int xspeed, int yspeed)); osx_mouse_get_mickeys, NULL, // AL_METHOD(int, analyse_data, (AL_CONST char *buffer, int size)); osx_enable_hardware_cursor, osx_select_system_cursor }; /* global variable */ int osx_mouse_warped = FALSE; int osx_skip_mouse_move = FALSE; NSTrackingRectTag osx_mouse_tracking_rect = -1; static NSCursor *cursor = NULL, *current_cursor = NULL; static NSCursor *requested_cursor = NULL; static unsigned char *cursor_data = NULL; static NSBitmapImageRep *cursor_rep = NULL; static NSImage *cursor_image = NULL; static int mouse_minx = 0; static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int mymickey_x = 0; static int mymickey_y = 0; static char driver_desc[256]; /* osx_change_cursor: * Actually change the current cursor. This can be called fom any thread * but ensures that the change is only called from the main thread. */ static void osx_change_cursor(NSCursor* cursor) { _unix_lock_mutex(osx_event_mutex); osx_cursor = cursor; _unix_unlock_mutex(osx_event_mutex); [cursor performSelectorOnMainThread: @selector(set) withObject: nil waitUntilDone: NO]; } /* osx_mouse_handler: * Mouse "interrupt" handler for mickey-mode driver. */ void osx_mouse_handler(int ax, int ay, int x, int y, int z, int buttons) { if (!_mouse_on) mymickey_x = mymickey_y = 0; if ((!_mouse_installed) || (!_mouse_on) || (osx_gfx_mode == OSX_GFX_NONE)) return; if (osx_cursor != current_cursor) { if (osx_window) { NSView* vw = [osx_window contentView]; [osx_window invalidateCursorRectsForView: vw]; } else { [osx_cursor set]; } current_cursor = osx_cursor; } if (osx_mouse_warped) { osx_mouse_warped = FALSE; return; } _mouse_b = buttons; mymickey_x += x; mymickey_y += y; _mouse_x = ax; _mouse_y = ay; _mouse_z += z; _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); _handle_mouse_input(); } /* osx_mouse_init: * Initializes the mickey-mode driver. */ static int osx_mouse_init(void) { HID_DEVICE_COLLECTION devices={0,0,NULL}; int i, j; int buttons, max_buttons = -1; HID_DEVICE* device; if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) { /* On 10.1.x mice and keyboards aren't available from the HID Manager, * so we can't autodetect. We assume an 1-button mouse to always be * present. */ max_buttons = 1; } else { osx_hid_scan(HID_MOUSE, &devices); for (i = 0; i < devices.count; i++) { device=&devices.devices[i]; buttons = 0; for (j = 0; j < device->num_elements; j++) { if (device->element[j].type == HID_ELEMENT_BUTTON) buttons++; } if (buttons > max_buttons) { max_buttons = buttons; _al_sane_strncpy(driver_desc, "", sizeof(driver_desc)); if (device->manufacturer) { strncat(driver_desc, device->manufacturer, sizeof(driver_desc)-1); strncat(driver_desc, " ", sizeof(driver_desc)-1); } if (device->product) strncat(driver_desc, device->product, sizeof(driver_desc)-1); mouse_macosx.desc = driver_desc; } } osx_hid_free(&devices); } _unix_lock_mutex(osx_event_mutex); osx_emulate_mouse_buttons = (max_buttons == 1) ? TRUE : FALSE; _unix_unlock_mutex(osx_event_mutex); return max_buttons; } /* osx_mouse_exit: * Shuts down the mickey-mode driver. */ static void osx_mouse_exit(void) { osx_cursor = osx_blank_cursor; if (cursor) [cursor release]; if (cursor_image) [cursor_image release]; if (cursor_rep) [cursor_rep release]; if (cursor_data) free(cursor_data); cursor = NULL; cursor_image = NULL; cursor_rep = NULL; cursor_data = NULL; } /* osx_mouse_position: * Sets the position of the mickey-mode mouse. */ static void osx_mouse_position(int x, int y) { CGPoint point; NSRect frame; int screen_height; _unix_lock_mutex(osx_event_mutex); _mouse_x = point.x = x; _mouse_y = point.y = y; if (osx_window) { CFNumberGetValue(CFDictionaryGetValue(CGDisplayCurrentMode(kCGDirectMainDisplay), kCGDisplayHeight), kCFNumberSInt32Type, &screen_height); frame = [osx_window frame]; point.x += frame.origin.x; point.y += (screen_height - (frame.origin.y + gfx_driver->h)); } CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, point); mymickey_x = mymickey_y = 0; osx_mouse_warped = TRUE; _unix_unlock_mutex(osx_event_mutex); } /* osx_mouse_set_range: * Sets the range of the mickey-mode mouse. */ static void osx_mouse_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; osx_mouse_position(CLAMP(mouse_minx, _mouse_x, mouse_maxx), CLAMP(mouse_miny, _mouse_y, mouse_maxy)); } /* osx_mouse_get_mickeys: * Reads the mickey-mode count. */ static void osx_mouse_get_mickeys(int *mickeyx, int *mickeyy) { _unix_lock_mutex(osx_event_mutex); *mickeyx = mymickey_x; *mickeyy = mymickey_y; mymickey_x = mymickey_y = 0; _unix_unlock_mutex(osx_event_mutex); } /* osx_mouse_set_sprite: * Sets the hardware cursor sprite. */ int osx_mouse_set_sprite(BITMAP *sprite, int x, int y) { int ix, iy; int sw, sh; if (!sprite) return -1; sw = sprite->w; sh = sprite->h; if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_2) { // Before MacOS X 10.3, NSCursor can handle only 16x16 cursor sprites // Pad to 16x16 or fail if the sprite is already larger. if (sw>16 || sh>16) return -1; sh = sw = 16; } // Delete the old cursor (OK to send a message to nil) [cursor release]; NSBitmapImageRep* cursor_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL pixelsWide: sw pixelsHigh: sh bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 0 bitsPerPixel: 0]; int bpp = bitmap_color_depth(sprite); int mask = bitmap_mask_color(sprite); for (iy = 0; iy< sh; ++iy) { unsigned char* ptr = [cursor_rep bitmapData] + (iy * [cursor_rep bytesPerRow]); for (ix = 0; ix< sw; ++ix) { int color = is_inside_bitmap(sprite, ix, iy, 1) ? getpixel(sprite, ix, iy) : mask; // Disable the possibility of mouse sprites with alpha for now, because // this causes the built-in cursors to be invisible in 32 bit mode. // int alpha = (color == mask) ? 0 : ((bpp == 32) ? geta_depth(bpp, color) : 255); int alpha = (color == mask) ? 0 : 255; // BitmapImageReps use premultiplied alpha ptr[0] = getb_depth(bpp, color) * alpha / 255; ptr[1] = getg_depth(bpp, color) * alpha / 255; ptr[2] = getr_depth(bpp, color) * alpha / 255; ptr[3] = alpha; ptr += 4; } } NSImage* cursor_image = [[NSImage alloc] initWithSize: NSMakeSize(sw, sh)]; [cursor_image addRepresentation: cursor_rep]; [cursor_rep release]; cursor = [[NSCursor alloc] initWithImage: cursor_image hotSpot: NSMakePoint(x, y)]; [cursor_image release]; osx_change_cursor(requested_cursor = cursor); return 0; } /* osx_mouse_show: * Show the hardware cursor. */ int osx_mouse_show(BITMAP *bmp, int x, int y) { /* Only draw on screen */ if (!is_same_bitmap(bmp, screen)) return -1; if (!requested_cursor) return -1; osx_change_cursor(requested_cursor); return 0; } /* osx_mouse_hide: * Hide the hardware cursor. */ void osx_mouse_hide(void) { osx_change_cursor(osx_blank_cursor); } /* osx_mouse_move: * Get mouse move notification. Not that we need it... */ void osx_mouse_move(int x, int y) { } /* osx_enable_hardware_cursor: * Enable hardware cursor - on OSX it's always enabled. */ void osx_enable_hardware_cursor(AL_CONST int mode) { (void)mode; } /* osx_select_system_cursor: * Select a system cursor - on this platform, only the I-beam and the Arrow * are available as system cursors. */ static int osx_select_system_cursor(AL_CONST int cursor) { switch (cursor) { case MOUSE_CURSOR_ARROW: requested_cursor = [NSCursor arrowCursor]; break; case MOUSE_CURSOR_EDIT: requested_cursor = [NSCursor IBeamCursor]; break; default: return 0; } osx_change_cursor(requested_cursor); return cursor; } /* Local variables: */ /* c-basic-offset: 3 */ /* indent-tabs-mode: nil */ /* End: */ allegro-4.4.3.1/src/macosx/main.m0000664000175000017500000002204113437077643015462 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * main() function replacement for MacOS X. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif #include "allegro/internal/alconfig.h" #undef main /* For compatibility with the unix code */ extern int __crt0_argc; extern char **__crt0_argv; extern void *_mangled_main_address; static char *arg0, *arg1 = NULL; static int refresh_rate = 70; static volatile BOOL ready_to_terminate = NO; static BOOL in_bundle(void) { /* This comes from the ADC tips & tricks section: how to detect if the app * lives inside a bundle */ FSRef processRef; ProcessSerialNumber psn = { 0, kCurrentProcess }; FSCatalogInfo processInfo; GetProcessBundleLocation(&psn, &processRef); FSGetCatalogInfo(&processRef, kFSCatInfoNodeFlags, &processInfo, NULL, NULL, NULL); if (processInfo.nodeFlags & kFSNodeIsDirectoryMask) return YES; else return NO; } @implementation AllegroAppDelegate - (BOOL)application: (NSApplication *)theApplication openFile: (NSString *)filename { arg1 = strdup([filename lossyCString]); return YES; } /* applicationDidFinishLaunching: * Called when the app is ready to run. This runs the system events pump and * updates the app window if it exists. */ - (void)applicationDidFinishLaunching: (NSNotification *)aNotification { NSAutoreleasePool *pool = NULL; CFDictionaryRef mode; NSString* exename, *resdir; NSFileManager* fm; BOOL isDir; /* create mutex */ osx_event_mutex = _unix_create_mutex(); osx_skip_events_processing_mutex = _unix_create_mutex(); pool = [[NSAutoreleasePool alloc] init]; if (in_bundle() == YES) { /* In a bundle, so chdir to the containing directory, * or to the 'magic' resource directory if it exists. * (see the readme.osx file for more info) */ osx_bundle = [NSBundle mainBundle]; exename = [[osx_bundle executablePath] lastPathComponent]; resdir = [[osx_bundle resourcePath] stringByAppendingPathComponent: exename]; fm = [NSFileManager defaultManager]; if ([fm fileExistsAtPath: resdir isDirectory: &isDir] && isDir) { /* Yes, it exists inside the bundle */ [fm changeCurrentDirectoryPath: resdir]; } else { /* No, change to the 'standard' OSX resource directory if it exists*/ if ([fm fileExistsAtPath: [osx_bundle resourcePath] isDirectory: &isDir] && isDir) { [fm changeCurrentDirectoryPath: [osx_bundle resourcePath]]; } /* It doesn't exist - this is unusual for a bundle. Don't chdir */ } arg0 = strdup([[osx_bundle bundlePath] fileSystemRepresentation]); if (arg1) { static char *args[2]; args[0] = arg0; args[1] = arg1; __crt0_argv = args; __crt0_argc = 2; } else { __crt0_argv = &arg0; __crt0_argc = 1; } } /* else: not in a bundle so don't chdir */ mode = CGDisplayCurrentMode(kCGDirectMainDisplay); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberSInt32Type, &refresh_rate); if (refresh_rate <= 0) refresh_rate = 70; [NSThread detachNewThreadSelector: @selector(app_main:) toTarget: [AllegroAppDelegate class] withObject: nil]; while (!ready_to_terminate) { if (osx_gfx_mode == OSX_GFX_WINDOW) osx_update_dirty_lines(); _unix_lock_mutex(osx_event_mutex); if (osx_gfx_mode == OSX_GFX_FULL) { if ((osx_palette) && (osx_palette_dirty)) { CGDisplaySetPalette(kCGDirectMainDisplay, osx_palette); osx_palette_dirty = FALSE; } } osx_event_handler(); _unix_unlock_mutex(osx_event_mutex); usleep(1000000 / refresh_rate); } [pool release]; _unix_destroy_mutex(osx_event_mutex); [NSApp terminate:self]; } /* applicationDidChangeScreenParameters: * Invoked when the screen did change resolution/color depth. */ - (void)applicationDidChangeScreenParameters: (NSNotification *)aNotification { CFDictionaryRef mode; int new_refresh_rate; if ((osx_window) && (osx_gfx_mode == OSX_GFX_WINDOW)) { osx_setup_colorconv_blitter(); [osx_window display]; } mode = CGDisplayCurrentMode(kCGDirectMainDisplay); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberSInt32Type, &new_refresh_rate); if (new_refresh_rate <= 0) new_refresh_rate = 70; refresh_rate = new_refresh_rate; } /* Call the user main() */ static void call_user_main(void) { int (*real_main)(int, char*[]) = (int (*)(int, char*[])) _mangled_main_address; real_main(__crt0_argc, __crt0_argv); allegro_exit(); ready_to_terminate = YES; } /* app_main: * Thread dedicated to the user program; real main() gets called here. */ + (void)app_main: (id)arg { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; call_user_main(); [pool release]; } /* applicationShouldTerminate: * Called upon Command-Q or "Quit" menu item selection. * If the window close callback is set, calls it, otherwise does * not exit. */ - (NSApplicationTerminateReply) applicationShouldTerminate: (id)sender { if (ready_to_terminate) { return NSTerminateNow; } else { if (osx_window_close_hook) osx_window_close_hook(); return NSTerminateCancel; } } /* quitAction: * This is connected to the Quit menu. The menu sends this message to the * delegate, rather than sending terminate: directly to NSApp, so that we get a * chance to validate the menu item first. */ - (void) quitAction: (id) sender { [NSApp terminate: self]; } /* validateMenuItem: * If the user has not set a window close hook, return NO from this function so * that the Quit menu item is greyed out. */ - (BOOL) validateMenuItem: (NSMenuItem*) item { if ([item action] == @selector(quitAction:)) { return (osx_window_close_hook == NULL) ? NO : YES; } /* Default, all other items are valid (there are none at the moment */ return YES; } /* end of AllegroAppDelegate implementation */ @end /* This prevents warnings that 'NSApplication might not * respond to setAppleMenu' on OS X 10.4 */ @interface NSApplication(AllegroOSX) - (void)setAppleMenu:(NSMenu *)menu; @end /* main: * Replacement for main function. */ int main(int argc, char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; AllegroAppDelegate *app_delegate = [[AllegroAppDelegate alloc] init]; NSMenu *menu; NSMenuItem *menu_item, *temp_item; /* I don't know what that NSAutoreleasePool line does but the variable was * otherwise unused --pw */ (void)pool; __crt0_argc = argc; __crt0_argv = argv; if (!osx_bootstrap_ok()) /* not safe to use NSApplication */ call_user_main(); [NSApplication sharedApplication]; /* Load the main menu nib if possible */ if ((!in_bundle()) || ([NSBundle loadNibNamed: @"MainMenu" owner: NSApp] == NO)) { /* Didn't load the nib; create a default menu programmatically */ NSString* title = nil; NSDictionary* app_dictionary = [[NSBundle mainBundle] infoDictionary]; if (app_dictionary) { title = [app_dictionary objectForKey: @"CFBundleName"]; } if (title == nil) { title = [[NSProcessInfo processInfo] processName]; } [NSApp setMainMenu: [[NSMenu allocWithZone: [NSMenu menuZone]] initWithTitle: @"temp"]]; menu = [[NSMenu allocWithZone: [NSMenu menuZone]] initWithTitle: @"temp"]; temp_item = [[NSMenuItem allocWithZone: [NSMenu menuZone]] initWithTitle: @"temp" action: NULL keyEquivalent: @""]; [[NSApp mainMenu] addItem: temp_item]; [[NSApp mainMenu] setSubmenu: menu forItem: temp_item]; [NSApp setAppleMenu: menu]; NSString *quit = [@"Quit " stringByAppendingString: title]; menu_item = [[NSMenuItem allocWithZone: [NSMenu menuZone]] initWithTitle: quit action: @selector(quitAction:) keyEquivalent: @"q"]; [menu_item setKeyEquivalentModifierMask: NSCommandKeyMask]; [menu_item setTarget: app_delegate]; [menu addItem: menu_item]; } [NSApp setDelegate: app_delegate]; [NSApp run]; /* Can never get here */ return 0; } /* Local variables: */ /* c-basic-offset: 3 */ /* indent-tabs-mode: nil */ /* c-file-style: "linux" */ /* End: */ allegro-4.4.3.1/src/macosx/qtmidi.m0000664000175000017500000002006413437077643016030 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QuickTime MIDI driver routines for MacOS X. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif typedef struct MIDI_VOICE { NoteChannel channel; int note; int bend; int inst; int vol; int pan; } MIDI_VOICE; static NoteAllocator note_allocator = NULL; static MIDI_VOICE voice[17]; static char driver_desc[256]; static int osx_midi_detect(int input); static int osx_midi_init(int input, int voices); static void osx_midi_exit(int input); static int osx_midi_set_mixer_volume(int volume); static void osx_midi_key_on(int inst, int note, int bend, int vol, int pan); static void osx_midi_key_off(int voice); static void osx_midi_set_volume(int voice, int vol); static void osx_midi_set_pitch(int voice, int note, int bend); static void osx_midi_set_pan(int voice, int pan); MIDI_DRIVER midi_quicktime = { MIDI_QUICKTIME, /* driver ID code */ empty_string, /* driver name */ empty_string, /* description string */ "QuickTime MIDI", /* ASCII format name string */ 16, /* available voices */ 0, /* voice number offset */ 16, /* maximum voices we can support */ 0, /* default number of voices to use */ 10, 10, /* reserved voice range */ osx_midi_detect, /* AL_METHOD(int, detect, (int input)); */ osx_midi_init, /* AL_METHOD(int, init, (int input, int voices)); */ osx_midi_exit, /* AL_METHOD(void, exit, (int input)); */ osx_midi_set_mixer_volume, /* AL_METHOD(int, set_mixer_volume, (int volume)); */ NULL, /* AL_METHOD(int, get_mixer_volume, (void)); */ NULL, /* AL_METHOD(void, raw_midi, (int data)); */ _dummy_load_patches, /* AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ _dummy_adjust_patches, /* AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ osx_midi_key_on, /* AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); */ osx_midi_key_off, /* AL_METHOD(void, key_off, (int voice)); */ osx_midi_set_volume, /* AL_METHOD(void, set_volume, (int voice, int vol)); */ osx_midi_set_pitch, /* AL_METHOD(void, set_pitch, (int voice, int note, int bend)); */ osx_midi_set_pan, /* AL_METHOD(void, set_pan, (int voice, int pan)); */ _dummy_noop2, /* AL_METHOD(void, set_vibrato, (int voice, int amount)); */ }; /* osx_midi_detect: * QuickTime Music MIDI detection. */ static int osx_midi_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } note_allocator = OpenDefaultComponent(kNoteAllocatorComponentType, 0); if (!note_allocator) return FALSE; CloseComponent(note_allocator); return TRUE; } /* osx_midi_init: * Initializes the QuickTime Music MIDI driver. */ static int osx_midi_init(int input, int voices) { NoteRequest note_request; ComponentResult result; char tmp[256]; int i; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } note_allocator = OpenDefaultComponent(kNoteAllocatorComponentType, 0); if(!note_allocator) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot open the NoteAllocator QuickTime component")); return -1; } memset(voice, 0, 17 * sizeof(MIDI_VOICE)); for(i = 1; i <= 16; i++) { voice[i].note = -1; voice[i].bend = -1; voice[i].inst = -1; voice[i].vol = -1; voice[i].pan = -1; memset(¬e_request, 0, sizeof(note_request)); #if TARGET_RT_BIG_ENDIAN note_request.info.polyphony = 8; note_request.info.typicalPolyphony = 0x00010000; #else note_request.info.polyphony.bigEndianValue = EndianU16_NtoB(8); note_request.info.typicalPolyphony.bigEndianValue = EndianS32_NtoB(X2Fix(1.0)); #endif result = NAStuffToneDescription(note_allocator, 1, ¬e_request.tone); result |= NANewNoteChannel(note_allocator, ¬e_request, &voice[i].channel); result |= NAResetNoteChannel(note_allocator, voice[i].channel); if ((result) || (!voice[i].channel)) { osx_midi_exit(input); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed initializing MIDI channels")); return -1; } } uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("QuickTime Music MIDI synthesizer", tmp)); midi_quicktime.desc = driver_desc; return 0; } /* osx_midi_exit: * Shuts down QuickTime Music MIDI subsystem. */ static void osx_midi_exit(int input) { int i; if (input) return; if (note_allocator) { for(i = 1; i <= 16; i++) { if (voice[i].channel) { NAPlayNote(note_allocator, voice[i].channel, voice[i].note, 0); NADisposeNoteChannel(note_allocator, voice[i].channel); voice[i].channel = 0; } } CloseComponent(note_allocator); } } /* osx_midi_set_mixer_volume: * Sets QuickTime Music MIDI volume multiplier for all channels. */ static int osx_midi_set_mixer_volume(int volume) { int i; for (i = 1; i <= 16; i++) { if (NASetNoteChannelVolume(note_allocator, voice[i].channel, volume << 8)) return -1; } return 0; } /* osx_midi_key_on: * Triggers a specified voice. */ static void osx_midi_key_on(int inst, int note, int bend, int vol, int pan) { int voice_id; NoteChannel channel; if (inst > 127) { /* Percussion */ note = inst - 128; inst = kFirstDrumkit + 1; } else inst = kFirstGMInstrument + inst; voice_id = _midi_allocate_voice(1, 16); if (voice_id < 0) return; channel = voice[voice_id].channel; if (voice[voice_id].inst != inst) { if (NASetInstrumentNumber(note_allocator, channel, inst) != noErr) return; voice[voice_id].inst = inst; } NAPlayNote(note_allocator, channel, voice[voice_id].note, 0); if (NAPlayNote(note_allocator, channel, note, vol) != noErr) return; voice[voice_id].note = note; osx_midi_set_pitch(voice_id, note, bend); osx_midi_set_pan(voice_id, pan); } /* osx_midi_key_off: * Turns off specified voice. */ static void osx_midi_key_off(int voice_id) { NAPlayNote(note_allocator, voice[voice_id].channel, voice[voice_id].note, 0); } /* osx_midi_set_volume: * Sets volume for a specified voice. */ static void osx_midi_set_volume(int voice_id, int vol) { if (voice[voice_id].vol != vol) { if (NASetController(note_allocator, voice[voice_id].channel, kControllerVolume, vol << 7) == noErr) voice[voice_id].vol = vol; } } /* osx_midi_set_pitch: * Sets pitch of specified voice. */ static void osx_midi_set_pitch(int voice_id, int note, int bend) { bend >>= 5; if (voice[voice_id].bend != bend) { if (NASetController(note_allocator, voice[voice_id].channel, kControllerPitchBend, bend) == noErr) voice[voice_id].bend = bend; } } /* osx_midi_set_pan: * Sets pan value on specified voice. */ static void osx_midi_set_pan(int voice_id, int pan) { if (voice[voice_id].pan != pan) { if (NASetNoteChannelBalance(note_allocator, voice[voice_id].channel, pan - 127) == noErr) voice[voice_id].pan = pan; } } allegro-4.4.3.1/src/macosx/quartz.m0000664000175000017500000001373113437077643016072 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X common quartz (quickdraw) gfx driver functions. * * By Angelo Mottola, based on similar QNX code by Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif /* setup_direct_shifts * Setups direct color shifts. */ void setup_direct_shifts(void) { _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; _rgb_a_shift_32 = 24; _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; } /* osx_qz_write_line: * Line switcher for video bitmaps. */ unsigned long osx_qz_write_line(BITMAP *bmp, int line) { if (!(bmp->id & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; if (bmp->extra) { while (!QDDone(BMP_EXTRA(bmp)->port)); LockPortBits(BMP_EXTRA(bmp)->port); } } return (unsigned long)(bmp->line[line]); } /* osx_qz_unwrite_line: * Line updater for video bitmaps. */ void osx_qz_unwrite_line(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); if (bmp->extra) UnlockPortBits(BMP_EXTRA(bmp)->port); } } /* osx_qz_acquire: * Bitmap locking for video bitmaps. */ void osx_qz_acquire(BITMAP *bmp) { if (!(bmp->id & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; if (bmp->extra) { while (!QDDone(BMP_EXTRA(bmp)->port)); while (LockPortBits(BMP_EXTRA(bmp)->port)); } } } /* osx_qz_release: * Bitmap unlocking for video bitmaps. */ void osx_qz_release(BITMAP *bmp) { bmp->id &= ~BMP_ID_LOCKED; if (bmp->extra) UnlockPortBits(BMP_EXTRA(bmp)->port); } /* osx_qz_created_sub_bitmap: * Makes a sub bitmap to inherit the GWorld of its parent. */ void osx_qz_created_sub_bitmap(BITMAP *bmp, BITMAP *parent) { bmp->extra = parent->extra; } /* _make_quickdraw_bitmap: * Creates a BITMAP using a QuickDraw GWorld as backing store. */ static BITMAP *_make_quickdraw_bitmap(int width, int height, int flags) { BITMAP *bmp; GWorldPtr gworld; Rect rect; char *addr; int pitch; int i, size; /* create new GWorld */ SetRect(&rect, 0, 0, width, height); if (NewGWorld(&gworld, screen->vtable->color_depth, &rect, NULL, NULL, flags)) return NULL; LockPortBits(gworld); addr = GetPixBaseAddr(GetPortPixMap(gworld)); pitch = GetPixRowBytes(GetPortPixMap(gworld)); UnlockPortBits(gworld); if (!addr) { DisposeGWorld(gworld); return NULL; } /* create Allegro bitmap */ size = sizeof(BITMAP) + sizeof(char *) * height; bmp = (BITMAP *) malloc(size); if (!bmp) { DisposeGWorld(gworld); return NULL; } bmp->w = bmp->cr = width; bmp->h = bmp->cb = height; bmp->clip = TRUE; bmp->cl = bmp->ct = 0; bmp->vtable = &_screen_vtable; bmp->write_bank = bmp->read_bank = osx_qz_write_line; bmp->dat = NULL; bmp->id = BMP_ID_VIDEO; bmp->extra = NULL; bmp->x_ofs = 0; bmp->y_ofs = 0; bmp->seg = _video_ds(); bmp->line[0] = (unsigned char *)addr; for (i = 1; i < height; i++) bmp->line[i] = bmp->line[i - 1] + pitch; /* setup surface info structure to store additional information */ bmp->extra = malloc(sizeof(struct BMP_EXTRA_INFO)); if (!bmp->extra) { free(bmp); DisposeGWorld(gworld); return NULL; } BMP_EXTRA(bmp)->port = gworld; return bmp; } /* osx_qz_create_video_bitmap: * Tries to allocate a BITMAP in video memory. */ BITMAP *osx_qz_create_video_bitmap(int width, int height) { if ((gfx_driver->w == width) && (gfx_driver->h == height) && (!osx_screen_used)) { osx_screen_used = TRUE; return screen; } return _make_quickdraw_bitmap(width, height, useDistantHdwrMem); } /* osx_qz_create_system_bitmap: * Tries to allocates a BITMAP in AGP memory. */ BITMAP *osx_qz_create_system_bitmap(int width, int height) { return _make_quickdraw_bitmap(width, height, useLocalHdwrMem); } /* osx_qz_destroy_video_bitmap: * Frees memory used by bitmap structure and releases associated GWorld. */ void osx_qz_destroy_video_bitmap(BITMAP *bmp) { if (bmp) { if (bmp == screen) { osx_screen_used = FALSE; return; } if (bmp->extra) { if (BMP_EXTRA(bmp)->port) DisposeGWorld(BMP_EXTRA(bmp)->port); free(bmp->extra); } free(bmp); } } /* osx_qz_blit_to_self: * Accelerated vram -> vram blitting routine. */ void osx_qz_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { Rect source_rect, dest_rect; SetRect(&source_rect, source_x + source->x_ofs, source_y + source->y_ofs, source_x + source->x_ofs + width, source_y + source->y_ofs + height); SetRect(&dest_rect, dest_x + dest->x_ofs, dest_y + dest->y_ofs, dest_x + dest->x_ofs + width, dest_y + dest->y_ofs + height); while (!QDDone(BMP_EXTRA(dest)->port)); if (!(dest->id & BMP_ID_LOCKED)) LockPortBits(BMP_EXTRA(dest)->port); CopyBits(GetPortBitMapForCopyBits(BMP_EXTRA(source)->port), GetPortBitMapForCopyBits(BMP_EXTRA(dest)->port), &source_rect, &dest_rect, srcCopy, NULL); if (!(dest->id & BMP_ID_LOCKED)) UnlockPortBits(BMP_EXTRA(dest)->port); } allegro-4.4.3.1/src/macosx/qzwindow.m0000664000175000017500000005707513437077643016437 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X quartz windowed gfx driver * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif static BITMAP *osx_qz_window_init(int, int, int, int, int); static void osx_qz_window_exit(BITMAP *); static void osx_qz_window_vsync(void); static void osx_qz_window_set_palette(AL_CONST struct RGB *, int, int, int); static void osx_signal_vsync(void); static BITMAP* osx_create_video_bitmap(int w, int h); static int osx_show_video_bitmap(BITMAP*); static void osx_destroy_video_bitmap(BITMAP*); static BITMAP* create_video_page(unsigned char*); static pthread_mutex_t vsync_mutex; static pthread_cond_t vsync_cond; static int lock_nesting = 0; static AllegroWindowDelegate *window_delegate = NULL; static char driver_desc[256]; static int requested_color_depth; static COLORCONV_BLITTER_FUNC *colorconv_blitter = NULL; static RgnHandle update_region = NULL; static RgnHandle temp_region = NULL; static AllegroView *qd_view = NULL; static int desktop_depth; static BITMAP* pseudo_screen = NULL; static BITMAP* first_page = NULL; static unsigned char *pseudo_screen_addr = NULL; static int pseudo_screen_pitch; static int pseudo_screen_depth; static char *dirty_lines = NULL; static GFX_VTABLE _special_vtable; /* special vtable for active video page */ static GFX_VTABLE _unspecial_vtable; /* special vtable for inactive video page */ static BITMAP* current_video_page = NULL; void* osx_window_mutex; GFX_DRIVER gfx_quartz_window = { GFX_QUARTZ_WINDOW, empty_string, empty_string, "Quartz window", osx_qz_window_init, osx_qz_window_exit, NULL, /* AL_METHOD(int, scroll, (int x, int y)); */ osx_qz_window_vsync, osx_qz_window_set_palette, NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ osx_create_video_bitmap, /* AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); */ osx_destroy_video_bitmap, /* AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); */ osx_show_video_bitmap, /* AL_METHOD(int, show_video_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, request_video_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(BITMAP *, create_system_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_system_bitmap, (BITMAP *bitmap)); */ osx_mouse_set_sprite, /* AL_METHOD(int, set_mouse_sprite, (BITMAP *sprite, int xfocus, int yfocus)); */ osx_mouse_show, /* AL_METHOD(int, show_mouse, (BITMAP *bmp, int x, int y)); */ osx_mouse_hide, /* AL_METHOD(void, hide_mouse, (void)); */ osx_mouse_move, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ NULL, /* AL_METHOD(int, fetch_mode_list, (void)); */ 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ TRUE }; /* prepare_window_for_animation: * Prepares the window for a (de)miniaturization animation. * Called by the window display method when the window is about to be * deminiaturized, this updates the QuickDraw view contents and sets the * alpha component to 255 (opaque). * When called from the miniaturize window method, only the alpha value * is updated. */ static void prepare_window_for_animation(int refresh_view) { struct GRAPHICS_RECT src_gfx_rect, dest_gfx_rect; unsigned int *addr; int pitch, y, x; _unix_lock_mutex(osx_window_mutex); while (![qd_view lockFocusIfCanDraw]); while (!QDDone([qd_view qdPort])); LockPortBits([qd_view qdPort]); pitch = GetPixRowBytes(GetPortPixMap([qd_view qdPort])) / 4; addr = (unsigned int *)GetPixBaseAddr(GetPortPixMap([qd_view qdPort])) + ((int)([osx_window frame].size.height) - gfx_quartz_window.h) * pitch; if (refresh_view && colorconv_blitter) { src_gfx_rect.width = gfx_quartz_window.w; src_gfx_rect.height = gfx_quartz_window.h; src_gfx_rect.pitch = pseudo_screen_pitch; src_gfx_rect.data = pseudo_screen_addr; dest_gfx_rect.pitch = pitch * 4; dest_gfx_rect.data = addr; colorconv_blitter(&src_gfx_rect, &dest_gfx_rect); } for (y = gfx_quartz_window.h; y; y--) { for (x = 0; x < gfx_quartz_window.w; x++) *(addr + x) |= 0xff000000; addr += pitch; } UnlockPortBits([qd_view qdPort]); [qd_view unlockFocus]; _unix_unlock_mutex(osx_window_mutex); } @implementation AllegroWindow /* display: * Called when the window is about to be deminiaturized. */ - (void)display { [super display]; if (desktop_depth == 32) prepare_window_for_animation(TRUE); } /* miniaturize: * Called when the window is miniaturized. */ - (void)miniaturize: (id)sender { if (desktop_depth == 32) prepare_window_for_animation(FALSE); [super miniaturize: sender]; } @end @implementation AllegroWindowDelegate /* windowShouldClose: * Called when the user attempts to close the window. * Default behaviour is to call the user callback (if any) and deny closing. */ - (BOOL)windowShouldClose: (id)sender { if (osx_window_close_hook) osx_window_close_hook(); return NO; } /* windowDidDeminiaturize: * Called when the window deminiaturization animation ends; marks the whole * window contents as dirty, so it is updated on next refresh. */ - (void)windowDidDeminiaturize: (NSNotification *)aNotification { _unix_lock_mutex(osx_window_mutex); memset(dirty_lines, 1, gfx_quartz_window.h); _unix_unlock_mutex(osx_window_mutex); } /* windowDidBecomeKey: * Sent by the default notification center immediately after an NSWindow * object has become key. */ - (void)windowDidBecomeKey:(NSNotification *)notification { _unix_lock_mutex(osx_skip_events_processing_mutex); osx_skip_events_processing = FALSE; _unix_unlock_mutex(osx_skip_events_processing_mutex); } /* windowDidResignKey: * Sent by the default notification center immediately after an NSWindow * object has resigned its status as key window. */ - (void)windowDidResignKey:(NSNotification *)notification { _unix_lock_mutex(osx_skip_events_processing_mutex); osx_skip_events_processing = TRUE; _unix_unlock_mutex(osx_skip_events_processing_mutex); } @end @implementation AllegroView /* resetCursorRects: * Called when the view needs to reset its cursor rects; this restores the * Allegro cursor rect and enables it. */ - (void)resetCursorRects { [super resetCursorRects]; [self addCursorRect: NSMakeRect(0, 0, gfx_quartz_window.w, gfx_quartz_window.h) cursor: osx_cursor]; [osx_cursor setOnMouseEntered: YES]; } @end /* osx_qz_acquire_win: * Bitmap locking for Quartz windowed mode. */ static void osx_qz_acquire_win(BITMAP *bmp) { /* to prevent the drawing threads and the rendering proc from concurrently accessing the dirty lines array */ _unix_lock_mutex(osx_window_mutex); if (lock_nesting++ == 0) { bmp->id |= BMP_ID_LOCKED; } } /* osx_qz_release_win: * Bitmap unlocking for Quartz windowed mode. */ static void osx_qz_release_win(BITMAP *bmp) { ASSERT(lock_nesting > 0); if (--lock_nesting == 0) { bmp->id &= ~BMP_ID_LOCKED; } _unix_unlock_mutex(osx_window_mutex); } /* osx_qz_write_line_win: * Line switcher for Quartz windowed mode. */ static unsigned long osx_qz_write_line_win(BITMAP *bmp, int line) { if (!(bmp->id & BMP_ID_LOCKED)) { osx_qz_acquire_win(bmp); if (bmp->extra) { while (!QDDone(BMP_EXTRA(bmp)->port)); while (LockPortBits(BMP_EXTRA(bmp)->port)); } bmp->id |= BMP_ID_AUTOLOCK; } dirty_lines[line + bmp->y_ofs] = 1; return (unsigned long)(bmp->line[line]); } /* osx_qz_unwrite_line_win: * Line updater for Quartz windowed mode. */ static void osx_qz_unwrite_line_win(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { osx_qz_release_win(bmp); if (bmp->extra) UnlockPortBits(BMP_EXTRA(bmp)->port); bmp->id &= ~BMP_ID_AUTOLOCK; } } /* update_dirty_lines: * Dirty lines updater routine. This is always called from the main app * thread only. */ void osx_update_dirty_lines(void) { struct GRAPHICS_RECT src_gfx_rect, dest_gfx_rect; Rect rect; CGrafPtr qd_view_port; int qd_view_pitch; char *qd_view_addr; if (![osx_window isVisible]) return; /* Skip everything if there are no dirty lines */ _unix_lock_mutex(osx_window_mutex); for (rect.top = 0; (rect.top < gfx_quartz_window.h) && (!dirty_lines[rect.top]); rect.top++) ; if (rect.top >= gfx_quartz_window.h) { _unix_unlock_mutex(osx_window_mutex); osx_signal_vsync(); return; } /* Dirty lines need to be updated */ if ([qd_view lockFocusIfCanDraw] == YES) { while (!QDDone([qd_view qdPort])); LockPortBits([qd_view qdPort]); qd_view_port = [qd_view qdPort]; if (qd_view_port) { qd_view_pitch = GetPixRowBytes(GetPortPixMap(qd_view_port)); qd_view_addr = GetPixBaseAddr(GetPortPixMap(qd_view_port)) + ((int)([osx_window frame].size.height) - gfx_quartz_window.h) * qd_view_pitch; if (colorconv_blitter || (osx_setup_colorconv_blitter() == 0)) { SetEmptyRgn(update_region); rect.left = 0; rect.right = gfx_quartz_window.w; while (rect.top < gfx_quartz_window.h) { while ((!dirty_lines[rect.top]) && (rect.top < gfx_quartz_window.h)) rect.top++; if (rect.top >= gfx_quartz_window.h) break; rect.bottom = rect.top; while ((dirty_lines[rect.bottom]) && (rect.bottom < gfx_quartz_window.h)) { dirty_lines[rect.bottom] = 0; rect.bottom++; } /* fill in source graphics rectangle description */ src_gfx_rect.width = rect.right - rect.left; src_gfx_rect.height = rect.bottom - rect.top; src_gfx_rect.pitch = pseudo_screen_pitch; src_gfx_rect.data = pseudo_screen_addr + (rect.top * pseudo_screen_pitch) + (rect.left * BYTES_PER_PIXEL(pseudo_screen_depth)); /* fill in destination graphics rectangle description */ dest_gfx_rect.pitch = qd_view_pitch; dest_gfx_rect.data = qd_view_addr + (rect.top * qd_view_pitch) + (rect.left * BYTES_PER_PIXEL(desktop_depth)); /* function doing the hard work */ colorconv_blitter(&src_gfx_rect, &dest_gfx_rect); RectRgn(temp_region, &rect); UnionRgn(temp_region, update_region, update_region); rect.top = rect.bottom; } } QDFlushPortBuffer(qd_view_port, update_region); } UnlockPortBits([qd_view qdPort]); [qd_view unlockFocus]; } _unix_unlock_mutex(osx_window_mutex); osx_signal_vsync(); } /* osx_setup_colorconv_blitter: * Sets up the window color conversion blitter function depending on the * Allegro requested color depth and the current desktop color depth. */ int osx_setup_colorconv_blitter() { CFDictionaryRef mode; void *vp; int dd; if (qd_view && (vp = [qd_view qdPort])) { dd = GetPixDepth(GetPortPixMap(vp)); } else { mode = CGDisplayCurrentMode(kCGDirectMainDisplay); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel), kCFNumberSInt32Type, &desktop_depth); dd = desktop_depth; } if (dd == 16) dd = 15; _unix_lock_mutex(osx_window_mutex); if (colorconv_blitter) _release_colorconv_blitter(colorconv_blitter); colorconv_blitter = _get_colorconv_blitter(requested_color_depth, dd); /* We also need to update the color conversion palette to reflect the change */ if (colorconv_blitter) _set_colorconv_palette(_current_palette, 0, 255); /* Mark all the window as dirty */ memset(dirty_lines, 1, gfx_quartz_window.h); _unix_unlock_mutex(osx_window_mutex); return (colorconv_blitter ? 0 : -1); } /* osx_qz_window_init: * Initializes windowed gfx mode. */ static BITMAP *private_osx_qz_window_init(int w, int h, int v_w, int v_h, int color_depth) { CFDictionaryRef mode; NSRect rect = NSMakeRect(0, 0, w, h); int refresh_rate; char tmp1[128], tmp2[128]; pthread_cond_init(&vsync_cond, NULL); pthread_mutex_init(&vsync_mutex, NULL); osx_window_mutex=_unix_create_mutex(); lock_nesting = 0; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (color_depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((w == 0) && (h == 0)) { w = 320; h = 200; } if (v_w < w) v_w = w; if (v_h < h) v_h = h; if ((v_w != w) || (v_h != h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } osx_window = [[AllegroWindow alloc] initWithContentRect: rect styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask backing: NSBackingStoreBuffered defer: NO]; window_delegate = [[[AllegroWindowDelegate alloc] init] autorelease]; [osx_window setDelegate: window_delegate]; [osx_window setOneShot: YES]; [osx_window setAcceptsMouseMovedEvents: YES]; [osx_window setViewsNeedDisplay: NO]; [osx_window setReleasedWhenClosed: YES]; [osx_window useOptimizedDrawing: YES]; [osx_window center]; qd_view = [[AllegroView alloc] initWithFrame: rect]; if (!qd_view) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } [osx_window setContentView: qd_view]; set_window_title(osx_window_title); [osx_window makeKeyAndOrderFront: nil]; /* the last flag serves as an end of loop delimiter */ dirty_lines = calloc(h + 1, sizeof(char)); /* Mark all the window as dirty */ memset(dirty_lines, 1, h + 1); setup_direct_shifts(); gfx_quartz_window.w = w; gfx_quartz_window.h = h; gfx_quartz_window.vid_mem = w * h * BYTES_PER_PIXEL(color_depth); requested_color_depth = color_depth; colorconv_blitter=NULL; mode = CGDisplayCurrentMode(kCGDirectMainDisplay); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel), kCFNumberSInt32Type, &desktop_depth); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberSInt32Type, &refresh_rate); _set_current_refresh_rate(refresh_rate); pseudo_screen_pitch = w * BYTES_PER_PIXEL(color_depth); pseudo_screen_addr = _AL_MALLOC(h * pseudo_screen_pitch); pseudo_screen = _make_bitmap(w, h, (unsigned long) pseudo_screen_addr, &gfx_quartz_window, color_depth, pseudo_screen_pitch); if (!pseudo_screen) { return NULL; } current_video_page = pseudo_screen; first_page = NULL; /* create a new special vtable for the pseudo screen */ memcpy(&_special_vtable, &_screen_vtable, sizeof(GFX_VTABLE)); _special_vtable.acquire = osx_qz_acquire_win; _special_vtable.release = osx_qz_release_win; _special_vtable.unwrite_bank = osx_qz_unwrite_line_win; memcpy(&_unspecial_vtable, _get_vtable(color_depth), sizeof(GFX_VTABLE)); pseudo_screen->read_bank = osx_qz_write_line_win; pseudo_screen->write_bank = osx_qz_write_line_win; pseudo_screen->vtable = &_special_vtable; uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("Cocoa window using QuickDraw view, %d bpp %s", tmp1), color_depth, uconvert_ascii(color_depth == desktop_depth ? "in matching" : "in fast emulation", tmp2)); gfx_quartz_window.desc = driver_desc; update_region = NewRgn(); temp_region = NewRgn(); osx_mouse_tracking_rect = [qd_view addTrackingRect: rect owner: NSApp userData: nil assumeInside: YES]; osx_keyboard_focused(FALSE, 0); clear_keybuf(); osx_gfx_mode = OSX_GFX_WINDOW; osx_skip_mouse_move = TRUE; osx_window_first_expose = TRUE; return pseudo_screen; } static BITMAP *osx_qz_window_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; _unix_lock_mutex(osx_event_mutex); bmp = private_osx_qz_window_init(w, h, v_w, v_h, color_depth); _unix_unlock_mutex(osx_event_mutex); if (!bmp) osx_qz_window_exit(bmp); return bmp; } /* osx_qz_window_exit: * Shuts down windowed gfx mode. */ static void osx_qz_window_exit(BITMAP *bmp) { _unix_lock_mutex(osx_event_mutex); if (update_region) { DisposeRgn(update_region); update_region = NULL; } if (temp_region) { DisposeRgn(temp_region); temp_region = NULL; } if (osx_window) { [osx_window close]; osx_window = NULL; } if (pseudo_screen_addr) { free(pseudo_screen_addr); pseudo_screen_addr = NULL; } if (dirty_lines) { free(dirty_lines); dirty_lines = NULL; } if (colorconv_blitter) { _release_colorconv_blitter(colorconv_blitter); colorconv_blitter = NULL; } _unix_destroy_mutex(osx_window_mutex); pthread_cond_destroy(&vsync_cond); pthread_mutex_destroy(&vsync_mutex); osx_mouse_tracking_rect = -1; osx_gfx_mode = OSX_GFX_NONE; _unix_unlock_mutex(osx_event_mutex); } /* osx_qz_window_vsync: * Quartz video vertical synchronization routine for windowed mode. */ static void osx_qz_window_vsync(void) { if (lock_nesting==0) { pthread_mutex_trylock(&vsync_mutex); pthread_cond_wait(&vsync_cond, &vsync_mutex); pthread_mutex_unlock(&vsync_mutex); } else { ASSERT(0); /* Screen already acquired, don't call vsync() */ } } /* osx_qz_window_set_palette: * Sets palette for quartz window. */ static void osx_qz_window_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { if (vsync) osx_qz_window_vsync(); _unix_lock_mutex(osx_window_mutex); _set_colorconv_palette(p, from, to); /* invalidate the whole screen */ memset(dirty_lines, 1, gfx_quartz_window.h); _unix_unlock_mutex(osx_window_mutex); } void osx_signal_vsync(void) { pthread_mutex_lock(&vsync_mutex); pthread_cond_broadcast(&vsync_cond); pthread_mutex_unlock(&vsync_mutex); } // create_video_bitmap: // Create a video bitmap - actually a memory bitmap or // a pseudo-screen if the dimensions match the screen static BITMAP* osx_create_video_bitmap(int w, int h) { if ((w == gfx_quartz_window.w) && (h == gfx_quartz_window.h)) { if (first_page == NULL) { // First ever call, return a bitmap mapping the screen memory first_page = create_video_page(pseudo_screen_addr); return first_page; } else { // Must create another return create_video_page(NULL); } } else { return create_bitmap(w, h); } } static BITMAP* create_video_page(unsigned char* addr) { BITMAP* page; int i; int w = gfx_quartz_window.w, h = gfx_quartz_window.h; page = (BITMAP*) _AL_MALLOC(sizeof(BITMAP) + sizeof(char*) * h); if (!page) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } if (addr == NULL) { addr = _AL_MALLOC(gfx_quartz_window.vid_mem); // Use page->dat to indicate that we own the memory page->dat = addr; page->vtable = &_unspecial_vtable; page->write_bank = page->read_bank = _stub_bank_switch; } else { page->dat = NULL; page->vtable = &_special_vtable; page->write_bank = page->read_bank = osx_qz_write_line_win; } if (!addr) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } page->w = page->cr = w; page->h = page->cb = h; page->clip = TRUE; page->cl = page->ct = 0; page->id = BMP_ID_VIDEO; page->extra = NULL; page->x_ofs = 0; page->y_ofs = 0; page->seg = _video_ds(); for (i = 0; i < h; ++i) { page->line[i] = addr; addr += pseudo_screen_pitch; } return page; } static int osx_show_video_bitmap(BITMAP* vb) { if (vb->vtable == &_special_vtable) { // This bitmap already switched in, therefore no-op return 0; } if (vb->vtable == &_unspecial_vtable) { _unix_lock_mutex(osx_window_mutex); // switch out the old one if ((current_video_page == pseudo_screen) && (first_page != NULL)) { // switching out screen, also do page 1 first_page->vtable = &_unspecial_vtable; first_page->write_bank = first_page->read_bank =_stub_bank_switch; } else if ((current_video_page == first_page) && (first_page != NULL)) { // If switching out page 1, also do screen pseudo_screen->vtable = &_unspecial_vtable; pseudo_screen->write_bank = pseudo_screen->read_bank = _stub_bank_switch; } if (current_video_page != NULL) { current_video_page->vtable = &_unspecial_vtable; current_video_page->write_bank = current_video_page->read_bank = _stub_bank_switch; } // Switch in this one if ((vb == pseudo_screen) && (first_page != NULL)) { // If asking for show_video_bitmap(screen), also do page 1 first_page->vtable = &_special_vtable; first_page->write_bank = first_page->read_bank = osx_qz_write_line_win; } else if (vb == first_page) { // If asking for show_video_bitmap( page 1), also do screen pseudo_screen->vtable = &_special_vtable; pseudo_screen->write_bank = pseudo_screen->read_bank = osx_qz_write_line_win; } pseudo_screen_addr = vb->line[0]; vb->vtable = &_special_vtable; vb->write_bank = vb->read_bank = osx_qz_write_line_win; current_video_page = vb; // mark all lines dirty - they will be flushed to the screen. memset(dirty_lines, 1, gfx_quartz_window.h); _unix_unlock_mutex(osx_window_mutex); return 0; } // Otherwise it's not eligible to be switched in return -1; } static void osx_destroy_video_bitmap(BITMAP* bm) { if (bm == pseudo_screen) { // Don't do this! return; } if (bm == first_page) first_page = NULL; if (bm->vtable == &_special_vtable) { osx_show_video_bitmap(pseudo_screen); free(bm->dat); free(bm); } else if (bm->vtable == &_unspecial_vtable) { free(bm->dat); free(bm); } // Otherwise it wasn't a video page } /* Local variables: */ /* c-basic-offset: 3 */ /* indent-tabs-mode: nil */ /* c-file-style: "linux" */ /* End: */ allegro-4.4.3.1/src/macosx/camidi.m0000664000175000017500000001473013437077643015772 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * CoreAudio MIDI driver routines for MacOS X. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif static int ca_detect(int); static int ca_init(int, int); static void ca_exit(int); static int ca_set_mixer_volume(int); static void ca_raw_midi(int); static AUGraph graph; static AudioUnit synth_unit; static int command, data_pos, data_buffer[2]; static char driver_desc[256]; MIDI_DRIVER midi_core_audio = { MIDI_CORE_AUDIO, /* driver ID code */ empty_string, /* driver name */ empty_string, /* description string */ "CoreAudio", /* ASCII format name string */ 16, /* available voices */ 0, /* voice number offset */ 16, /* maximum voices we can support */ 0, /* default number of voices to use */ 10, 10, /* reserved voice range */ ca_detect, /* AL_METHOD(int, detect, (int input)); */ ca_init, /* AL_METHOD(int, init, (int input, int voices)); */ ca_exit, /* AL_METHOD(void, exit, (int input)); */ ca_set_mixer_volume, /* AL_METHOD(int, mixer_set_volume, (int volume)); */ NULL, /* AL_METHOD(int, mixer_get_volume, (void)); */ ca_raw_midi, /* AL_METHOD(void, raw_midi, (int data)); */ _dummy_load_patches, /* AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ _dummy_adjust_patches, /* AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ _dummy_key_on, /* AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); */ _dummy_noop1, /* AL_METHOD(void, key_off, (int voice)); */ _dummy_noop2, /* AL_METHOD(void, set_volume, (int voice, int vol)); */ _dummy_noop3, /* AL_METHOD(void, set_pitch, (int voice, int note, int bend)); */ _dummy_noop2, /* AL_METHOD(void, set_pan, (int voice, int pan)); */ _dummy_noop2, /* AL_METHOD(void, set_vibrato, (int voice, int amount)); */ }; static int ca_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) return FALSE; return TRUE; } static int ca_init(int input, int voices) { char tmp[128], tmp1[128], tmp2[128]; char *sound = uconvert_ascii("sound", tmp); ComponentDescription desc; AUNode synth_node, output_node; UInt32 quality, reverb_type; int reverb; struct { UInt32 type; char *name; } reverb_info[6] = { { kReverbRoomType_SmallRoom, "small room" }, { kReverbRoomType_MediumRoom, "medium room" }, { kReverbRoomType_LargeRoom, "large room" }, { kReverbRoomType_MediumHall, "medium hall" }, { kReverbRoomType_LargeHall, "large hall" }, { kReverbRoomType_Plate, "plate" } }; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MacOS X.2 or newer required by this driver")); return -1; } NewAUGraph(&graph); desc.componentType = kAudioUnitType_MusicDevice; desc.componentSubType = kAudioUnitSubType_DLSSynth; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AUGraphNewNode(graph, &desc, 0, NULL, &synth_node); desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AUGraphNewNode(graph, &desc, 0, NULL, &output_node); AUGraphConnectNodeInput(graph, synth_node, 0, output_node, 0); AUGraphOpen(graph); AUGraphInitialize(graph); AUGraphGetNodeInfo(graph, synth_node, NULL, NULL, NULL, &synth_unit); quality = CLAMP(0, get_config_int(sound, uconvert_ascii("ca_midi_quality", tmp), 127), 127); AudioUnitSetProperty(synth_unit, kAudioUnitProperty_RenderQuality, kAudioUnitScope_Output, 0, &quality, sizeof(quality)); reverb = CLAMP(0, get_config_int(sound, uconvert_ascii("ca_midi_reverb", tmp), 0), 5); reverb_type = reverb_info[reverb].type; AudioUnitSetProperty(synth_unit, kAudioUnitProperty_ReverbRoomType, kAudioUnitScope_Output, 0, &reverb_type, sizeof(reverb_type)); AUGraphStart(graph); uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("DLSMusicDevice unit, %s quality, %s reverb", tmp), (quality < 32 ? uconvert_ascii("low", tmp1) : (quality >= 96 ? uconvert_ascii("high", tmp1) : uconvert_ascii("medium", tmp1))), uconvert_ascii(reverb_info[reverb].name, tmp2)); midi_core_audio.desc = driver_desc; command = -1; return 0; } static void ca_exit(int input) { if (input) return; AUGraphStop(graph); AUGraphUninitialize(graph); AUGraphClose(graph); DisposeAUGraph(graph); } static int ca_set_mixer_volume(int volume) { float value = (float)volume / 255.0; return AudioUnitSetParameter(synth_unit, kAudioUnitParameterUnit_LinearGain, kAudioUnitScope_Output, 0, value, 0); } static void ca_raw_midi(int data) { if (command == -1) { data_buffer[0] = data_buffer[1] = 0; data_pos = 0; command = data; return; } data_buffer[data_pos++] = data; if (((data_pos == 1) && (((command >> 4) == 0xC) || ((command >> 4) == 0xD))) || (data_pos == 2)) { MusicDeviceMIDIEvent(synth_unit, command, data_buffer[0], data_buffer[1], 0); command = -1; } } allegro-4.4.3.1/src/macosx/hidman.m0000664000175000017500000004607513437077643016013 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X HID Manager access routines. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error Something is wrong with the makefile #endif #define USAGE(p, u) (((p)<<16)+(u)) static void hid_store_element_data(CFTypeRef element, int type, HID_DEVICE *device, int app, int collection, int index); static void hid_scan_physical_collection(CFTypeRef properties, HID_DEVICE *device, int app, int collection); static void hid_scan_application_collection(CFMutableDictionaryRef properties, HID_DEVICE *device); static HID_DEVICE* add_device(HID_DEVICE_COLLECTION*); /* add_element: * Add a new, blank element to a device. * This is later specialized into a button * axis or whatever */ static HID_ELEMENT* add_element(HID_DEVICE* d) { HID_ELEMENT* e; if (d->element==NULL) { d->capacity=8; d->element=malloc(d->capacity*sizeof(HID_ELEMENT)); } if (d->num_elements>=d->capacity) { d->capacity*=2; d->element=realloc(d->element, d->capacity*sizeof(HID_ELEMENT)); } e=&d->element[d->num_elements++]; memset(e, 0, sizeof(HID_ELEMENT)); return e; } /* i_val: * Helper method - get an integer value from a dictionary * Defaults to 0 if the value is not found; in practice this * should not occur. */ static int i_val(CFTypeRef d, CFStringRef key) { int ans; CFTypeRef num = CFDictionaryGetValue(d, key); if (num) CFNumberGetValue(num, kCFNumberIntType, &ans); else ans = 0; return ans; } /* hid_store_element_data: * Parse this HID element, break it down and store the * relevant data in the device structure */ static void hid_store_element_data(CFTypeRef element, int type, HID_DEVICE *device, int app, int col, int idx) { HID_ELEMENT *hid_element; CFTypeRef type_ref; AL_CONST char *name; hid_element = add_element(device); hid_element->type = type; hid_element->index = idx; hid_element->col = col; hid_element->app = app; hid_element->cookie = (IOHIDElementCookie) i_val(element, CFSTR(kIOHIDElementCookieKey)); hid_element->min = i_val(element, CFSTR(kIOHIDElementMinKey)); hid_element->max = i_val(element, CFSTR(kIOHIDElementMaxKey)); type_ref = CFDictionaryGetValue(element, CFSTR(kIOHIDElementNameKey)); if ((type_ref) && (name = CFStringGetCStringPtr(type_ref, CFStringGetSystemEncoding()))) hid_element->name = strdup(name); else hid_element->name = NULL; } /* hid_scan_application: * scan the elements that make up one 'application' * i.e. one unit like a joystick. */ static void hid_scan_application(CFTypeRef properties, HID_DEVICE *device, int app) { CFTypeRef array_ref, element; int type, usage_page, usage; int i; int axis=0; int stick=0; array_ref = CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey)); if ((array_ref) && (CFGetTypeID(array_ref) == CFArrayGetTypeID())) { for (i = 0; i < CFArrayGetCount(array_ref); i++) { element = CFArrayGetValueAtIndex(array_ref, i); if (CFGetTypeID(element) == CFDictionaryGetTypeID()) { type = i_val(element, CFSTR(kIOHIDElementTypeKey)); usage = i_val(element, CFSTR(kIOHIDElementUsageKey)); usage_page = i_val(element, CFSTR(kIOHIDElementUsagePageKey)); if (type == kIOHIDElementTypeCollection) { /* It is a collection; recurse into it, if it is part of the generic desktop (sometimes the whole joystick is wrapped up inside a collection like this. */ if (usage_page == kHIDPage_GenericDesktop) hid_scan_application(element, device, app); } else { switch (usage_page) { case kHIDPage_GenericDesktop: switch(usage) { case kHIDUsage_GD_Pointer: if (axis!=0) { /* already have some elements in this stick */ ++stick; axis=0; } hid_scan_physical_collection(element, device, app, stick); ++stick; break; case kHIDUsage_GD_X: hid_store_element_data(element, HID_ELEMENT_AXIS_PRIMARY_X, device, app, stick, axis++); break; case kHIDUsage_GD_Y: hid_store_element_data(element, HID_ELEMENT_AXIS_PRIMARY_Y, device, app, stick, axis++); break; case kHIDUsage_GD_Z: case kHIDUsage_GD_Rx: case kHIDUsage_GD_Ry: case kHIDUsage_GD_Rz: hid_store_element_data(element, HID_ELEMENT_AXIS, device,app, stick, axis++); break; case kHIDUsage_GD_Slider: case kHIDUsage_GD_Dial: case kHIDUsage_GD_Wheel: /* If we've already seen some axes on this stick, move to the next one */ if (axis > 0) { ++stick; axis=0; } hid_store_element_data(element, HID_ELEMENT_STANDALONE_AXIS, device, app, stick++, 0); break; case kHIDUsage_GD_Hatswitch: /* If we've already seen some axes on this stick, move to the next one */ if (axis > 0) { ++stick; axis=0; } hid_store_element_data(element, HID_ELEMENT_HAT, device, app, stick++, 0); break; } break; case kHIDPage_Button: hid_store_element_data(element, HID_ELEMENT_BUTTON, device, app, 0, usage-1); break; } } if (axis>=2) { ++stick; axis=0; } } } } } /* hid_scan_physical_collection: * scan the elements that make up one 'stick' */ static void hid_scan_physical_collection(CFTypeRef properties, HID_DEVICE *device, int app, int stick) { CFTypeRef array_ref, element; int type, usage_page, usage; int i; int axis=0; array_ref = CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey)); if ((array_ref) && (CFGetTypeID(array_ref) == CFArrayGetTypeID())) { for (i = 0; i < CFArrayGetCount(array_ref); i++) { element = CFArrayGetValueAtIndex(array_ref, i); if (CFGetTypeID(element) == CFDictionaryGetTypeID()) { type = i_val(element, CFSTR(kIOHIDElementTypeKey)); usage = i_val(element, CFSTR(kIOHIDElementUsageKey)); usage_page = i_val(element, CFSTR(kIOHIDElementUsagePageKey)); switch (usage_page) { case kHIDPage_GenericDesktop: switch(usage) { case kHIDUsage_GD_X: hid_store_element_data(element, HID_ELEMENT_AXIS_PRIMARY_X, device, app, stick, axis++); break; case kHIDUsage_GD_Y: hid_store_element_data(element, HID_ELEMENT_AXIS_PRIMARY_Y, device, app, stick, axis++); break; case kHIDUsage_GD_Z: case kHIDUsage_GD_Rx: case kHIDUsage_GD_Ry: case kHIDUsage_GD_Rz: hid_store_element_data(element, HID_ELEMENT_AXIS, device,app, stick, axis++); break; } break; case kHIDPage_Button: hid_store_element_data(element, HID_ELEMENT_BUTTON, device, app, 0, usage-1); break; } } } } } /* hid_scan_application_collection: * Scan the elements array; each element will be an 'application' * i.e. one joystick, gamepad or mouse * */ static void hid_scan_application_collection(CFMutableDictionaryRef properties, HID_DEVICE *device) { CFTypeRef array_ref, element; int usage, usage_page; int i; array_ref = CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey)); if ((array_ref) && (CFGetTypeID(array_ref) == CFArrayGetTypeID())) { for (i = 0; i < CFArrayGetCount(array_ref); i++) { element = CFArrayGetValueAtIndex(array_ref, i); if (CFGetTypeID(element) == CFDictionaryGetTypeID()) { usage=i_val(element, CFSTR(kIOHIDElementUsageKey)); usage_page=i_val(element, CFSTR(kIOHIDElementUsagePageKey)); switch(USAGE(usage_page, usage)) { case USAGE(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick): device->type=HID_JOYSTICK; hid_scan_application(element, device, device->cur_app); device->cur_app++; break; case USAGE(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad): device->type=HID_GAMEPAD; hid_scan_application(element, device, device->cur_app); device->cur_app++; break; case USAGE(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse): device->type=HID_MOUSE; hid_scan_application(element, device, device->cur_app); device->cur_app++; break; } } } } } /* get_usb_properties: * Get a property dictionary from the USB plane. */ static CFMutableDictionaryRef get_usb_properties(io_object_t device) { io_registry_entry_t parent, grandparent; CFMutableDictionaryRef usb_properties = NULL; if (IORegistryEntryGetParentEntry(device, kIOServicePlane, &parent) == KERN_SUCCESS) { if (IORegistryEntryGetParentEntry(parent, kIOServicePlane, &grandparent) == KERN_SUCCESS) { IORegistryEntryCreateCFProperties (grandparent, &usb_properties, kCFAllocatorDefault, kNilOptions); IOObjectRelease(grandparent); } IOObjectRelease(parent); } return usb_properties; } #if OSX_HID_PSEUDO_SCAN /* * Pseudo scan - for development purposes, if someone has hardware * that isn't parsed by this code, you can ask them to dump _their_ scan * as a plist, then reload it here in order to debug it. */ HID_DEVICE_COLLECTION *osx_hid_scan(int type, HID_DEVICE_COLLECTION* col) { HID_DEVICE* this_device; NSDictionary* properties = nil; NSString* filename; switch (type) { case HID_GAMEPAD: filename = @"gamepad.plist"; break; case HID_JOYSTICK: filename = @"joystick.plist"; break; case HID_MOUSE: filename = @"mouse.plist"; break; default: filename = nil; break; } if (filename != nil) properties = [NSDictionary dictionaryWithContentsOfFile:filename]; if (properties) { this_device = add_device(col); this_device->manufacturer = strdup([((NSString*) [properties objectForKey: @kIOHIDManufacturerKey]) lossyCString]); this_device->product = strdup([((NSString*) [properties objectForKey: @kIOHIDProductKey]) lossyCString]); hid_scan_application_collection((CFDictionaryRef) properties, this_device); [properties release]; } return col; } #else /* osx_hid_scan: * Scan the hid manager for devices of type 'type', * and append to the collection col */ HID_DEVICE_COLLECTION *osx_hid_scan(int type, HID_DEVICE_COLLECTION* col) { ASSERT(col); HID_DEVICE *this_device; mach_port_t master_port = 0; io_iterator_t hid_object_iterator = 0; io_object_t hid_device = 0; CFMutableDictionaryRef class_dictionary = NULL; int usage, usage_page; CFTypeRef type_ref; CFNumberRef usage_ref = NULL, usage_page_ref = NULL; CFMutableDictionaryRef properties = NULL, usb_properties = NULL; IOCFPlugInInterface **plugin_interface = NULL; IOReturn result; AL_CONST char *string; SInt32 score = 0; int error; usage_page = kHIDPage_GenericDesktop; switch (type) { case HID_MOUSE: usage = kHIDUsage_GD_Mouse; break; case HID_JOYSTICK: usage = kHIDUsage_GD_Joystick; break; case HID_GAMEPAD: usage=kHIDUsage_GD_GamePad; break; } result = IOMasterPort(bootstrap_port, &master_port); if (result == kIOReturnSuccess) { class_dictionary = IOServiceMatching(kIOHIDDeviceKey); if (class_dictionary) { /* Add key for device type to refine the matching dictionary. */ usage_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); usage_page_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page); CFDictionarySetValue(class_dictionary, CFSTR(kIOHIDPrimaryUsageKey), usage_ref); CFDictionarySetValue(class_dictionary, CFSTR(kIOHIDPrimaryUsagePageKey), usage_page_ref); } result = IOServiceGetMatchingServices(master_port, class_dictionary, &hid_object_iterator); if ((result == kIOReturnSuccess) && (hid_object_iterator)) { /* Ok, we have a list of attached HID devices; scan them. */ while ((hid_device = IOIteratorNext(hid_object_iterator))!=0) { if ((IORegistryEntryCreateCFProperties(hid_device, &properties, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS) && (properties != NULL)) { error = FALSE; this_device = add_device(col); this_device->type = type; if (col->count==0) { this_device->cur_app=0; } else { this_device->cur_app=col->devices[col->count-1].cur_app; } /* * Mac OS X currently is not mirroring all USB properties * to HID page so need to look at USB device page also. */ usb_properties = get_usb_properties(hid_device); type_ref = CFDictionaryGetValue(properties, CFSTR(kIOHIDManufacturerKey)); if (!type_ref) type_ref = CFDictionaryGetValue(usb_properties, CFSTR("USB Vendor Name")); if ((type_ref) && (string = CFStringGetCStringPtr(type_ref, CFStringGetSystemEncoding()))) this_device->manufacturer = strdup(string); else this_device->manufacturer = NULL; type_ref = CFDictionaryGetValue(properties, CFSTR(kIOHIDProductKey)); if (!type_ref) type_ref = CFDictionaryGetValue(usb_properties, CFSTR("USB Product Name")); if ((type_ref) && (string = CFStringGetCStringPtr(type_ref, CFStringGetSystemEncoding()))) this_device->product = strdup(string); else this_device->product = NULL; type_ref = CFDictionaryGetValue(usb_properties, CFSTR("USB Address")); if ((type == HID_MOUSE) && (!type_ref)) { /* Not an USB mouse. Must be integrated trackpad: we report it as a single button mouse */ add_element(this_device)->type = HID_ELEMENT_BUTTON; } else { /* Scan for device elements */ this_device->num_elements = 0; hid_scan_application_collection(properties, this_device); } this_device->interface = NULL; if ((type == HID_JOYSTICK) || (type == HID_GAMEPAD)) { /* Joystick or gamepad device: create HID interface */ if (IOCreatePlugInInterfaceForService(hid_device, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin_interface, &score) != kIOReturnSuccess) error = TRUE; else { if ((*plugin_interface)->QueryInterface(plugin_interface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void *)&(this_device->interface)) != S_OK) error = TRUE; (*plugin_interface)->Release(plugin_interface); if ((*(this_device->interface))->open(this_device->interface, 0) != KERN_SUCCESS) error = TRUE; } } if (error) { if (this_device->manufacturer) free(this_device->manufacturer); if (this_device->product) free(this_device->product); if (this_device->interface) (*(this_device->interface))->Release(this_device->interface); this_device->interface=NULL; --col->count; } CFRelease(properties); CFRelease(usb_properties); } } IOObjectRelease(hid_object_iterator); } CFRelease(usage_ref); CFRelease(usage_page_ref); mach_port_deallocate(mach_task_self(), master_port); } return col; } #endif /* add_device: * add a new device to a collection */ static HID_DEVICE* add_device(HID_DEVICE_COLLECTION* o) { HID_DEVICE* d; if (o->devices==NULL) { o->count=0; o->capacity=1; o->devices=malloc(o->capacity*sizeof(HID_DEVICE)); } if (o->count>=o->capacity) { o->capacity*=2; o->devices=realloc(o->devices, o->capacity*sizeof(HID_DEVICE)); } d=&o->devices[o->count]; memset(d, 0, sizeof(HID_DEVICE)); /* Chain onto the preceding app count */ if (o->count>0) d->cur_app = o->devices[o->count-1].cur_app; ++o->count; return d; } /* osx_hid_free: * Release the memory taken up by a collection */ void osx_hid_free(HID_DEVICE_COLLECTION *col) { HID_DEVICE *device; HID_ELEMENT *element; int i, j; for (i = 0; i < col->count; i++) { device = &col->devices[i]; if (device->manufacturer) free(device->manufacturer); if (device->product) free(device->product); for (j = 0; j < device->num_elements; j++) { element = &device->element[j]; if (element->name) free(element->name); } free(device->element); if (device->interface) { (*(device->interface))->close(device->interface); (*(device->interface))->Release(device->interface); } } free(col->devices); } /* Local variables: */ /* c-basic-offset: 3 */ /* indent-tabs-mode: nil */ /* End: */ allegro-4.4.3.1/src/macosx/soundman.m0000664000175000017500000001667313437077643016400 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X Sound Manager digital sound driver. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif #define SAMPLES_PER_BUFFER 4096 static int osx_digi_sound_detect(int); static int osx_digi_sound_init(int, int); static void osx_digi_sound_exit(int); static int osx_digi_sound_buffer_size(); static int osx_digi_sound_set_mixer_volume(int); static SndChannel *sound_channel = NULL; static ExtSoundHeader sound_header; static unsigned char *sound_buffer[2] = { NULL, NULL }; static char sound_desc[256]; DIGI_DRIVER digi_sound_manager = { DIGI_SOUND_MANAGER, empty_string, empty_string, "Sound Manager", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, osx_digi_sound_detect, osx_digi_sound_init, osx_digi_sound_exit, osx_digi_sound_set_mixer_volume, NULL, NULL, NULL, osx_digi_sound_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* sound_callback: * Sound Manager channel callback to update sound data. */ static void sound_callback(SndChannel *channel, SndCommand *command) { SndCommand new_command; /* Send mixed buffer to sound card */ sound_header.samplePtr = (Ptr)sound_buffer[command->param1]; new_command.cmd = bufferCmd; new_command.param1 = 0; new_command.param2 = (long)&sound_header; if (SndDoCommand(channel, &new_command, FALSE) != noErr) return; /* Mix the other buffer */ command->param1 ^= 1; _mix_some_samples((unsigned long)sound_buffer[command->param1], 0, (_sound_bits == 16) ? TRUE : FALSE); /* Reissue the callback */ new_command.cmd = callBackCmd; new_command.param1 = command->param1; SndDoCommand(channel, &new_command, FALSE); } /* osx_digi_sound_detect. * Returns TRUE if Sound Manager 3.x or newer is available. */ static int osx_digi_sound_detect(int input) { NumVersion version; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } version = SndSoundManagerVersion(); if (version.majorRev < 3) return FALSE; return TRUE; } /* osx_digi_sound_init: * Initializes the sound driver. */ static int osx_digi_sound_init(int input, int voices) { SndCommand command; NumVersion version; long sound_caps = 0; char tmp[128]; int i; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } version = SndSoundManagerVersion(); if (version.majorRev < 3) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Sound Manager version 3.0 or newer required")); return -1; } Gestalt(gestaltSoundAttr, &sound_caps); if (_sound_stereo >= 0) { if (_sound_stereo && (sound_caps & (1 << gestaltStereoCapability))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Stereo output not supported")); return -1; } } else _sound_stereo = (sound_caps & (1 << gestaltStereoCapability)) ? TRUE : FALSE; if (_sound_bits >= 0) { if (_sound_bits != ((sound_caps & (1 << gestalt16BitAudioSupport)) ? 16 : 8)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("16 bit output not supported")); return -1; } } else _sound_bits = (sound_caps & (1 << gestalt16BitAudioSupport)) ? 16 : 8; if (_sound_freq <= 0) _sound_freq = 44100; memset(&sound_header, 0, sizeof(sound_header)); sound_header.numChannels = (_sound_stereo) ? 2 : 1; sound_header.sampleRate = _sound_freq << 16; sound_header.encode = extSH; sound_header.numFrames = SAMPLES_PER_BUFFER; sound_header.sampleSize = _sound_bits; for (i = 0; i < 2; i++) { sound_buffer[i] = (unsigned char *)calloc(1, SAMPLES_PER_BUFFER * (_sound_bits / 8) * (_sound_stereo ? 2 : 1)); if (!sound_buffer[i]) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); osx_digi_sound_exit(input); return -1; } } digi_sound_manager.voices = voices; if (_mixer_init(SAMPLES_PER_BUFFER * (_sound_stereo ? 2 : 1), _sound_freq, _sound_stereo, ((_sound_bits == 16) ? TRUE: FALSE), &digi_sound_manager.voices)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error initializing mixer")); osx_digi_sound_exit(input); return -1; } sound_channel = (SndChannel *)malloc(sizeof(SndChannel)); if (!sound_channel) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); osx_digi_sound_exit(input); return -1; } sound_channel->qLength = 128; if (SndNewChannel(&sound_channel, sampledSynth, (_sound_stereo ? initStereo : initMono), sound_callback) != noErr) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed creating sound channel")); free(sound_channel); return -1; } command.cmd = callBackCmd; command.param1 = 0; SndDoCommand(sound_channel, &command, FALSE); uszprintf(sound_desc, sizeof(sound_desc), get_config_text("Sound Manager version %d.%d, %d bits, %d bps, %s"), ((version.majorRev / 16) * 10) + (version.majorRev & 0xf), (version.minorAndBugRev / 16), _sound_bits, _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp)); digi_sound_manager.desc = sound_desc; return 0; } /* osx_digi_sound_exit: * Shuts down the sound driver. */ static void osx_digi_sound_exit(int input) { int i; if (input) return; if (sound_channel) { SndDisposeChannel(sound_channel, TRUE); free(sound_channel); sound_channel = NULL; } for (i = 0; i < 2; i++) { if (sound_buffer[i]) { free(sound_buffer[i]); sound_buffer[i] = NULL; } } _mixer_exit(); } /* osx_digi_sound_buffer_size: * Returns the mixing buffer size, for use by the audiostream code. */ static int osx_digi_sound_buffer_size() { return SAMPLES_PER_BUFFER; } /* osx_digi_sound_set_mixer_volume: * Sets the sound channel volume. */ static int osx_digi_sound_set_mixer_volume(int volume) { SndCommand command; if (!sound_channel) return -1; command.cmd = volumeCmd; command.param1 = 0; command.param2 = (volume << 16) | volume; return (SndDoCommand(sound_channel, &command, FALSE) != noErr); } allegro-4.4.3.1/src/macosx/qzfull.m0000664000175000017500000003447313437077643016067 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X quartz fullscreen gfx driver * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error something is wrong with the makefile #endif #define FADE_STEPS 16 static BITMAP *osx_qz_full_init(int, int, int, int, int); static void osx_qz_full_exit(BITMAP *); static void osx_qz_full_vsync(void); static void osx_qz_full_set_palette(AL_CONST struct RGB *, int, int, int); static int osx_qz_show_video_bitmap(BITMAP *); static GFX_MODE_LIST *osx_qz_fetch_mode_list(void); CGDirectPaletteRef osx_palette = NULL; int osx_palette_dirty = FALSE; int osx_screen_used; static char driver_desc[256]; static CFDictionaryRef old_mode = NULL; static CGrafPtr screen_port = NULL; static CGGammaValue original_table[768]; static BITMAP *old_visible_bmp = NULL; GFX_DRIVER gfx_quartz_full = { GFX_QUARTZ_FULLSCREEN, empty_string, empty_string, "Quartz fullscreen", osx_qz_full_init, osx_qz_full_exit, NULL, /* AL_METHOD(int, scroll, (int x, int y)); */ osx_qz_full_vsync, osx_qz_full_set_palette, NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ osx_qz_create_video_bitmap, /* AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); */ osx_qz_destroy_video_bitmap, /* AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); */ osx_qz_show_video_bitmap, /* AL_METHOD(int, show_video_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, request_video_bitmap, (BITMAP *bitmap)); */ osx_qz_create_system_bitmap, /* AL_METHOD(BITMAP *, create_system_bitmap, (int width, int height)); */ osx_qz_destroy_video_bitmap, /* AL_METHOD(void, destroy_system_bitmap, (BITMAP *bitmap)); */ osx_mouse_set_sprite, /* AL_METHOD(int, set_mouse_sprite, (BITMAP *sprite, int xfocus, int yfocus)); */ osx_mouse_show, /* AL_METHOD(int, show_mouse, (BITMAP *bmp, int x, int y)); */ osx_mouse_hide, /* AL_METHOD(void, hide_mouse, (void)); */ osx_mouse_move, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ osx_qz_fetch_mode_list, /* AL_METHOD(int, fetch_mode_list, (void)); */ 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ FALSE }; void osx_init_fade_system(void) { CGTableCount samples; CGGetDisplayTransferByTable(kCGDirectMainDisplay, 256, &original_table[0], &original_table[256], &original_table[512], &samples); } void osx_fade_screen(int fade_in, double seconds) { int interval = (int)((seconds * 1000000.0) / (double)FADE_STEPS); int i, j; double factor; CGGammaValue table[768]; for (i = 0; i < FADE_STEPS; i++) { if (fade_in) factor = (double)i / (double)FADE_STEPS; else factor = (double)(FADE_STEPS - i) / (double)FADE_STEPS; for (j = 0; j < 256; j++) { table[j] = original_table[j] * factor; table[256 + j] = original_table[256 + j] * factor; table[512 + j] = original_table[512 + j] * factor; } if (CGSetDisplayTransferByTable(kCGDirectMainDisplay, 256, &table[0], &table[256], &table[512]) != kCGErrorSuccess) break; usleep(interval); } } /* osx_qz_full_init: * Initializes fullscreen gfx mode. */ static BITMAP *private_osx_qz_full_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; CFDictionaryRef mode = NULL; boolean_t match = FALSE; int bpp, refresh_rate; char tmp1[128]; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((w == 0) && (h == 0)) { w = 320; h = 200; } if (v_w < w) v_w = w; if (v_h < h) v_h = h; if ((v_w != w) || (v_h != h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } bpp = color_depth == 15 ? 16 : color_depth; if (_refresh_rate_request > 0) mode = CGDisplayBestModeForParametersAndRefreshRate(kCGDirectMainDisplay, bpp, w, h, (double)_refresh_rate_request, &match); if (!match) mode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, bpp, w, h, &match); if (!match) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } osx_init_fade_system(); old_mode = CGDisplayCurrentMode(kCGDirectMainDisplay); osx_fade_screen(FALSE, 0.2); if (CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot capture main display")); return NULL; } if (CGDisplaySwitchToMode(kCGDirectMainDisplay, mode) != kCGErrorSuccess) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot switch main display mode")); return NULL; } HideMenuBar(); CGDisplayRestoreColorSyncSettings(); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberSInt32Type, &refresh_rate); _set_current_refresh_rate(refresh_rate); if (CGDisplayCanSetPalette(kCGDirectMainDisplay)) osx_palette = CGPaletteCreateDefaultColorPalette(); bmp = _make_bitmap(w, h, (unsigned long)CGDisplayBaseAddress(kCGDirectMainDisplay), &gfx_quartz_full, color_depth, CGDisplayBytesPerRow(kCGDirectMainDisplay)); if (bmp) bmp->extra = calloc(1, sizeof(struct BMP_EXTRA_INFO)); if ((!bmp) || (!bmp->extra)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } screen_port = CreateNewPortForCGDisplayID((UInt32)kCGDirectMainDisplay); if (!screen_port) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot create DirectDisplay port")); return NULL; } BMP_EXTRA(bmp)->port = screen_port; setup_direct_shifts(); gfx_quartz_full.w = w; gfx_quartz_full.h = h; gfx_quartz_full.vid_mem = w * h * BYTES_PER_PIXEL(color_depth); _screen_vtable.created_sub_bitmap = osx_qz_created_sub_bitmap; if (color_depth != 8) _screen_vtable.blit_to_self = osx_qz_blit_to_self; uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("CoreGraphics DirectDisplay access, %d bpp", tmp1), color_depth); gfx_quartz_full.desc = driver_desc; osx_keyboard_focused(FALSE, 0); clear_keybuf(); osx_gfx_mode = OSX_GFX_FULL; osx_skip_mouse_move = TRUE; osx_screen_used = FALSE; if (color_depth != 8) { gfx_quartz_full.set_mouse_sprite = osx_mouse_set_sprite; gfx_quartz_full.show_mouse = osx_mouse_show; gfx_quartz_full.hide_mouse = osx_mouse_hide; gfx_quartz_full.move_mouse = osx_mouse_move; } else { /* 8 bit modes have problems handling hardware cursor so we disable it */ gfx_quartz_full.set_mouse_sprite = NULL; gfx_quartz_full.show_mouse = NULL; gfx_quartz_full.hide_mouse = NULL; gfx_quartz_full.move_mouse = NULL; CGDisplayHideCursor(kCGDirectMainDisplay); } old_visible_bmp = bmp; return bmp; } static BITMAP *osx_qz_full_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; _unix_lock_mutex(osx_event_mutex); bmp = private_osx_qz_full_init(w, h, v_w, v_h, color_depth); _unix_unlock_mutex(osx_event_mutex); _unix_lock_mutex(osx_skip_events_processing_mutex); osx_skip_events_processing = FALSE; _unix_unlock_mutex(osx_skip_events_processing_mutex); if (!bmp) osx_qz_full_exit(bmp); return bmp; } /* osx_qz_full_exit: * Shuts down fullscreen gfx mode. */ static void osx_qz_full_exit(BITMAP *bmp) { _unix_lock_mutex(osx_event_mutex); if ((bmp) && (bmp->extra)) { if (BMP_EXTRA(bmp)->port) DisposeGWorld(BMP_EXTRA(bmp)->port); free(bmp->extra); } if (osx_palette) { CGPaletteRelease(osx_palette); osx_palette = NULL; } if (old_mode) { osx_fade_screen(FALSE, 0.1); CGDisplaySwitchToMode(kCGDirectMainDisplay, old_mode); CGDisplayRelease(kCGDirectMainDisplay); ShowMenuBar(); if (bitmap_color_depth(bmp) == 8) CGDisplayShowCursor(kCGDirectMainDisplay); osx_fade_screen(TRUE, 0.2); CGDisplayRestoreColorSyncSettings(); old_mode = NULL; } osx_gfx_mode = OSX_GFX_NONE; _unix_unlock_mutex(osx_event_mutex); _unix_lock_mutex(osx_skip_events_processing_mutex); osx_skip_events_processing = TRUE; _unix_unlock_mutex(osx_skip_events_processing_mutex); } /* osx_qz_full_vsync: * Quartz video vertical synchronization routine for fullscreen mode. */ static void osx_qz_full_vsync(void) { CGDisplayWaitForBeamPositionOutsideLines(kCGDirectMainDisplay, 0, gfx_quartz_full.h / 2); CGDisplayWaitForBeamPositionOutsideLines(kCGDirectMainDisplay, gfx_quartz_full.h / 2, gfx_quartz_full.h - 1); } /* osx_qz_full_set_palette: * Sets palette for quartz fullscreen. */ static void osx_qz_full_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { int i; CGDeviceColor color; if (!CGDisplayCanSetPalette(kCGDirectMainDisplay)) return; _unix_lock_mutex(osx_event_mutex); for (i = from; i <= to; i++) { color.red = ((float)p[i].r / 63.0); color.green = ((float)p[i].g / 63.0); color.blue = ((float)p[i].b / 63.0); CGPaletteSetColorAtIndex(osx_palette, color, i); } osx_palette_dirty = TRUE; _unix_unlock_mutex(osx_event_mutex); } /* osx_qz_show_video_bitmap: * Displays a video bitmap on the screen by copying it using CopyBits * (hw accelerated copy). */ static int osx_qz_show_video_bitmap(BITMAP *bmp) { Rect rect; unsigned char *addr; int i; if ((bmp->w != gfx_quartz_full.w) || (bmp->h != gfx_quartz_full.h)) return -1; SetRect(&rect, 0, 0, bmp->w, bmp->h); while (!QDDone(screen_port)); while (!QDDone(BMP_EXTRA(bmp)->port)); LockPortBits(screen_port); LockPortBits(BMP_EXTRA(bmp)->port); if (_wait_for_vsync) osx_qz_full_vsync(); CopyBits(GetPortBitMapForCopyBits(BMP_EXTRA(bmp)->port), GetPortBitMapForCopyBits(screen_port), &rect, &rect, srcCopy, NULL); UnlockPortBits(screen_port); UnlockPortBits(BMP_EXTRA(bmp)->port); /* Since we're copying instead of page flipping, we have to make sure * the page now in the back does not have line pointers pointing to * the real screen, so we swap them with the page now in the front. */ for (i = 0; i < bmp->h; i++) { addr = bmp->line[i]; bmp->line[i] = old_visible_bmp->line[i]; old_visible_bmp->line[i] = addr; } old_visible_bmp = bmp; return 0; } /* osx_qz_fetch_mode_list: * Creates a list of available fullscreen video modes. */ static GFX_MODE_LIST *osx_qz_fetch_mode_list(void) { GFX_MODE_LIST *gfx_mode_list = NULL; GFX_MODE *gfx_mode; CFArrayRef modes_list; CFDictionaryRef mode; int i, j, num_modes; int width, height, bpp; int already_stored; modes_list = CGDisplayAvailableModes(kCGDirectMainDisplay); if (!modes_list) return NULL; num_modes = CFArrayGetCount(modes_list); gfx_mode_list = (GFX_MODE_LIST *)malloc(sizeof(GFX_MODE_LIST)); if (!gfx_mode_list) return NULL; gfx_mode_list->mode = NULL; gfx_mode_list->num_modes = 0; for (i = 0; i < num_modes; i++) { mode = CFArrayGetValueAtIndex(modes_list, i); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayWidth), kCFNumberSInt32Type, &width); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayHeight), kCFNumberSInt32Type, &height); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel), kCFNumberSInt32Type, &bpp); if (bpp == 16) bpp = 15; already_stored = FALSE; for (j = 0; j < gfx_mode_list->num_modes; j++) { if ((gfx_mode_list->mode[j].width == width) && (gfx_mode_list->mode[j].height == height) && (gfx_mode_list->mode[j].bpp == bpp)) { already_stored = TRUE; break; } } if (!already_stored) { gfx_mode_list->num_modes++; gfx_mode = (GFX_MODE *)realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1)); if (!gfx_mode) { free(gfx_mode_list->mode); free(gfx_mode_list); return NULL; } gfx_mode_list->mode = gfx_mode; gfx_mode = &gfx_mode_list->mode[gfx_mode_list->num_modes - 1]; gfx_mode->width = width; gfx_mode->height = height; gfx_mode->bpp = bpp; } } if (gfx_mode_list->mode) { gfx_mode_list->mode[gfx_mode_list->num_modes].width = 0; gfx_mode_list->mode[gfx_mode_list->num_modes].height = 0; gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = 0; } else { free(gfx_mode_list); return NULL; } return gfx_mode_list; } allegro-4.4.3.1/src/macosx/drivers.m0000664000175000017500000000363013437077643016217 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of MacOS X drivers. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error Something is wrong with the makefile #endif _DRIVER_INFO _keyboard_driver_list[] = { { KEYBOARD_MACOSX, &keyboard_macosx, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _timer_driver_list[] = { { TIMERDRV_UNIX_PTHREADS, &timerdrv_unix_pthreads, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _mouse_driver_list[] = { { MOUSE_MACOSX, &mouse_macosx, TRUE }, { 0, NULL, 0 } }; BEGIN_GFX_DRIVER_LIST { GFX_QUARTZ_FULLSCREEN, &gfx_quartz_full, TRUE }, { GFX_QUARTZ_WINDOW, &gfx_quartz_window, TRUE }, END_GFX_DRIVER_LIST BEGIN_DIGI_DRIVER_LIST { DIGI_CORE_AUDIO, &digi_core_audio, TRUE }, { DIGI_SOUND_MANAGER, &digi_sound_manager, TRUE }, END_DIGI_DRIVER_LIST BEGIN_MIDI_DRIVER_LIST { MIDI_CORE_AUDIO, &midi_core_audio, TRUE }, { MIDI_QUICKTIME, &midi_quicktime, TRUE }, END_MIDI_DRIVER_LIST BEGIN_JOYSTICK_DRIVER_LIST { JOYSTICK_HID, &joystick_hid, TRUE }, END_JOYSTICK_DRIVER_LIST allegro-4.4.3.1/src/macosx/keybd.m0000664000175000017500000001431013437077643015634 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOS X keyboard module. * * By Angelo Mottola. * * Based on Unix/X11 version by Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintosx.h" #ifndef ALLEGRO_MACOSX #error Something is wrong with the makefile #endif static int osx_keyboard_init(void); static void osx_keyboard_exit(void); /* Mac keycode to Allegro scancode conversion table */ static const int mac_to_scancode[128] = { /* 0x00 */ KEY_A, KEY_S, KEY_D, KEY_F, /* 0x04 */ KEY_H, KEY_G, KEY_Z, KEY_X, /* 0x08 */ KEY_C, KEY_V, 0, KEY_B, /* 0x0c */ KEY_Q, KEY_W, KEY_E, KEY_R, /* 0x10 */ KEY_Y, KEY_T, KEY_1, KEY_2, /* 0x14 */ KEY_3, KEY_4, KEY_6, KEY_5, /* 0x18 */ KEY_EQUALS, KEY_9, KEY_7, KEY_MINUS, /* 0x1c */ KEY_8, KEY_0, KEY_CLOSEBRACE, KEY_O, /* 0x20 */ KEY_U, KEY_OPENBRACE, KEY_I, KEY_P, /* 0x24 */ KEY_ENTER, KEY_L, KEY_J, KEY_QUOTE, /* 0x28 */ KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, /* 0x2c */ KEY_SLASH, KEY_N, KEY_M, KEY_STOP, /* 0x30 */ KEY_TAB, KEY_SPACE, KEY_BACKQUOTE, KEY_BACKSPACE, /* 0x34 */ KEY_ENTER, KEY_ESC, 0, KEY_COMMAND, /* 0x38 */ KEY_LSHIFT, KEY_CAPSLOCK, KEY_ALT, KEY_LEFT, /* 0x3c */ KEY_RIGHT, KEY_DOWN, KEY_UP, 0, /* 0x40 */ 0, KEY_STOP, 0, KEY_ASTERISK, /* 0x44 */ 0, KEY_PLUS_PAD, 0, KEY_NUMLOCK, /* 0x48 */ 0, 0, 0, KEY_SLASH_PAD, /* 0x4c */ KEY_ENTER_PAD, 0, KEY_MINUS_PAD, 0, /* 0x50 */ 0, KEY_EQUALS_PAD, KEY_0_PAD, KEY_1_PAD, /* 0x54 */ KEY_2_PAD, KEY_3_PAD, KEY_4_PAD, KEY_5_PAD, /* 0x58 */ KEY_6_PAD, KEY_7_PAD, 0, KEY_8_PAD, /* 0x5c */ KEY_9_PAD, 0, 0, 0, /* 0x60 */ KEY_F5, KEY_F6, KEY_F7, KEY_F3, /* 0x64 */ KEY_F8, KEY_F9, 0, KEY_F11, /* 0x68 */ 0, KEY_PRTSCR, 0, KEY_SCRLOCK, /* 0x6c */ 0, KEY_F10, 0, KEY_F12, /* 0x70 */ 0, KEY_PAUSE, KEY_INSERT, KEY_HOME, /* 0x74 */ KEY_PGUP, KEY_DEL, KEY_F4, KEY_END, /* 0x78 */ KEY_F2, KEY_PGDN, KEY_F1, KEY_LEFT, /* 0x7c */ KEY_RIGHT, KEY_DOWN, KEY_UP, 0 }; static unsigned int old_mods = 0; KEYBOARD_DRIVER keyboard_macosx = { KEYBOARD_MACOSX, empty_string, empty_string, "MacOS X keyboard", TRUE, osx_keyboard_init, osx_keyboard_exit, NULL, // AL_METHOD(void, poll, (void)); NULL, // AL_METHOD(void, set_leds, (int leds)); NULL, // AL_METHOD(void, set_rate, (int delay, int rate)); NULL, // AL_METHOD(void, wait_for_input, (void)); NULL, // AL_METHOD(void, stop_waiting_for_input, (void)); NULL, // AL_METHOD(int, scancode_to_ascii, (int scancode)); NULL // scancode_to_name }; /* osx_keyboard_handler: * Keyboard "interrupt" handler. */ void osx_keyboard_handler(int pressed, NSEvent *event) { const char character = [[event charactersIgnoringModifiers] lossyCString][0]; int scancode = mac_to_scancode[[event keyCode]]; int modifiers = [event modifierFlags]; if (pressed) { if (modifiers & NSAlternateKeyMask) _handle_key_press(0, scancode); else { if ((modifiers & NSControlKeyMask) && (isalpha(character))) _handle_key_press(tolower(character) - 'a' + 1, scancode); else _handle_key_press(character, scancode); } if ((three_finger_flag) && (scancode == KEY_END) && (_key_shifts & (KB_CTRL_FLAG | KB_ALT_FLAG))) { raise(SIGTERM); } } else _handle_key_release(scancode); } /* osx_keyboard_modifier: * Handles keyboard modifiers changes. */ void osx_keyboard_modifiers(unsigned int mods) { unsigned const int mod_info[5][3] = { { NSAlphaShiftKeyMask, KB_CAPSLOCK_FLAG, KEY_CAPSLOCK }, { NSShiftKeyMask, KB_SHIFT_FLAG, KEY_LSHIFT }, { NSControlKeyMask, KB_CTRL_FLAG, KEY_LCONTROL }, { NSAlternateKeyMask, KB_ALT_FLAG, KEY_ALT }, { NSCommandKeyMask, KB_COMMAND_FLAG, KEY_COMMAND } }; int i, changed; for (i = 0; i < 5; i++) { changed = (mods ^ old_mods) & mod_info[i][0]; if (changed) { if (mods & mod_info[i][0]) { _key_shifts |= mod_info[i][1]; _handle_key_press(-1, mod_info[i][2]); if (i == 0) /* Caps lock requires special handling */ _handle_key_release(mod_info[0][2]); } else { _key_shifts &= ~mod_info[i][1]; if (i == 0) _handle_key_press(-1, mod_info[0][2]); _handle_key_release(mod_info[i][2]); } } } old_mods = mods; } /* osx_keyboard_focused: * Keyboard focus change handler. */ void osx_keyboard_focused(int focused, int state) { int i, mask; if (focused) { mask = KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG; _key_shifts = (_key_shifts & ~mask) | (state & mask); } else { for (i=0; imBuffers[0].mData, 0, TRUE); return 0; } static int ca_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) return FALSE; return TRUE; } static int ca_init(int input, int voices) { AudioDeviceID audio_device; ComponentDescription desc; AUNode output_node, converter_node; AURenderCallbackStruct render_cb; UInt32 property_size, buffer_size; AudioStreamBasicDescription input_format_desc, output_format_desc; char device_name[64], manufacturer[64]; UInt32 device_name_size, manufacturer_size; char tmp1[256], tmp2[256], tmp3[256]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MacOS X.2 or newer required by this driver")); return -1; } NewAUGraph(&graph); desc.componentType = kAudioUnitType_FormatConverter; desc.componentSubType = kAudioUnitSubType_AUConverter; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AUGraphNewNode(graph, &desc, 0, NULL, &converter_node); desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AUGraphNewNode(graph, &desc, 0, NULL, &output_node); AUGraphOpen(graph); AUGraphInitialize(graph); AUGraphGetNodeInfo(graph, output_node, NULL, NULL, NULL, &output_unit); AUGraphGetNodeInfo(graph, converter_node, NULL, NULL, NULL, &converter_unit); property_size = sizeof(output_format_desc); if (AudioUnitGetProperty(output_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &output_format_desc, &property_size)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot detect output audio format")); ca_exit(FALSE); return -1; } input_format_desc.mSampleRate = output_format_desc.mSampleRate; input_format_desc.mFormatID = kAudioFormatLinearPCM; #ifdef ALLEGRO_BIG_ENDIAN input_format_desc.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; #else input_format_desc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; #endif input_format_desc.mBytesPerPacket = 4; input_format_desc.mFramesPerPacket = 1; input_format_desc.mBytesPerFrame = 4; input_format_desc.mChannelsPerFrame = 2; input_format_desc.mBitsPerChannel = 16; if (AudioUnitSetProperty(converter_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &output_format_desc, sizeof(output_format_desc)) || AudioUnitSetProperty(converter_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &input_format_desc, sizeof(input_format_desc))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot configure format converter audio unit")); ca_exit(FALSE); return -1; } _sound_bits = 16; _sound_stereo = TRUE; _sound_freq = (int)output_format_desc.mSampleRate; AUGraphConnectNodeInput(graph, converter_node, 0, output_node, 0); render_cb.inputProc = render_callback; render_cb.inputProcRefCon = NULL; if (AudioUnitSetProperty(converter_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &render_cb, sizeof(render_cb))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot set audio rendering callback")); ca_exit(FALSE); return -1; } property_size = sizeof(audio_device); if (AudioUnitGetProperty(output_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Output, 0, &audio_device, &property_size)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot get CoreAudio device")); ca_exit(FALSE); return -1; } property_size = sizeof(buffer_size); if (AudioDeviceGetProperty(audio_device, 0, false, kAudioDevicePropertyBufferSize, &property_size, &buffer_size)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot get CoreAudio device buffer size")); ca_exit(FALSE); return -1; } audio_buffer_size = buffer_size / sizeof(float) * sizeof(short); digi_core_audio.voices = voices; if (_mixer_init(audio_buffer_size / sizeof(short), _sound_freq, _sound_stereo, TRUE, &digi_core_audio.voices)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error initializing mixer")); ca_exit(FALSE); return -1; } AUGraphStart(graph); device_name_size = sizeof(device_name); manufacturer_size = sizeof(manufacturer); if (!AudioDeviceGetProperty(audio_device, 0, false, kAudioDevicePropertyDeviceName, &device_name_size, device_name) && !AudioDeviceGetProperty(audio_device, 0, false, kAudioDevicePropertyDeviceManufacturer, &manufacturer_size, manufacturer)) { uszprintf(ca_desc, sizeof(ca_desc), get_config_text("%s (%s), 16 bits (%d real), %d bps, %s"), uconvert_ascii(device_name, tmp1), uconvert_ascii(manufacturer, tmp2), output_format_desc.mBitsPerChannel, _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp3)); } else { uszprintf(ca_desc, sizeof(ca_desc), get_config_text("16 bits (%d real), %d bps, %s"), output_format_desc.mBitsPerChannel, _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp3)); } digi_core_audio.desc = ca_desc; return 0; } static void ca_exit(int input) { if (input) return; AUGraphStop(graph); AUGraphUninitialize(graph); AUGraphClose(graph); DisposeAUGraph(graph); _mixer_exit(); } static int ca_buffer_size() { return audio_buffer_size; } static int ca_set_mixer_volume(int volume) { float value = (float)volume / 255.0; return AudioUnitSetParameter(converter_unit, kAudioUnitParameterUnit_LinearGain, kAudioUnitScope_Output, 0, value, 0); } allegro-4.4.3.1/src/mac/0000775000175000017500000000000013437077643013627 5ustar siegesiegeallegro-4.4.3.1/src/mac/mmid.c0000664000175000017500000001505713437077643014731 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MIDI driver routines for MacOS. * * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintmac.h" #include #ifndef ALLEGRO_MPW #error something is wrong with the makefile #endif static NoteAllocator qtna=0; static struct{ NoteChannel channel; int note; int inst; int vol; int pan; }macmidivoices[17]; static int mac_midi_detect(int input); static int mac_midi_init(int input, int voices); static void mac_midi_exit(int input); static int mac_midi_set_mixer_volume(int volume); static void mac_midi_key_on(int inst, int note, int bend, int vol, int pan); static void mac_midi_key_off(int voice); static void mac_midi_set_volume(int voice, int vol); static void mac_midi_set_pitch(int voice, int note, int bend); static void mac_midi_set_pan(int voice, int pan); MIDI_DRIVER midi_quicktime = { MIDI_QUICKTIME, /* driver ID code */ empty_string, /* driver name */ empty_string, /* description string */ "QuickTime Midi", /* ASCII format name string */ 16, /* available voices */ 0, /* voice number offset */ 16, /* maximum voices we can support */ 0, /* default number of voices to use */ 10, 10, /* reserved voice range */ mac_midi_detect, /* AL_METHOD(int, detect, (int input)); */ mac_midi_init, /* AL_METHOD(int, init, (int input, int voices)); */ mac_midi_exit, /* AL_METHOD(void, exit, (int input)); */ mac_midi_set_mixer_volume,/* AL_METHOD(int, mixer_set_volume, (int volume)); */ NULL, /* AL_METHOD(int, mixer_get_volume, (void)); */ NULL, /* AL_METHOD(void, raw_midi, (int data)); */ _dummy_load_patches, /* AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ _dummy_adjust_patches, /* AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ mac_midi_key_on, /* AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); */ mac_midi_key_off, /* AL_METHOD(void, key_off, (int voice)); */ mac_midi_set_volume, /* AL_METHOD(void, set_volume, (int voice, int vol)); */ mac_midi_set_pitch, /* AL_METHOD(void, set_pitch, (int voice, int note, int bend)); */ mac_midi_set_pan, /* AL_METHOD(void, set_pan, (int voice, int pan)); */ _dummy_noop2, /* AL_METHOD(void, set_vibrato, (int voice, int amount)); */ }; /* mac_midi_detect: * MacOS MIDI detection. */ static int mac_midi_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } return TRUE; } /* mac_midi_init: * Initializes the MacOS MIDI driver. */ static int mac_midi_init(int input, int voices) { NoteRequest nr; ComponentResult thisError; int i; qtna = OpenDefaultComponent(kNoteAllocatorComponentType, 0); printf("na=%d",qtna); if(!qtna){ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("open NoteAllocator failed")); printf("open NoteAllocator failed\n"); return -1; } for(i=1;i<17;i++){ nr.info.flags = 0; nr.info.reserved = 0; nr.info.polyphony = 2; nr.info.typicalPolyphony = 0x00010000; macmidivoices[i].inst = (i==10)?16385:1; macmidivoices[i].vol = -1; macmidivoices[i].pan = -1; macmidivoices[i].note = 0; thisError = NAStuffToneDescription(qtna, macmidivoices[i].inst, &nr.tone); thisError = NANewNoteChannel(qtna, &nr, &macmidivoices[i].channel); if(thisError || !macmidivoices[i].channel){ mac_midi_exit(input); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("failed on channel initialization")); printf("failed on init %s channel",i); return -1; } } return 0; } /* mac_midi_exit: * Shuts down MIDI subsystem. */ static void mac_midi_exit(int input) { int i; if (qtna){ for(i=1; (i<17) && macmidivoices[i].channel;i++){ mac_midi_key_off(i); NADisposeNoteChannel(qtna, macmidivoices[i].channel); macmidivoices[i].channel = 0; } CloseComponent(qtna); qtna=0; } } /* mac_midi_set_mixer_volume: * Sets MIDI mixer output volume. */ static int mac_midi_set_mixer_volume(int volume) { return 0; } /* mac_midi_key_on: * Triggers a specified voice. */ static void mac_midi_key_on(int inst, int note, int bend, int vol, int pan) { int voice; NoteChannel ch; ComponentResult thisError; printf("keyon(%d,%d,%d,%d,%d)\n",inst, note, bend, vol,pan); if (inst < 128) { voice = _midi_allocate_voice(1, 16); } else { inst = inst+16385-128; voice = _midi_allocate_voice(10,10); } ch = macmidivoices[voice].channel; if(!ch) return; mac_midi_key_off(voice); if(macmidivoices[voice].inst!=inst){ thisError = NASetInstrumentNumber/*InterruptSafe*/(qtna,ch,inst); macmidivoices[voice].inst=inst; }; if(macmidivoices[voice].vol!=vol){ thisError = NASetNoteChannelVolume(qtna,ch,vol<<8); macmidivoices[voice].vol=vol; }; if(macmidivoices[voice].pan!=pan){ thisError = NASetNoteChannelBalance(qtna,ch,pan-128); macmidivoices[voice].pan=pan; }; thisError = NAPlayNote(qtna,ch,note,80); macmidivoices[voice].note=note; } /* mac_midi_key_off: * Turns off specified voice. */ static void mac_midi_key_off(int voice) { if(macmidivoices[voice].channel) NAPlayNote(qtna,macmidivoices[voice].channel,macmidivoices[voice].note,0); } /* mac_midi_set_volume: * Sets volume for a specified voice. */ static void mac_midi_set_volume(int voice, int vol) { } /* mac_midi_set_pitch: * Sets pitch of specified voice. */ static void mac_midi_set_pitch(int voice, int note, int bend) { } /* mac_midi_set_pan: * Sets pan value on specified voice. */ static void mac_midi_set_pan(int voice, int pan) { } allegro-4.4.3.1/src/mac/msbmp.c0000664000175000017500000004306413437077643015120 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * System bitmaps support. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "macalleg.h" #include "allegro/platform/aintmac.h" #include #pragma mark system bitmaps vtables GFX_VTABLE __mac_sys_vtable8; GFX_VTABLE __mac_sys_vtable15; GFX_VTABLE __mac_sys_vtable24; GFX_VTABLE __cache_vtable8; GFX_VTABLE __cache_vtable15; GFX_VTABLE __cache_vtable24; extern void _mac_sys_clear15(struct BITMAP *bmp,int color); extern void _mac_sys_putpixel8(BITMAP *dst, int x, int y, int color); extern void _ppc_linear_putpixel8(BITMAP *dst, int x, int y, int color); extern void _ppc_linear_hline8(BITMAP *dst, int x1, int y, int x2, int color); extern void _ppc_linear_hline8_32(BITMAP *dst, int x1, int y, int x2, int color); extern void _ppc_linear_vline8(BITMAP *dst, int x, int y1, int y2, int color); extern void _ppc_linear_rectfill8(BITMAP *dst, int x1, int y1, int x2, int y2, int color); extern void _ppc_linear_rectfill8_32(BITMAP *dst, int x1, int y1, int x2, int y2, int color); extern void _ppc_linear_clear_to_color8(BITMAP *dst, int color); extern void _ppc_linear_clear_to_color8_32(BITMAP *dst, int color); extern void _ppc_linear_clear_to_color15(BITMAP *dst, int color); extern void _ppc_linear_clear_to_color15_32(BITMAP *dst, int color); #pragma mark system bitmaps methods /* * */ void _mac_init_system_bitmap(void){ BlockMove(&__linear_vtable8,&__mac_sys_vtable8,sizeof(GFX_VTABLE)); BlockMove(&__linear_vtable15,&__mac_sys_vtable15,sizeof(GFX_VTABLE)); BlockMove(&__linear_vtable24,&__mac_sys_vtable24,sizeof(GFX_VTABLE)); __mac_sys_vtable8.clear_to_color=_ppc_linear_clear_to_color8; __mac_sys_vtable8.rectfill=_ppc_linear_rectfill8; __mac_sys_vtable8.blit_to_self=_mac_sys_blit8; __mac_sys_vtable8.blit_to_self_forward=_mac_sys_selfblit8; __mac_sys_vtable8.blit_to_self_backward=_mac_sys_selfblit8; __mac_sys_vtable8.putpixel=_ppc_linear_putpixel8; __mac_sys_vtable8.hline=_ppc_linear_hline8; __mac_sys_vtable8.vline=_ppc_linear_vline8; __mac_sys_vtable15.blit_to_self=_mac_sys_blit8; __mac_sys_vtable15.blit_to_self_forward=_mac_sys_selfblit8; __mac_sys_vtable15.blit_to_self_backward=_mac_sys_selfblit8; __mac_sys_vtable15.clear_to_color=_ppc_linear_clear_to_color15; BlockMove(&__mac_sys_vtable8,&__cache_vtable8,sizeof(GFX_VTABLE)); BlockMove(&__mac_sys_vtable15,&__cache_vtable15,sizeof(GFX_VTABLE)); BlockMove(&__mac_sys_vtable24,&__cache_vtable24,sizeof(GFX_VTABLE)); __cache_vtable8.clear_to_color=_ppc_linear_clear_to_color8_32; __cache_vtable8.hline=_ppc_linear_hline8_32; __cache_vtable8.rectfill=_ppc_linear_rectfill8_32; __cache_vtable15.clear_to_color=_ppc_linear_clear_to_color15_32; } /* * */ BITMAP *_mac_create_system_bitmap(int w, int h){ BITMAP *b; CGrafPtr graf; GDHandle oldDevice; Ptr data; unsigned char*theseBits; long sizeOfOff, offRowBytes; short thisDepth; Rect bounds; int size; mac_bitmap *mb; int i; SetRect(&bounds,0,0,w,h); oldDevice = GetGDevice(); SetGDevice(MainGDevice); graf = (CGrafPtr)NewPtrClear(sizeof(CGrafPort)); if (graf != 0L){ OpenCPort(graf); thisDepth = (**(*graf).portPixMap).pixelSize; offRowBytes = ((((long)thisDepth *(long)w) + 255L) >> 8L) << 5L; sizeOfOff = (long)h * offRowBytes+32; data = NewPtrClear(sizeOfOff); theseBits=(unsigned char*)((long)(data+31)&(-32L)); if (theseBits != 0L){ (**(*graf).portPixMap).baseAddr = (char*)theseBits; (**(*graf).portPixMap).rowBytes = (short)offRowBytes + 0x8000; (**(*graf).portPixMap).bounds = bounds; (**(*graf).portPixMap).pmTable = MainCTable; ClipRect(&bounds); RectRgn(graf->visRgn,&bounds); ForeColor(blackColor); BackColor(whiteColor); EraseRect(&bounds); } else { CloseCPort(graf); DisposePtr((Ptr)graf); graf = 0L; return NULL; } } SetGDevice(oldDevice); size = sizeof(mac_bitmap); mb = (mac_bitmap *)NewPtr(size); if (!mb)return NULL; mb->cg=graf; mb->rowBytes=offRowBytes; mb->data=data; mb->first=theseBits; mb->flags=1; if((long)theseBits&31){ mb->cachealigned=0; } else{ mb->cachealigned=1; } size=sizeof(BITMAP)+ sizeof(char *) * h; b=(BITMAP*)NewPtr(size); if(b==NULL){ DisposePtr((Ptr)mb);return NULL; } b->w = b->cr = w; b->h = b->cb = h; b->clip = TRUE; b->cl = b->ct = 0; switch((**(*graf).portPixMap).pixelSize){ case 8: b->vtable = &__cache_vtable8; break; case 16: b->vtable = &__cache_vtable15; break; case 32: b->vtable = &__cache_vtable24; break; default: DisposePtr((Ptr)b); DisposePtr((Ptr)mb); b=NULL; } /* b->vtable = &__mac_sys_vtable8;*/ b->write_bank = b->read_bank = _stub_bank_switch; b->dat = NULL; b->id = BMP_ID_SYSTEM; b->extra = (void*)mb; b->x_ofs = 0; b->y_ofs = 0; b->seg = _video_ds(); b->line[0] = (unsigned char *)theseBits; for (i=1; iline[i] = b->line[i-1] + offRowBytes; mb->last=b->line[i-1]+w; return b; } /* * */ void _mac_destroy_system_bitmap(BITMAP *bmp){ mac_bitmap *mbmp; if(bmp){ mbmp=GETMACBITMAP(bmp); if(mbmp){ if(mbmp->flags){ if(mbmp->data){ CloseCPort(mbmp->cg); DisposePtr((Ptr)mbmp->cg); DisposePtr(mbmp->data); } } DisposePtr((Ptr)mbmp); } else{ bmp->id&=~BMP_ID_SYSTEM; destroy_bitmap(bmp); } DisposePtr((Ptr)bmp); } } /* * */ void _mac_sys_set_clip(struct BITMAP *dst){ RgnHandle rclip; mac_bitmap *mdst; mdst=GETMACBITMAP(dst); SetPort((GrafPtr)mdst->cg); rclip=NewRgn(); MacSetRectRgn(rclip,dst->cl,dst->ct,dst->cr,dst->cb); SetClip(rclip); DisposeRgn(rclip); } /* * */ void _mac_sys_clear_to_color8 (BITMAP *bmp, int color){ int w,h,inc,wr; unsigned char *p; float f; color&=0xFF; *(long *)(&f)=color*0x1010101; h=bmp->h; wr=bmp->w; p=bmp->line[0]; inc=bmp->line[1]-bmp->line[0]-wr; while(h){ w=wr; while(w){ *p++=color; w--; } p=p+inc; h--; } } /* * */ void _mac_sys_blit8(BITMAP *src,BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h){ DSpBlitInfo di; Rect rsrc,rdst; mac_bitmap *msrc; mac_bitmap *mdst; msrc=GETMACBITMAP(src); mdst=GETMACBITMAP(dst); SetRect(&rsrc,src_x,src_y,src_x+w,src_y+h); SetRect(&rdst,dst_x,dst_y,dst_x+w,dst_y+h); SetPort((GrafPtr)mdst->cg); di.completionFlag=false; di.filler[0]=0; di.filler[1]=0; di.filler[2]=0; di.filler[3]=0; di.completionProc=NULL; di.srcContext=NULL; di.srcBuffer=msrc->cg; di.srcRect=rsrc; di.srcKey=0; di.dstContext=NULL; di.dstBuffer=mdst->cg; di.dstRect=rdst; di.dstKey=0; di.mode=0; di.reserved[0]=0; di.reserved[1]=0; di.reserved[2]=0; di.reserved[3]=0; DSpBlit_Fastest(&di,false); } /* * */ void system_stretch_blit(BITMAP *src,BITMAP *dst,int sx,int sy,int sw,int sh,int dx,int dy,int dw,int dh){ Rect rsrc,rdst; RgnHandle rclip; mac_bitmap *msrc; mac_bitmap *mdst; msrc=GETMACBITMAP(src); mdst=GETMACBITMAP(dst); SetRect(&rsrc,sx,sy,sx+sw,sy+sh); SetRect(&rdst,dx,dy,dx+dw,dy+dh); SetPort((GrafPtr)mdst->cg); rclip=NewRgn(); MacSetRectRgn(rclip,dst->cl,dst->ct,dst->cr,dst->cb); SetClip(rclip); DisposeRgn(rclip); CopyBits( &((GrafPtr)msrc->cg)->portBits, &((GrafPtr)mdst->cg)->portBits, &rsrc,&rdst,srcCopy,NULL); } /* * */ void _mac_sys_selfblit8(BITMAP *src,BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h){ Rect rsrc,rdst; mac_bitmap *msrc; mac_bitmap *mdst; msrc=GETMACBITMAP(src); mdst=GETMACBITMAP(dst); SetRect(&rsrc,src_x,src_y,src_x+w,src_y+h); SetRect(&rdst,dst_x,dst_y,dst_x+w,dst_y+h); SetPort((GrafPtr)mdst->cg); CopyBits( &((GrafPtr)msrc->cg)->portBits, &((GrafPtr)mdst->cg)->portBits, &rsrc,&rdst,srcCopy,NULL); } /* * */ int _mac_sys_triangle(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color){ int done=0; mac_bitmap *mbmp; PolyHandle triPoly; if(_drawing_mode==DRAW_MODE_SOLID){ mbmp=GETMACBITMAP(bmp); SetPort((GrafPtr)mbmp->cg); RGBForeColor(&((**MainCTable).ctTable[color].rgb)); triPoly = OpenPoly(); MoveTo(x1,y1); LineTo(x2,y2); LineTo(x3,y3); ClosePoly(); PaintPoly(triPoly); KillPoly(triPoly); done=1; } return done; } /* * */ void _mac_sys_rectfill8(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color){ mac_bitmap *mbmp; BITMAP *parent; Rect r; int t; if(x1>x2){t=x1;x1=x2;x2=t;} if(y1>y2){t=y1;y1=y2;y2=t;} if(bmp->clip) { if (x1 < bmp->cl)x1 = bmp->cl; if (x2 >= bmp->cr)x2 = bmp->cr-1; if (x2 < x1)return; if (y1 < bmp->ct)y1 = bmp->ct; if (y2 >= bmp->cb)y2 = bmp->cb-1; if (y2 < y1)return; } switch(_drawing_mode){ case DRAW_MODE_SOLID: SetRect(&r,x1,y1,x2+1,y2+1); parent = bmp; mbmp=GETMACBITMAP(bmp); SetPort((GrafPtr)mbmp->cg); RGBForeColor(&((**MainCTable).ctTable[color].rgb)); PaintRect(&r); RGBForeColor(&ForeDef); break; default: _normal_rectfill(bmp,x1,y1,x2,y2,color); break; } } /* * */ void _mac_sys_hline8(struct BITMAP *bmp, int x1, int y, int x2, int color) { #define CALC_PATTERN() xoff=(x1 - _drawing_x_anchor) & _drawing_x_mask;\ sbase = _drawing_pattern->line[(y - _drawing_y_anchor) & _drawing_y_mask];\ s_end = sbase+_drawing_x_mask+1;\ s = sbase+xoff;\ xoff=_drawing_x_mask+1-(((long)last-(long)p)&_drawing_x_mask)-xoff;\ if(xoff>=0)xoff-=(_drawing_x_mask+1);\ last1=last+xoff unsigned long d; unsigned char * p; unsigned char * last; unsigned char * sbase; unsigned char * s_end; unsigned char * s; unsigned char * last1; unsigned char c=color&0xFF; int ctr; UnsignedWide uw; register double ck; long xoff; int t; if(x1>x2){t=x1;x1=x2;x2=t;} if(bmp->clip) { if ((y < bmp->ct)||(y >= bmp->cb))return; if (x1 < bmp->cl)x1 = bmp->cl; if (x2 >= bmp->cr)x2 = bmp->cr-1; if (x2 < x1)return; } last=bmp->line[y]+x2; p=bmp->line[y]+x1; d=0x01010101*c; uw.hi=d; uw.lo=d; ck=*(double*)&uw; switch(_drawing_mode){ case DRAW_MODE_SOLID: while((unsigned long)p&3L&&pdata[(unsigned char)color]; do{*p++=blender[*p];}while(p<=last); } break; case DRAW_MODE_COPY_PATTERN: CALC_PATTERN(); while(pline[1]-_drawing_pattern->line[0];\ sbase = _drawing_pattern->line[0]+xoff;\ s_end = _drawing_pattern->line[_drawing_y_mask]+xoff;\ s = _drawing_pattern->line[((y1) - _drawing_y_anchor) & _drawing_y_mask]+xoff unsigned long inc; unsigned char *p; unsigned char *last; unsigned long xoff; unsigned long pinc; unsigned char * sbase; unsigned char * s_end; unsigned char * s; unsigned char * work; int t; if(y1>y2){t=y1;y1=y2;y2=t;} if(bmp->clip) { if (y1 < bmp->ct)y1 = bmp->ct; if (y2 >= bmp->cb)y2 = bmp->cb-1; if (y2 < y1)return; if ((x < bmp->cl)||(x >= bmp->cr))return; } t=color; p=bmp->line[y1]+x; last=bmp->line[y2]+x; inc=bmp->line[1]-bmp->line[0]; switch(_drawing_mode){ case DRAW_MODE_SOLID: do{ *p = color; p += inc; }while(p <= last); break; case DRAW_MODE_XOR: do{*p ^= color;p += inc;}while(p <= last); break; case DRAW_MODE_TRANS:{ unsigned char * blender = color_map->data[(unsigned char)color]; do{*p=blender[*p];p+=inc;}while(p<=last); } break; case DRAW_MODE_COPY_PATTERN: CALC_PATTERN(); do{ work=s+(long)last-(long)p; s_end=(unsigned long)s_end<(unsigned long)work?s_end:work; do{*p=*s;p+=inc;s+=pinc;}while(s<=s_end&&p<=last); s = sbase; }while(p<=last); break; case DRAW_MODE_MASKED_PATTERN: CALC_PATTERN(); do{ work=s+(long)last-(long)p; s_end=(unsigned long)s_end<(unsigned long)work?s_end:work; do{ if(*s) *p=color; else *p=0; p += inc; s += pinc; }while(s <= s_end&&p<=last); s = sbase; }while(p <= last); break; case DRAW_MODE_SOLID_PATTERN: CALC_PATTERN(); do{ work=s+(long)last-(long)p; s_end=(unsigned long)s_end<(unsigned long)work?s_end:work; do{ if(*s) *p=color; p+=inc;s+=pinc; }while(s<=s_end&&p<=last); s = sbase; }while(p<=last); break; default: _linear_vline8(bmp,x,y1,y2,color); break; } } /* * */ void _mac_sys_putpixel8(BITMAP *dst, int x, int y, int color) { unsigned char *p; unsigned char s; if((unsigned)_drawing_mode>DRAW_MODE_TRANS){ _linear_putpixel8(dst,x,y,color); return; } if(dst->clip) { if (y < dst->ct) return; if (y >= dst->cb) return; if (x < dst->cl) return; if (x >= dst->cr) return; } p=dst->line[y]+x; if(_drawing_mode==DRAW_MODE_SOLID) *p=color; else if(_drawing_mode==DRAW_MODE_XOR) *p^=color; else if(_drawing_mode==DRAW_MODE_TRANS){ *p=color_map->data[(unsigned char)color&0xFF][*p]; } else{ s = *(_drawing_pattern->line[((y) - _drawing_y_anchor) & _drawing_y_mask] +((x - _drawing_x_anchor) & _drawing_x_mask)); if(_drawing_mode==DRAW_MODE_COPY_PATTERN) *p=s; else if(_drawing_mode==DRAW_MODE_MASKED_PATTERN){ if(s) *p=color; else *p=0; } else /*if(_drawing_mode==DRAW_MODE_SOLID_PATTERN)*/ if(s) *p=color; } } /* * */ void _mac_sys_clear15(struct BITMAP *bmp,int color){ int w,h,inc,wr; unsigned short *p; float f; color &= 0x7FFF; *(long *)(&f)=color*0x10001; h=bmp->h; wr=bmp->w; p=(unsigned short *)bmp->line[0]; inc=bmp->line[1]-bmp->line[0]-wr*2; while(h){ w=wr; while(w){ *p++=color; w--; } p=(unsigned short *)(((unsigned char *)p)+inc); h--; } } /* * */ BITMAP *_CGrafPtr_to_system_bitmap(CGrafPtr cg){ unsigned char *theseBits; long offRowBytes; Rect bounds; int size; BITMAP *b=NULL; mac_bitmap *mb; int i,h,w; GrafPtr svcg; bounds = (*cg).portRect; h=bounds.bottom-bounds.top; w=bounds.right-bounds.left; theseBits = (unsigned char *)(**(*cg).portPixMap).baseAddr; offRowBytes = 0x7FFF&(**(*cg).portPixMap).rowBytes; size = sizeof(mac_bitmap); mb = (mac_bitmap *)NewPtr(size); GetPort(&svcg); SetPort((GrafPtr)cg); ForeColor(blackColor); BackColor(whiteColor); SetPort(svcg); if (mb){ mb->flags=0; mb->cg=cg; mb->rowBytes=offRowBytes; mb->data=NULL; mb->first=theseBits; if(((long)theseBits|offRowBytes)&31) mb->cachealigned=0; else mb->cachealigned=1; size=sizeof(BITMAP)+ sizeof(char *) * h; b=(BITMAP*)NewPtr(size); if(b==NULL){DisposePtr((Ptr)mb);return NULL;} b->w = b->cr = w; b->h = b->cb = h; b->clip = TRUE; b->cl = b->ct = 0; b->write_bank = b->read_bank = _stub_bank_switch; b->dat = NULL; b->id = BMP_ID_SYSTEM; b->extra = (void*)mb; b->x_ofs = 0; b->y_ofs = 0; b->seg = _video_ds(); b->line[0] = theseBits; for (i=1; ih; i++)b->line[i] = (theseBits += offRowBytes); mb->last=theseBits+w; switch((**(*cg).portPixMap).pixelSize){ case 8: b->vtable = &__mac_sys_vtable8; break; case 16: b->vtable = &__mac_sys_vtable15; break; case 32: b->vtable = &__mac_sys_vtable24; break; default: DisposePtr((Ptr)b); DisposePtr((Ptr)mb); b=NULL; } } return b; } allegro-4.4.3.1/src/mac/allegro.r0000664000175000017500000000406313437077643015442 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacAllegro resources this file is requiered to all * applications linked with allegro.x!!! * * By Ronaldo H Yamada. * * See readme.txt for copyright information. */ #include "SysTypes.r" #include "Types.r" #include "allegro/internal/macdef.h" /*You Can modify this item*/ /*Control of Version*/ resource 'vers'(1){0x01, 0x00, release, 0x00,verUS, "1.00","1.00, Copyright ????.???? ??????" /*Which look at GetInfo from Finder*/ }; /*Please not modify the itens bellow*/ /*Definition of macallegro menssage box*/ resource 'ALRT' (rmac_message, purgeable){ {0, 0, 320, 480},rmac_message,{ OK, visible, silent, OK, visible, silent, OK, visible, silent, OK, visible, silent },centerMainScreen }; resource 'DITL' (rmac_message, purgeable) { { {280, 360, 300, 460},Button {enabled,"OK"}, {10, 60, 260, 460},StaticText {disabled,"^0"}, {8, 8, 40, 40},Icon {disabled,2} } }; /*Error strings not used yet*/ resource 'STR#' (rerror_str, purgeable) { { "Failed memory allocation"; "undefined error"; } }; /*The main application resource*/ resource 'SIZE' (-1) { dontSaveScreen, acceptSuspendResumeEvents, enableOptionSwitch, canBackground, multiFinderAware, backgroundAndForeground, dontGetFrontClicks, ignoreChildDiedEvents, is32BitCompatible, reserved, reserved, reserved, reserved, reserved, reserved, reserved, kprefsize*1024, /*pref size of memory required kprefsize is in defined macdef.h and is used in macallegro.c*/ kminsize*1024 /*min size of memory required kminsize is defined in macdef.h and is used in macallegro.c*/ }; allegro-4.4.3.1/src/mac/mkey.c0000664000175000017500000002574113437077643014751 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOs keyboard driver. * * By Ronaldo H Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "macalleg.h" #include "allegro/platform/aintmac.h" #define TRACE_MAC_KBRD 0 volatile KeyMap KeyNow; volatile KeyMap KeyOld; short _mac_keyboard_installed=FALSE; short volatile _mouse2nd = FALSE; extern short tm_running; extern volatile short _interrupt_time; static int key_mac_init(void); static void key_mac_exit(void); #define k_apple_caps 0x3E #define k_apple_shift 0x3F #define k_apple_rshift 0x38 #define k_apple_alt 0x3D #define k_apple_altgr 0x3A #define k_apple_control 0x3C #define k_apple_rcontrol 0x39 #define k_apple_command 0x30 #define k_2nd 0x30 /* mouse right button emulation */ /* The LookUp table to translate AppleKeyboard scan codes to Allegro KEY constants */ const unsigned char key_apple_to_allegro[128]= { /*00*/ KEY_X, KEY_Z, KEY_G, KEY_H, /*04*/ KEY_F, KEY_D, KEY_S, KEY_A, /*08*/ KEY_R, KEY_E, KEY_W, KEY_Q, /*0C*/ KEY_B, KEY_TILDE, KEY_V, KEY_C, /*10*/ KEY_5, KEY_6, KEY_4, KEY_3, /*14*/ KEY_2, KEY_1, KEY_T, KEY_Y, /*18*/ KEY_O, KEY_CLOSEBRACE, KEY_0, KEY_8, /*1C*/ KEY_MINUS, KEY_7, KEY_9, KEY_EQUALS, /*20*/ KEY_QUOTE, KEY_J, KEY_L, KEY_ENTER, /*24*/ KEY_P, KEY_I, KEY_OPENBRACE, KEY_U, /*28*/ KEY_STOP, KEY_M, KEY_N, KEY_SLASH, /*2C*/ KEY_COMMA, KEY_BACKSLASH, KEY_COLON, KEY_K, /*30*/ /*KEY_LWIN used for right button of mouse*/ 0, 0, KEY_ESC, 0, /*34*/ KEY_BACKSPACE, KEY_BACKSLASH2, KEY_SPACE, KEY_TAB, /*38*/ 0, KEY_RCONTROL, KEY_ALTGR,KEY_RSHIFT, /*3C*/ KEY_LCONTROL, KEY_ALT, KEY_CAPSLOCK, KEY_LSHIFT, /*40*/ KEY_NUMLOCK,0, KEY_PLUS_PAD, 0, /*44*/ KEY_ASTERISK, 0, KEY_DEL_PAD, 0, /*48*/ 0, KEY_MINUS_PAD, 0, KEY_ENTER_PAD, /*4C*/ KEY_SLASH_PAD, 0, 0, 0, /*50*/ KEY_5_PAD, KEY_4_PAD, KEY_3_PAD, KEY_2_PAD, /*54*/ KEY_1_PAD, KEY_0_PAD, 0, 0, /*58*/ 0, 0, 0, KEY_9_PAD, /*5C*/ KEY_8_PAD, 0, KEY_7_PAD, KEY_6_PAD, /*60*/ KEY_F11, 0, KEY_F9, KEY_F8, /*64*/ KEY_F3, KEY_F7, KEY_F6, KEY_F5, /*68*/ KEY_F12, 0, KEY_F10, 0, /*6C*/ KEY_SCRLOCK, 0, KEY_PRTSCR, 0, /*70*/ KEY_END, KEY_F4, KEY_DEL, KEY_PGUP, /*74*/ KEY_HOME, KEY_INSERT, KEY_PAUSE, 0, /*78*/ 0, KEY_UP, KEY_DOWN, KEY_RIGHT, /*7C*/ KEY_LEFT, KEY_F1, KEY_PGDN, KEY_F2, }; #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG) #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG) #define KB_ACCENTS (KB_ACCENT1_FLAG | KB_ACCENT2_FLAG | KB_ACCENT3_FLAG | KB_ACCENT4_FLAG) #define KB_SH_CTRL_ALT (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG) #define KB_CTRL_ALT (KB_CTRL_FLAG | KB_ALT_FLAG) /* convert Allegro format scancodes into key_shifts flag bits */ static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = { KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG, KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG, KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG, KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG }; /* convert numeric pad scancodes into arrow codes */ static unsigned char numlock_table[10] = { KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT, KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP }; /* default mapping table for the US keyboard layout */ static unsigned short standard_key_ascii_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* capslock mapping table for the US keyboard layout */ static unsigned short standard_key_capslock_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* shifted mapping table for the US keyboard layout */ static unsigned short standard_key_shift_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* ctrl+key mapping table for the US keyboard layout */ static unsigned short standard_key_control_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ 2, 2, 2, 2, 2, 10, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; KEYBOARD_DRIVER keyboard_macos ={ KEYBOARD_MACOS, empty_string, empty_string, "MacOs Key", TRUE, key_mac_init, key_mac_exit, NULL, NULL, NULL, NULL, NULL, NULL }; /* * */ void _handle_mac_key_press(short keycode) { unsigned int ascii; if(keycode >= KEY_MODIFIERS && keycode=KEY_MODIFIERS&&keycode _DRIVER_INFO _system_driver_list[] ={ {SYSTEM_MACOS, &system_macos, TRUE}, {SYSTEM_NONE, &system_none, TRUE}, {0, NULL, 0} }; _DRIVER_INFO _timer_driver_list[] ={ {TIMER_MACOS, &timer_macos, TRUE}, {0, NULL, 0} }; _DRIVER_INFO _mouse_driver_list[] ={ {MOUSE_MACOS, &mouse_macos, TRUE}, {MOUSE_ADB, &mouse_adb, TRUE}, {MOUSEDRV_NONE, &mousedrv_none, TRUE}, {0, NULL, 0} }; _DRIVER_INFO _keyboard_driver_list[] ={ {KEYBOARD_MACOS, &keyboard_macos, TRUE}, {KEYBOARD_ADB, &keyboard_adb, TRUE}, {0, NULL, 0} }; _DRIVER_INFO _gfx_driver_list[] ={ {GFX_DRAWSPROCKET, &gfx_drawsprocket, TRUE}, {0, NULL, 0} }; _DRIVER_INFO _digi_driver_list[]={ {DIGI_MACOS,&digi_macos,TRUE}, {0,NULL,0} }; _DRIVER_INFO _midi_driver_list[]={ {MIDI_DIGMID,&midi_digmid,TRUE}, {MIDI_QUICKTIME,&midi_quicktime,TRUE}, {0,NULL,0} }; _DRIVER_INFO _joystick_driver_list[]={ {JOY_TYPE_NONE,&joystick_none,TRUE}, {0,NULL,0} }; allegro-4.4.3.1/src/mac/madb.c0000664000175000017500000004647413437077643014715 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mac ADB drivers. * * By Ronaldo H Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "macalleg.h" #include "allegro/platform/aintmac.h" #include extern volatile KeyMap KeyNow; extern volatile KeyMap KeyOld; #define ADB_LISTENMASK 8 #define ADB_TALKMASK 12 #define ADB_COMMANDMASK 12 #define ADB_TYPEREGISTER 3 #define ADB_KEYLEDREGISTER 2 #define ADB_KEYLEDMASK 7 #define ADB_MOUSE 3 #define ADB_KEYBOARD 2 #define ADB_ALLEGROTYPE 3 volatile int adb_command_done = 1; extern volatile short _interrupt_time; extern volatile short _mouse2nd; int adb_keyboard_id=0; ADBDataBlock adb_key_save; ADBServiceRoutineUPP adb_key_upp; ADBCompletionUPP adb_key_cpt_upp; static int key_adb_init(void); static void key_adb_exit(void); int adb_mouse_id=0; ADBDataBlock adb_mouse_save; ADBServiceRoutineUPP adb_mouse_upp; ADBCompletionUPP adb_mouse_cpt_upp; static int mouse_adb_init(void); static void mouse_adb_exit(void); static void mouse_adb_position(int x, int y); static void mouse_adb_set_range(int x1, int y1, int x2, int y2); static void mouse_adb_get_mickeys(int *mickeyx, int *mickeyy); static short mouse_x_min; static short mouse_y_min; static short mouse_x_max; static short mouse_y_max; static short mickey_x; static short mickey_y; KEYBOARD_DRIVER keyboard_adb ={ KEYBOARD_ADB, empty_string, empty_string, "Apple Desktop Bus keyboard", TRUE, key_adb_init, key_adb_exit, NULL, NULL, NULL, NULL, NULL, NULL }; MOUSE_DRIVER mouse_adb ={ MOUSE_ADB, empty_string, empty_string, "Apple Desktop Bus Mouse", mouse_adb_init, mouse_adb_exit, NULL, NULL, mouse_adb_position, mouse_adb_set_range, NULL, mouse_adb_get_mickeys, NULL, NULL }; #define k_apple_caps 0x3E #define k_apple_shift 0x3F #define k_apple_rshift 0x38 #define k_apple_alt 0x3D #define k_apple_altgr 0x3A #define k_apple_control 0x3C #define k_apple_rcontrol 0x39 #define k_apple_command 0x30 #define k_2nd k_apple_command #define kk_2nd 0x37 static const unsigned char adb_to_allegro[]={ /*00*/ KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_TILDE, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R, /*10*/ KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5, KEY_EQUALS, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_CLOSEBRACE, KEY_O, /*20*/ KEY_U, KEY_OPENBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_QUOTE, KEY_K, KEY_COLON, KEY_BACKSLASH, KEY_COMMA, KEY_BACKSLASH2, KEY_N, KEY_M, KEY_STOP, /*30*/ KEY_TAB, KEY_SPACE, KEY_SLASH, KEY_BACKSPACE, 0, KEY_ESC, KEY_LCONTROL, 0/*KEY_MENU*/, KEY_LSHIFT, KEY_CAPSLOCK, KEY_ALT, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0, /*10*/ 0, 0, 0, KEY_ASTERISK, 0, KEY_PLUS_PAD, 0, KEY_NUMLOCK, 0, 0, 0, KEY_SLASH_PAD, KEY_ENTER_PAD, 0, KEY_MINUS_PAD, 0, 0, KEY_DEL_PAD, KEY_0_PAD, KEY_1_PAD, KEY_2_PAD, KEY_3_PAD, KEY_4_PAD, KEY_5_PAD, KEY_6_PAD, KEY_7_PAD, 0, KEY_8_PAD, KEY_9_PAD, 0, 0, 0, KEY_F5, KEY_F6, KEY_F7, KEY_F3, KEY_F8, KEY_F9, 0, KEY_F11, 0, KEY_PRTSCR, 0, KEY_SCRLOCK, 0, KEY_F10, 0, KEY_F12, 0, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PGUP, KEY_DEL, KEY_F4, KEY_END, KEY_F2, KEY_PGDN, KEY_F1, KEY_RSHIFT, KEY_ALTGR, KEY_RCONTROL, 0, 0, }; #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG) #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG) #define KB_ACCENTS (KB_ACCENT1_FLAG | KB_ACCENT2_FLAG | KB_ACCENT3_FLAG | KB_ACCENT4_FLAG) #define KB_SH_CTRL_ALT (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG) #define KB_CTRL_ALT (KB_CTRL_FLAG | KB_ALT_FLAG) /* convert Allegro format scancodes into key_shifts flag bits */ static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = { KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG, KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG, KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG, KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG }; /* convert numeric pad scancodes into arrow codes */ static unsigned char numlock_table[10] = { KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT, KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP }; /* default mapping table for the US keyboard layout */ static unsigned short standard_key_ascii_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* capslock mapping table for the US keyboard layout */ static unsigned short standard_key_capslock_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* shifted mapping table for the US keyboard layout */ static unsigned short standard_key_shift_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* ctrl+key mapping table for the US keyboard layout */ static unsigned short standard_key_control_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ 2, 2, 2, 2, 2, 10, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * */ static pascal void adb_command_callback (Ptr buffer, Ptr refCon, long command) { #pragma unused buffer, command *refCon=1; } END_OF_STATIC_FUNCTION(adb_command_callback); /* * send a command to an ADB device */ static OSErr send_adb_command_sync (Ptr myBufferPtr,short adb_command) { OSErr e; adb_command_done = 0; e = ADBOp((Ptr)&adb_command_done, adb_key_cpt_upp, myBufferPtr, adb_command); if (e == noErr && !_interrupt_time) { while(!adb_command_done){}; } return e; }; /* * */ static pascal void key_adb_interrupt(Ptr buffer, TempADBServiceRoutineUPP completionProc, Ptr refCon, long command) { extern short _mac_keyboard_installed; unsigned char origcode; unsigned char keycode; int a; if((command & 0xF) == 0xC){ for(a = 1; a < 3 ; a++ ){ origcode=buffer[a]; keycode=adb_to_allegro[origcode&0x7f]; if(keycode!=0){ if(origcode&0x80){ if(keycode >= KEY_MODIFIERS && keycode= KEY_MODIFIERS && keycode restore system driver else if(origcode == 0x7F && _key_shifts & KB_SHIFT_FLAG && _key_shifts & KB_CTRL_FLAG){ ADBAddress adb_address; ADBSetInfoBlock mySet; ADBDataBlock now_data; adb_address = GetIndADB(&now_data, adb_keyboard_id); mySet.siService = adb_key_save.dbServiceRtPtr; mySet.siDataAreaAddr = adb_key_save.dbDataAreaAddr; SetADBInfo (&mySet,adb_address); _mac_keyboard_installed=TRUE; keyboard_driver = &keyboard_macos; } } } } END_OF_STATIC_FUNCTION(key_adb_interrupt); /* * */ static void key_adb_set_leds(int leds) { /* short adb_keyboard_id;*/ /* ADBDataBlock adb_key_save;*/ /* ADBAddress adb_address;*/ /* */ /* adb_leds = (leds & KB_NUMLOCK_FLAG)?0:1;*/ /* adb_leds += (leds & KB_CAPSLOCK_FLAG)?0:2;*/ /* adb_leds += (leds & KB_SCROLOCK_FLAG)?0:4;*/ /**/ /* for(adb_keyboard_id = 1; adb_keyboard_id <= adb_adb_keyboard_ids; adb_keyboard_id++){*/ /* adb_address = GetIndADB(&adb_key_save, adb_keyboard_id);*/ /* if(GetADBInfo(&adb_key_save, adb_address) == noErr){*/ /* if(adb_key_save.origADBAddr == 2 && adb_controls[adb_keyboard_id].type==EXTKEYBOARD){*/ /* adb_controls[adb_keyboard_id].adb_key_registers[0] = 2;*/ /* ADBOp(NULL, led_upp, adb_controls[adb_keyboard_id].adb_key_registers,*/ /* (adb_address << 4) + ADB_TALKMASK + ADB_KEYLEDREGISTER);*/ /* }*/ /* }*/ /* }*/ } /* * */ static int key_adb_init(void) { OSErr e; short adb_command; short adb_devices; char adb_key_registers[8]; ADBAddress adb_address; ADBSetInfoBlock mySet; adb_key_cpt_upp = NewADBCompletionUPP(adb_command_callback); adb_key_upp = NewADBServiceRoutineUPP (key_adb_interrupt); adb_devices = CountADBs(); for(adb_keyboard_id = 1 ; adb_keyboard_id <= adb_devices ; adb_keyboard_id++){ adb_address = GetIndADB(&adb_key_save, adb_keyboard_id); e = GetADBInfo(&adb_key_save, adb_address); if(adb_key_save.origADBAddr == ADB_KEYBOARD){ switch (adb_key_save.devType){ case 2:case 3:case 5: LOCK_VARIABLE(KeyNow); LOCK_VARIABLE(KeyOld); LOCK_VARIABLE(_mouse2nd); LOCK_VARIABLE(adb_to_allegro); LOCK_VARIABLE(modifier_table); LOCK_VARIABLE(standard_key_ascii_table); LOCK_VARIABLE(standard_key_capslock_table); LOCK_VARIABLE(standard_key_shift_table); LOCK_VARIABLE(standard_key_control_table); /* LOCK_FUNCTION(key_adb_interrupt);*/ /* LOCK_FUNCTION(adb_command_callback);*/ mySet.siService = adb_key_upp; mySet.siDataAreaAddr = NULL; SetADBInfo (&mySet,adb_address); adb_key_registers[0] = 2; adb_command = (adb_address * 16) + ADB_TALKMASK + ADB_TYPEREGISTER; if (send_adb_command_sync(adb_key_registers, adb_command) == noErr){ adb_key_registers[2] = 3; adb_command = (adb_address * 16) + ADB_LISTENMASK + ADB_TYPEREGISTER; send_adb_command_sync(adb_key_registers, adb_command); } GetKeys(KeyNow); _key_shifts=0; if(BitTst(KeyNow,k_apple_shift) || BitTst(KeyNow,k_apple_rshift))_key_shifts |= KB_SHIFT_FLAG; if(BitTst(KeyNow,k_apple_alt) || BitTst(KeyNow,k_apple_altgr))_key_shifts |= KB_ALT_FLAG; if(BitTst(KeyNow,k_apple_control) || BitTst(KeyNow,k_apple_rcontrol))_key_shifts |= KB_CTRL_FLAG; _mouse2nd = BitTst(KeyNow,k_2nd); return 0; default: break; } } } adb_keyboard_id=0; return -1; } /* * */ static void key_adb_exit(void) { OSErr e; short adb_command; short tmp; char adb_key_registers[8]; ADBAddress adb_address; ADBDataBlock now_data; ADBSetInfoBlock mySet; if(adb_keyboard_id!=0){ adb_address = GetIndADB(&now_data, adb_keyboard_id); e = GetADBInfo(&now_data, adb_address); if(now_data.origADBAddr == 2){ adb_key_registers[0] = 2; adb_command = (adb_address * 16) + ADB_TALKMASK + ADB_TYPEREGISTER; if (send_adb_command_sync(adb_key_registers, adb_command) == noErr){ tmp=adb_key_save.devType; if(tmp == 3 || tmp ==5) adb_key_registers[2] = tmp; else adb_key_registers[2] = 2; adb_command = (adb_address * 16) + ADB_LISTENMASK + ADB_TYPEREGISTER; send_adb_command_sync(adb_key_registers, adb_command); } } mySet.siService = adb_key_save.dbServiceRtPtr; mySet.siDataAreaAddr = adb_key_save.dbDataAreaAddr; SetADBInfo (&mySet,adb_address); adb_keyboard_id=0; } DisposeADBServiceRoutineUPP (adb_key_upp); DisposeADBCompletionUPP(adb_key_cpt_upp); } /* * */ static pascal void mouse_adb_interrupt(Ptr buffer, TempADBServiceRoutineUPP completionProc, Ptr refCon, long command) { signed char tmp; tmp=buffer[1]; _mouse_b = tmp&0x80?0:(_mouse2nd?2:1); if(tmp & 0x40) tmp |= 0xC0; else tmp &= 0x3F; _mouse_y += tmp; mickey_y += tmp; _mouse_y = CLAMP(mouse_y_min,mouse_y_max,_mouse_y); tmp=buffer[2]; _mouse_b |= tmp&0x80?0:2; if(tmp & 0x40) tmp |= 0xC0; else tmp &= 0x3F; _mouse_x += tmp; mickey_x += tmp; _mouse_x = CLAMP(mouse_x_min,mouse_x_max,_mouse_x); _handle_mouse_input(); } END_OF_STATIC_FUNCTION(mouse_adb_interrupt); /* mick_position: * Sets the position of the mickey-mode mouse. */ static void mouse_adb_position(int x, int y) { _mouse_x = x; _mouse_y = y; } /* * */ static void mouse_adb_set_range(int x1, int y1, int x2, int y2) { mouse_x_min = x1; mouse_y_min = y1; mouse_x_max = x2; mouse_y_max = y2; _mouse_x = CLAMP(mouse_x_min, _mouse_x, mouse_x_max); _mouse_y = CLAMP(mouse_x_min, _mouse_y, mouse_y_max); } /* * */ static void mouse_adb_get_mickeys(int *mickeyx, int *mickeyy) { int temp_x = mickey_x; int temp_y = mickey_y; mickey_x -= temp_x; mickey_y -= temp_y; *mickeyx = temp_x; *mickeyy = temp_y; } /* * */ static int mouse_adb_init(void) { OSErr e; ADBAddress adb_address; ADBSetInfoBlock mySet; short adb_devices; adb_mouse_cpt_upp = NewADBCompletionUPP(adb_command_callback); adb_mouse_upp = NewADBServiceRoutineUPP (mouse_adb_interrupt); adb_devices = CountADBs(); for(adb_mouse_id = 1 ; adb_mouse_id <= adb_devices ; adb_mouse_id++){ adb_address = GetIndADB(&adb_mouse_save, adb_mouse_id); e = GetADBInfo(&adb_mouse_save, adb_address); if(adb_mouse_save.origADBAddr == ADB_MOUSE){ switch (adb_mouse_save.devType){ case 1: LOCK_VARIABLE(mouse_x_min); LOCK_VARIABLE(mouse_y_min); LOCK_VARIABLE(mouse_x_max); LOCK_VARIABLE(mouse_y_max); LOCK_VARIABLE(mickey_x); LOCK_VARIABLE(mickey_y); LOCK_VARIABLE(_mouse2nd); mickey_x=0; mickey_y=0; mySet.siService = adb_mouse_upp; mySet.siDataAreaAddr = NULL; SetADBInfo (&mySet,adb_address); _mouse_x = 0; _mouse_y = 0; _mouse_b = 0; return 2; default: break; } } } adb_mouse_id=0; return -1; } /* * */ static void mouse_adb_exit(void) { ADBAddress adb_address; ADBDataBlock now_data; ADBSetInfoBlock mySet; if(adb_mouse_id != 0){ adb_address = GetIndADB(&now_data, adb_mouse_id); mySet.siService = adb_mouse_save.dbServiceRtPtr; mySet.siDataAreaAddr = adb_mouse_save.dbDataAreaAddr; SetADBInfo (&mySet,adb_address); adb_mouse_id = 0; } DisposeADBServiceRoutineUPP (adb_mouse_upp); DisposeADBCompletionUPP(adb_mouse_cpt_upp); } allegro-4.4.3.1/src/mac/msnd.c0000664000175000017500000015467413437077643014755 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mac sound support. * * By Ronaldo Hideki Yamada. * * from code of /src/mixer.c by Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/platform/aintmac.h" #ifndef ALLEGRO_MPW #error something is wrong with the makefile #endif static void pascal sound_mac_interrupt(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer); static int sound_mac_detect(int input); static int sound_mac_init(int input, int voices); static void sound_mac_exit(int input); static int sound_mac_set_mixer_volume(int volume); static int sound_mac_buffer_size(void); static char sb_desc[256] = EMPTY_STRING; static int sound_mac_in_use = 0; static int sound_mac_stereo = 0; static int sound_mac_16bit = 0; static int sound_mac_buf_size = 256; static int sound_mac_total_buf_size = 256; static int sound_mac_freq=44100; static long _mac_sound=0; static char sound_mac_desc[256] = EMPTY_STRING; static SndDoubleBackUPP myDBUPP=NULL; static SndChannelPtr chan=NULL; static SndDoubleBufferHeader myDblHeader; #define MAC_MSG_NONE 0 #define MAC_MSG_DONE 1 #define MAC_MSG_CLOSE 2 /* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sample mixing code. * * By Shawn Hargreaves. * * Proper 16 bit sample support added by SET. * * Ben Davis provided the voice_volume_scale functionality, programmed * the silent mixer so that silent voices don't freeze, and fixed a * few minor bugs elsewhere. * * See readme.txt for copyright information. */ #include #include "allegro/internal/aintern.h" struct MIXER_VOICE; typedef struct MIXER_VOICE { int playing; /* are we active? */ int stereo; /* mono or stereo input data? */ unsigned char *data8; /* data for 8 bit samples */ unsigned short *data16; /* data for 16 bit samples */ long pos; /* fixed point position in sample */ long diff; /* fixed point speed of play */ long len; /* fixed point sample length */ long loop_start; /* fixed point loop start position */ long loop_end; /* fixed point loop end position */ int lvol; /* left channel volume */ int rvol; /* right channel volume */ AL_METHOD(void, mix , (struct MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len)); } MIXER_VOICE; #define MIX_FIX_SHIFT 8 #define MIX_FIX_SCALE (1<vol>>13; pan = pv->pan>>13; /* no need to check for mix_stereo if we're using hq */ lvol = vol*(127-pan); rvol = vol*pan; /* adjust for 127*127<128*128-1 */ lvol += lvol>>6; rvol += rvol>>6; mv->lvol = MAX(0, lvol); mv->rvol = MAX(0, rvol); } END_OF_STATIC_FUNCTION(updatemixer_volume); /* update_mixer_freq: * Called whenever the voice frequency changes, to update the sample * delta value. */ static void updatemixer_freq(MIXER_VOICE *mv, PHYS_VOICE *pv) { mv->diff = (pv->freq >> (12 - MIX_FIX_SHIFT)) / sound_mac_freq; if (pv->playmode & PLAYMODE_BACKWARD) mv->diff = -mv->diff; } END_OF_STATIC_FUNCTION(updatemixer_freq); /* update_silent_mixer: * Another helper for updating the volume ramp and pitch/pan sweep status. * This version is designed for the silent mixer, and it is called just once * per buffer. The len parameter is used to work out how much the values * must be adjusted. */ static void update_silent_mixer(MIXER_VOICE *spl, PHYS_VOICE *voice, int len) { len >>= UPDATE_FREQ_SHIFT; if (voice->dpan) { /* update pan sweep */ voice->pan += voice->dpan * len; if (((voice->dpan > 0) && (voice->pan >= voice->target_pan)) || ((voice->dpan < 0) && (voice->pan <= voice->target_pan))) { voice->pan = voice->target_pan; voice->dpan = 0; } } /* update frequency sweep */ if (voice->dfreq) { voice->freq += voice->dfreq * len; if (((voice->dfreq > 0) && (voice->freq >= voice->target_freq)) || ((voice->dfreq < 0) && (voice->freq <= voice->target_freq))) { voice->freq = voice->target_freq; voice->dfreq = 0; } updatemixer_freq(spl, voice); } } END_OF_STATIC_FUNCTION(update_silent_mixer); #define BEGIN_MIXER() \ int register lvol = spl->lvol; \ int register rvol = spl->rvol; \ int register d; \ int register left; \ int register right; \ int register sublen; \ long register pos = spl->pos; \ long register diff = spl->diff; \ long register loop_end = spl->loop_end; \ long register loop_start = spl->loop_start #define END_MIXER() \ spl->pos = pos; \ spl->diff = diff; \ spl->loop_end = loop_end; \ spl->loop_start = loop_start; \ spl->lvol = lvol; \ spl->rvol = rvol #define BEGIN_8x1() \ unsigned char *data = spl->data8 #define BEGIN_8x2() \ unsigned short *data = (unsigned short *)spl->data8 #define BEGIN_16x1() \ unsigned short *data = spl->data16 #define BEGIN_16x2() \ unsigned long *data = (unsigned long *)spl->data16 #define MIX_8x1() \ d = data[pos>>MIX_FIX_SHIFT]-0x80; \ right = *(unsigned long *)buf; \ left = right & 0xFFFF0000; \ right += (d*rvol)>>8; \ left += (((d*lvol)<<8) & 0xFFFF0000); \ right &= 0xFFFF; \ right |= left; \ *(unsigned long *)buf = right; \ buf = buf + 2 #define MIX_8x2() \ d = data[pos>>MIX_FIX_SHIFT]; \ right = *(unsigned long *)buf; \ left = right >> 16 ; \ right &= 0xFFFF; \ left += (((d>>8)-0x80)*lvol)>>8; \ right += (((d&0xFF)-0x80)*rvol)>>8; \ right &= 0xFFFF; \ right += (left << 16); \ *(unsigned long *)buf = right; \ buf = buf + 2 #define MIX_16x1() \ d = data[pos >>MIX_FIX_SHIFT]-0x8000; \ right = *(unsigned long *)buf; \ left = right >> 16 ; \ right &= 0xFFFF; \ left += (d*lvol)>>16; \ right += (d*rvol)>>16; \ right &= 0xFFFF; \ right += (left << 16); \ *(unsigned long *)buf = right; \ buf = buf + 2 #define MIX_16x2() \ d = data[pos >>MIX_FIX_SHIFT]; \ right = *(unsigned long *)buf; \ left = right >> 16 ; \ right &= 0xFFFF; \ left += (((((unsigned)d)>>16)-0x8000)*lvol)>>16; \ right += (((d&0xFFFF)-0x8000)*rvol)>>16; \ right &= 0xFFFF; \ right += (left << 16); \ *(unsigned long *)buf = right; \ buf = buf + 2 #define UPDATE() \ { \ if ((voice->dvol) || (voice->dpan)) { \ /* update volume ramp */ \ if (voice->dvol) { \ voice->vol += voice->dvol; \ if (((voice->dvol > 0) && (voice->vol >= voice->target_vol)) || \ ((voice->dvol < 0) && (voice->vol <= voice->target_vol))) { \ voice->vol = voice->target_vol; \ voice->dvol = 0; \ } \ } \ /* update pan sweep */ \ if (voice->dpan) { \ voice->pan += voice->dpan; \ if (((voice->dpan > 0) && (voice->pan >= voice->target_pan)) || \ ((voice->dpan < 0) && (voice->pan <= voice->target_pan))) { \ voice->pan = voice->target_pan; \ voice->dpan = 0; \ } \ } \ /* updatemixer_volume(spl, voice);*/ \ d = voice->vol>>13; \ right = voice->pan>>13; \ lvol = d*(127-right); \ rvol = d*right; \ lvol += lvol>>6; \ rvol += rvol>>6; \ lvol = MAX(0, lvol); \ rvol = MAX(0, rvol); \ } \ /* update frequency sweep */ \ if (voice->dfreq) { \ voice->freq += voice->dfreq; \ if (((voice->dfreq > 0) && (voice->freq >= voice->target_freq)) || \ ((voice->dfreq < 0) && (voice->freq <= voice->target_freq))) { \ voice->freq = voice->target_freq; \ voice->dfreq = 0; \ } \ diff = (voice->freq >> (12 - MIX_FIX_SHIFT)) / sound_mac_freq; \ if (voice->playmode & PLAYMODE_BACKWARD) \ diff = -diff; \ } \ } #define MIXER_FORWARD() { \ len = len >> UPDATE_FREQ_SHIFT; \ do { \ sublen = UPDATE_FREQ; \ do { \ MIX(); \ pos += diff; \ if (pos >= loop_end) { \ spl->playing = FALSE; \ goto MIXER_END; \ } \ } while (--sublen) ; \ UPDATE(); \ } while (--len); \ MIXER_END:{}; \ } #define MIXER_BACKWARD() { \ len = len >> UPDATE_FREQ_SHIFT; \ do { \ sublen = UPDATE_FREQ; \ do { \ MIX(); \ pos += diff; \ if (pos < loop_start) { \ spl->playing = FALSE; \ goto MIXER_END; \ } \ } while (--sublen) ; \ UPDATE(); \ } while (--len); \ MIXER_END:{}; \ } #define MIXER_LOOP_FORWARD() { \ len = len >> UPDATE_FREQ_SHIFT; \ do { \ sublen = UPDATE_FREQ; \ do { \ MIX(); \ pos += diff; \ if (pos >= loop_end) { \ pos -= (loop_end - loop_start); \ } \ } while (--sublen) ; \ UPDATE(); \ } while (--len); \ } #define MIXER_LOOP_BACKWARD() { \ len = len >> UPDATE_FREQ_SHIFT; \ do { \ sublen = UPDATE_FREQ; \ do { \ MIX(); \ pos += diff; \ if (pos < loop_start) { \ pos += (loop_end - loop_start); \ } \ } while (--sublen) ; \ UPDATE(); \ } while (--len); \ } #define MIXER_BIDIR() { \ len = len >> UPDATE_FREQ_SHIFT; \ if (voice->playmode & PLAYMODE_BACKWARD){ \ do { \ sublen = UPDATE_FREQ; \ do { \ MIX(); \ pos += diff; \ if (pos < loop_start) { \ diff = -diff; \ /* however far the sample has overshot, move it the same */\ /* distance from the loop point, within the loop section */\ /* if sample is more short than buffer then this is a bug */\ pos = (loop_start << 1) - pos; \ voice->playmode ^= PLAYMODE_BACKWARD; \ } \ } while (--sublen) ; \ UPDATE(); \ } while (--len); \ } \ else{ \ do { \ sublen = UPDATE_FREQ; \ do { \ MIX(); \ pos += diff; \ if (pos >= loop_end) { \ diff = -diff; \ /* however far the sample has overshot, move it the same */\ /* distance from the loop point, within the loop section */\ /* if sample is more short than buffer then this is a bug */\ pos = ((loop_end - 1) << 1) - pos; \ voice->playmode ^= PLAYMODE_BACKWARD; \ } \ } while (--sublen) ; \ UPDATE(); \ } while (--len); \ } \ } static void mac_mixer_8x1_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x1(); #define MIX() MIX_8x1() MIXER_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x1_forward); static void mac_mixer_8x1_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x1(); #define MIX() MIX_8x1() MIXER_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x1_backward); static void mac_mixer_8x1_loop_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x1(); #define MIX() MIX_8x1() MIXER_LOOP_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x1_loop_forward); static void mac_mixer_8x1_loop_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x1(); #define MIX() MIX_8x1() MIXER_LOOP_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x1_loop_backward); static void mac_mixer_8x1_bidir(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x1(); #define MIX() MIX_8x1() MIXER_BIDIR(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x1_bidir); static void mac_mixer_8x2_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x2(); #define MIX() MIX_8x2() MIXER_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x2_forward); static void mac_mixer_8x2_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x2(); #define MIX() MIX_8x2() MIXER_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x2_backward); static void mac_mixer_8x2_loop_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x2(); #define MIX() MIX_8x2() MIXER_LOOP_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x2_loop_forward); static void mac_mixer_8x2_loop_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x2(); #define MIX() MIX_8x2() MIXER_LOOP_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x2_loop_backward); static void mac_mixer_8x2_bidir(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_8x2(); #define MIX() MIX_8x2() MIXER_BIDIR(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_8x2_bidir); static void mac_mixer_16x1_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x1(); #define MIX() MIX_16x1() MIXER_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x1_forward); static void mac_mixer_16x1_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x1(); #define MIX() MIX_16x1() MIXER_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x1_backward); static void mac_mixer_16x1_loop_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x1(); #define MIX() MIX_16x1() MIXER_LOOP_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x1_loop_forward); static void mac_mixer_16x1_loop_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x1(); #define MIX() MIX_16x1() MIXER_LOOP_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x1_loop_backward); static void mac_mixer_16x1_bidir(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x1(); #define MIX() MIX_16x1() MIXER_BIDIR(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x1_bidir); static void mac_mixer_16x2_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x2(); #define MIX() MIX_16x2() MIXER_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x2_forward); static void mac_mixer_16x2_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x2(); #define MIX() MIX_16x2() MIXER_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x2_backward); static void mac_mixer_16x2_loop_forward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x2(); #define MIX() MIX_16x2() MIXER_LOOP_FORWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x2_loop_forward); static void mac_mixer_16x2_loop_backward(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x2(); #define MIX() MIX_16x2() MIXER_LOOP_BACKWARD(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x2_loop_backward); static void mac_mixer_16x2_bidir(MIXER_VOICE *spl, PHYS_VOICE *voice, unsigned short *buf, int len) { BEGIN_MIXER(); BEGIN_16x2(); #define MIX() MIX_16x2() MIXER_BIDIR(); #undef MIX END_MIXER(); } END_OF_STATIC_FUNCTION(mac_mixer_16x2_bidir); /* helper for constructing the body of a sample mixing routine */ #define MIXER() \ { \ if ((voice->playmode & PLAYMODE_LOOP) && \ (spl->loop_start < spl->loop_end)) { \ \ if (voice->playmode & PLAYMODE_BACKWARD) { \ /* mix a backward looping sample */ \ while (len-- > 0) { \ MIX(); \ spl->pos += spl->diff; \ if (spl->pos < spl->loop_start) { \ if (voice->playmode & PLAYMODE_BIDIR) { \ spl->diff = -spl->diff; \ /* however far the sample has overshot, move it the same */\ /* distance from the loop point, within the loop section */\ spl->pos = (spl->loop_start << 1) - spl->pos; \ voice->playmode ^= PLAYMODE_BACKWARD; \ } \ else \ spl->pos += (spl->loop_end - spl->loop_start); \ } \ update_mixer(spl, voice, len); \ } \ } \ else { \ /* mix a forward looping sample */ \ while (len-- > 0) { \ MIX(); \ spl->pos += spl->diff; \ if (spl->pos >= spl->loop_end) { \ if (voice->playmode & PLAYMODE_BIDIR) { \ spl->diff = -spl->diff; \ /* however far the sample has overshot, move it the same */\ /* distance from the loop point, within the loop section */\ spl->pos = ((spl->loop_end - 1) << 1) - spl->pos; \ voice->playmode ^= PLAYMODE_BACKWARD; \ } \ else \ spl->pos -= (spl->loop_end - spl->loop_start); \ } \ update_mixer(spl, voice, len); \ } \ } \ } \ else { \ /* mix a non-looping sample */ \ while (len-- > 0) { \ MIX(); \ spl->pos += spl->diff; \ if ((unsigned long)spl->pos >= (unsigned long)spl->len) { \ /* note: we don't need a different version for reverse play, */ \ /* as this will wrap and automatically do the Right Thing */ \ spl->playing = FALSE; \ return; \ } \ update_mixer(spl, voice, len); \ } \ } \ } /* mix_silent_samples: * This is used when the voice is silent, instead of the other * mix_*_samples() functions. It just extrapolates the sample position, * and stops the sample if it reaches the end and isn't set to loop. * Since no mixing is necessary, this function is much faster than * its friends. In addition, no buffer parameter is required, * and the same function can be used for all sample types. * * There is a catch. All the mix_stereo_*_samples() and * mix_hq?_*_samples() functions (those which write to a stereo mixing * buffer) divide len by 2 before using it in the MIXER() macro. * Therefore, all the mix_silent_samples() for stereo buffers must divide * the len parameter by 2. This is done in mix_some_samples(). */ static void mix_silent_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, int len) { if ((voice->playmode & PLAYMODE_LOOP) && (spl->loop_start < spl->loop_end)) { if (voice->playmode & PLAYMODE_BACKWARD) { /* mix a backward looping sample */ spl->pos += spl->diff * len; if (spl->pos < spl->loop_start) { if (voice->playmode & PLAYMODE_BIDIR) { do { spl->diff = -spl->diff; spl->pos = (spl->loop_start << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; if (spl->pos < spl->loop_end) break; spl->diff = -spl->diff; spl->pos = ((spl->loop_end - 1) << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; } while (spl->pos < spl->loop_start); } else { do { spl->pos += (spl->loop_end - spl->loop_start); } while (spl->pos < spl->loop_start); } } update_silent_mixer(spl, voice, len); } else { /* mix a forward looping sample */ spl->pos += spl->diff * len; if (spl->pos >= spl->loop_end) { if (voice->playmode & PLAYMODE_BIDIR) { do { spl->diff = -spl->diff; spl->pos = ((spl->loop_end - 1) << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; if (spl->pos >= spl->loop_start) break; spl->diff = -spl->diff; spl->pos = (spl->loop_start << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; } while (spl->pos >= spl->loop_end); } else { do { spl->pos -= (spl->loop_end - spl->loop_start); } while (spl->pos >= spl->loop_end); } } update_silent_mixer(spl, voice, len); } } else { /* mix a non-looping sample */ spl->pos += spl->diff * len; if ((unsigned long)spl->pos >= (unsigned long)spl->len) { /* note: we don't need a different version for reverse play, */ /* as this will wrap and automatically do the Right Thing */ spl->playing = FALSE; return; } update_silent_mixer(spl, voice, len); } } END_OF_STATIC_FUNCTION(mix_silent_samples); static void sound_mac_update_mix(int voice){ int playmode=_phys_voice[voice].playmode; if (sound_mac_voice[voice].loop_start > sound_mac_voice[voice].loop_end) playmode &= ~( PLAYMODE_LOOP | PLAYMODE_BIDIR ); switch (playmode){ case PLAYMODE_PLAY: if (sound_mac_voice[voice].data8) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_8x2_forward; else sound_mac_voice[voice].mix = mac_mixer_8x1_forward; } else if(sound_mac_voice[voice].data16) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_16x2_forward; else sound_mac_voice[voice].mix = mac_mixer_16x1_forward; } else sound_mac_voice[voice].mix = 0 ; break; case PLAYMODE_LOOP: if (sound_mac_voice[voice].data8) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_8x2_loop_forward; else sound_mac_voice[voice].mix = mac_mixer_8x1_loop_forward; } else if(sound_mac_voice[voice].data16) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_16x2_loop_forward; else sound_mac_voice[voice].mix = mac_mixer_16x1_loop_forward; } else sound_mac_voice[voice].mix = 0 ; break; case PLAYMODE_PLAY+PLAYMODE_BACKWARD: if (sound_mac_voice[voice].data8) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_8x2_backward; else sound_mac_voice[voice].mix = mac_mixer_8x1_backward; } else if(sound_mac_voice[voice].data16) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_16x2_backward; else sound_mac_voice[voice].mix = mac_mixer_16x1_backward; } else sound_mac_voice[voice].mix = 0 ; break; case PLAYMODE_LOOP+PLAYMODE_BACKWARD: if (sound_mac_voice[voice].data8) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_8x2_loop_backward; else sound_mac_voice[voice].mix = mac_mixer_8x1_loop_backward; } else if(sound_mac_voice[voice].data16) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_16x2_loop_backward; else sound_mac_voice[voice].mix = mac_mixer_16x1_loop_backward; } else sound_mac_voice[voice].mix = 0 ; break; default: if (_phys_voice[voice].playmode & PLAYMODE_BIDIR){ if (sound_mac_voice[voice].data8) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_8x2_bidir; else sound_mac_voice[voice].mix = mac_mixer_8x1_bidir; } else if(sound_mac_voice[voice].data16) { if(sound_mac_voice[voice].stereo) sound_mac_voice[voice].mix = mac_mixer_16x2_bidir; else sound_mac_voice[voice].mix = mac_mixer_16x1_bidir; } } else sound_mac_voice[voice].mix = 0 ; break; } } /* sound_mac_init_voice: * Initialises the specificed voice ready for playing a sample. */ static void sound_mac_init_voice(int voice, AL_CONST SAMPLE *sample) { sound_mac_voice[voice].playing = FALSE; sound_mac_voice[voice].stereo = sample->stereo; sound_mac_voice[voice].pos = 0; sound_mac_voice[voice].len = sample->len << MIX_FIX_SHIFT; sound_mac_voice[voice].loop_start = sample->loop_start << MIX_FIX_SHIFT; sound_mac_voice[voice].loop_end = sample->loop_end << MIX_FIX_SHIFT; if (sample->bits == 8) { sound_mac_voice[voice].data8 = sample->data; sound_mac_voice[voice].data16 = NULL; } else { sound_mac_voice[voice].data8 = NULL; sound_mac_voice[voice].data16 = sample->data; } updatemixer_volume(sound_mac_voice+voice, _phys_voice+voice); updatemixer_freq(sound_mac_voice+voice, _phys_voice+voice); sound_mac_update_mix(voice); } END_OF_STATIC_FUNCTION(sound_mac_init_voice); /* sound_mac_release_voice: * Releases a voice when it is no longer required. */ static void sound_mac_release_voice(int voice) { sound_mac_voice[voice].playing = FALSE; sound_mac_voice[voice].data8 = NULL; sound_mac_voice[voice].data16 = NULL; } END_OF_STATIC_FUNCTION(sound_mac_release_voice); /* sound_mac_start_voice: * Activates a voice, with the currently selected parameters. */ static void sound_mac_start_voice(int voice) { if (sound_mac_voice[voice].pos >= sound_mac_voice[voice].len) sound_mac_voice[voice].pos = 0; sound_mac_voice[voice].playing = TRUE; } END_OF_STATIC_FUNCTION(sound_mac_start_voice); /* sound_mac_stop_voice: * Stops a voice from playing. */ static void sound_mac_stop_voice(int voice) { sound_mac_voice[voice].playing = FALSE; } END_OF_STATIC_FUNCTION(sound_mac_stop_voice); /* sound_mac_loop_voice: * Sets the loopmode for a voice. */ static void sound_mac_loop_voice(int voice, int loopmode) { sound_mac_update_mix(voice); updatemixer_freq(sound_mac_voice+voice, _phys_voice+voice); } END_OF_STATIC_FUNCTION(sound_mac_loop_voice); /* sound_mac_get_position: * Returns the current play position of a voice, or -1 if it has finished. */ static int sound_mac_get_position(int voice) { if ((!sound_mac_voice[voice].playing) || (sound_mac_voice[voice].pos >= sound_mac_voice[voice].len)) return -1; return (sound_mac_voice[voice].pos >> MIX_FIX_SHIFT); } END_OF_STATIC_FUNCTION(sound_mac_get_position); /* sound_mac_set_position: * Sets the current play position of a voice. */ static void sound_mac_set_position(int voice, int position) { sound_mac_voice[voice].pos = (position << MIX_FIX_SHIFT); if (sound_mac_voice[voice].pos >= sound_mac_voice[voice].len) sound_mac_voice[voice].playing = FALSE; } END_OF_STATIC_FUNCTION(sound_mac_set_position); /* sound_mac_get_volume: * Returns the current volume of a voice. */ static int sound_mac_get_volume(int voice) { return (_phys_voice[voice].vol >> 12); } END_OF_STATIC_FUNCTION(sound_mac_get_volume); /* sound_mac_set_volume: * Sets the volume of a voice. */ static void sound_mac_set_volume(int voice, int volume) { updatemixer_volume(sound_mac_voice+voice, _phys_voice+voice); } END_OF_STATIC_FUNCTION(sound_mac_set_volume); /* sound_mac_ramp_volume: * Starts a volume ramping operation. */ static void sound_mac_ramp_volume(int voice, int time, int endvol) { int d = (endvol << 12) - _phys_voice[voice].vol; time = MAX(time * (sound_mac_freq / UPDATE_FREQ) / 1000, 1); _phys_voice[voice].target_vol = endvol << 12; _phys_voice[voice].dvol = d / time; } END_OF_STATIC_FUNCTION(sound_mac_ramp_volume); /* sound_mac_stop_volume_ramp: * Ends a volume ramp operation. */ static void sound_mac_stop_volume_ramp(int voice) { _phys_voice[voice].dvol = 0; } END_OF_STATIC_FUNCTION(sound_mac_stop_volume_ramp); /* sound_mac_get_frequency: * Returns the current frequency of a voice. */ static int sound_mac_get_frequency(int voice) { return (_phys_voice[voice].freq >> 12); } END_OF_STATIC_FUNCTION(sound_mac_get_frequency); /* sound_mac_set_frequency: * Sets the frequency of a voice. */ static void sound_mac_set_frequency(int voice, int frequency) { updatemixer_freq(sound_mac_voice+voice, _phys_voice+voice); } END_OF_STATIC_FUNCTION(sound_mac_set_frequency); /* sound_mac_sweep_frequency: * Starts a frequency sweep. */ static void sound_mac_sweep_frequency(int voice, int time, int endfreq) { int d = (endfreq << 12) - _phys_voice[voice].freq; time = MAX(time * (sound_mac_freq / UPDATE_FREQ) / 1000, 1); _phys_voice[voice].target_freq = endfreq << 12; _phys_voice[voice].dfreq = d / time; } END_OF_STATIC_FUNCTION(sound_mac_sweep_frequency); /* sound_mac_stop_frequency_sweep: * Ends a frequency sweep. */ static void sound_mac_stop_frequency_sweep(int voice) { _phys_voice[voice].dfreq = 0; } END_OF_STATIC_FUNCTION(sound_mac_stop_frequency_sweep); /* sound_mac_get_pan: * Returns the current pan position of a voice. */ static int sound_mac_get_pan(int voice) { return (_phys_voice[voice].pan >> 12); } END_OF_STATIC_FUNCTION(sound_mac_get_pan); /* sound_mac_set_pan: * Sets the pan position of a voice. */ static void sound_mac_set_pan(int voice, int pan) { updatemixer_volume(sound_mac_voice+voice, _phys_voice+voice); } END_OF_STATIC_FUNCTION(sound_mac_set_pan); /* sound_mac_sweep_pan: * Starts a pan sweep. */ static void sound_mac_sweep_pan(int voice, int time, int endpan) { int d = (endpan << 12) - _phys_voice[voice].pan; time = MAX(time * (sound_mac_freq / UPDATE_FREQ) / 1000, 1); _phys_voice[voice].target_pan = endpan << 12; _phys_voice[voice].dpan = d / time; } END_OF_STATIC_FUNCTION(sound_mac_sweep_pan); /* sound_mac_stop_pan_sweep: * Ends a pan sweep. */ static void sound_mac_stop_pan_sweep(int voice) { _phys_voice[voice].dpan = 0; } END_OF_STATIC_FUNCTION(sound_mac_stop_pan_sweep); /* sound_mac_set_echo: * Sets the echo parameters for a voice. */ static void sound_mac_set_echo(int voice, int strength, int delay) { /* not implemented */ } END_OF_STATIC_FUNCTION(sound_mac_set_echo); /* sound_mac_set_tremolo: * Sets the tremolo parameters for a voice. */ static void sound_mac_set_tremolo(int voice, int rate, int depth) { /* not implemented */ } END_OF_STATIC_FUNCTION(sound_mac_set_tremolo); /* sound_mac_set_vibrato: * Sets the amount of vibrato for a voice. */ static void sound_mac_set_vibrato(int voice, int rate, int depth) { /* not implemented */ } END_OF_STATIC_FUNCTION(sound_mac_set_vibrato); DIGI_DRIVER digi_macos={ DIGI_MACOS, empty_string, empty_string, "Apple SoundManager", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, /* setup routines */ sound_mac_detect, sound_mac_init, sound_mac_exit, sound_mac_set_mixer_volume, NULL, /* for use by the audiostream functions */ NULL, NULL, sound_mac_buffer_size, /* voice control functions */ sound_mac_init_voice, sound_mac_release_voice, sound_mac_start_voice, sound_mac_stop_voice, sound_mac_loop_voice, /* position control functions */ sound_mac_get_position, sound_mac_set_position, /* volume control functions */ sound_mac_get_volume, sound_mac_set_volume, sound_mac_ramp_volume, sound_mac_stop_volume_ramp, /* pitch control functions */ sound_mac_get_frequency, sound_mac_set_frequency, sound_mac_sweep_frequency, sound_mac_stop_frequency_sweep, /* pan control functions */ sound_mac_get_pan, sound_mac_set_pan, sound_mac_sweep_pan, sound_mac_stop_pan_sweep, /* effect control functions */ sound_mac_set_echo, sound_mac_set_tremolo, sound_mac_set_vibrato, /* input functions */ 0,/*int rec_cap_bits;*/ 0,/*int rec_cap_stereo;*/ NULL,/*AL_METHOD(int,rec_cap_rate, (int bits, int stereo));*/ NULL,/*AL_METHOD(int,rec_cap_parm, (int rate, int bits, int stereo));*/ NULL,/*AL_METHOD(int,rec_source, (int source));*/ NULL,/*AL_METHOD(int,rec_start, (int rate, int bits, int stereo));*/ NULL,/*AL_METHOD(void, rec_stop, (void));*/ NULL,/*AL_METHOD(int,rec_read, (void *buf));*/ }; /* sound_mac_interrupt * */ static void pascal sound_mac_interrupt(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer) { if(doubleBuffer->dbUserInfo[0] == MAC_MSG_CLOSE){ doubleBuffer->dbNumFrames = 1; doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady; doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbLastBuffer; doubleBuffer->dbUserInfo[0] = MAC_MSG_DONE; } else{ int i; unsigned short *p = (unsigned short *)(&(doubleBuffer->dbSoundData[0])); BlockZero(p,sound_mac_total_buf_size); for (i=0; i 0) || (_phys_voice[i].dvol > 0)) { if (sound_mac_voice[i].mix) sound_mac_voice[i].mix(sound_mac_voice+i, _phys_voice+i, p, sound_mac_buf_size); } else mix_silent_samples(sound_mac_voice+i, _phys_voice+i, sound_mac_buf_size); } } doubleBuffer->dbNumFrames = sound_mac_buf_size; doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady; } } END_OF_STATIC_FUNCTION(sound_mac_interrupt); /* * sound_mac_detect: */ static int sound_mac_detect(int input){ #define _sound_has_stereo() (_mac_sound & (1<= 3){ my_err = Gestalt(gestaltSoundAttr, &_mac_sound); if(my_err == noErr){ if(_sound_has_double_buffer()){ sound_mac_stereo = 1/*_sound_has_stereo()?_sound_stereo:0*/;/*_sound_stereo*/ sound_mac_16bit = 1/*(_sound_bits == 16 && _sound_has_16bit())?1:0*/;/*_sound_bits*/ sound_mac_freq = (_sound_freq > 0)?_sound_freq:44100; my_err=SndNewChannel(&chan, sampledSynth, sound_mac_stereo?initStereo:initMono, NULL); if(chan && my_err==noErr){ /* theCommand.cmd = volumeCmd;*/ /* theCommand.param1 = 0;*/ /* theCommand.param2 = (long)(&sound_mac_freq);*/ /* my_err = SndDoImmediate(chan, &theCommand);*/ /* printf("Sound freq %d",sound_mac_freq);*/ /* sound_mac_freq = Fix2Long((Fixed)sound_mac_freq);*/ /* SndDisposeChannel(chan , true);*/ _sound_freq = sound_mac_freq; _sound_bits = sound_mac_16bit?16:8; _sound_stereo = sound_mac_stereo; sound_mac_buf_size = get_config_int(sound, uconvert_ascii("oss_fragsize", tmp1), 256); uszprintf(sound_mac_desc, sizeof(sound_mac_desc), get_config_text("Apple SoundManager %d.x %d hz, %d-bit, %s , %d "), myVersion.majorRev, sound_mac_freq, sound_mac_16bit ? 16 : 8, uconvert_ascii(sound_mac_stereo ? "stereo" : "mono", tmp1), sound_mac_buf_size); digi_driver->desc=sound_mac_desc; return 1; } } else{ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not do double buffered sound")); } } else{ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not get information about sound")); } } else{ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("SoundManager 3.0 or later required")); } } else{ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("SoundManager not found")); } } else{ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); } return 0; } /* sound_mac_init: * returns zero on success, -1 on failure. */ static int sound_mac_init(int input, int voices){ int i; OSErr my_err; SndDoubleBufferPtr myDblBuffer; chan = NULL; digi_driver->voices = voices; if(input) return -1; my_err=SndNewChannel(&chan, sampledSynth, sound_mac_stereo?initStereo:initMono, NULL); if(my_err == noErr){ sound_mac_voices = 1; while ((sound_mac_voices < MIXER_MAX_SFX) && (sound_mac_voices < voices)) { sound_mac_voices <<= 1; } voices = sound_mac_voices; for (i=0; idbNumFrames = 0; myDblBuffer->dbFlags = 0; myDblBuffer->dbUserInfo[0] =MAC_MSG_NONE; InvokeSndDoubleBackUPP (chan, myDblBuffer , myDBUPP); myDblHeader.dbhBufferPtr[i] = myDblBuffer; } } if(my_err==noErr) my_err = SndPlayDoubleBuffer(chan, &myDblHeader); if (my_err != noErr){ for( i = 0 ; i < 2 ; i++ ) if( myDblHeader.dbhBufferPtr[i] != NULL){ DisposePtr((Ptr) myDblHeader.dbhBufferPtr[i]); myDblHeader.dbhBufferPtr[i]=NULL; } if( myDBUPP != NULL ){ DisposeSndDoubleBackUPP (myDBUPP); myDBUPP=NULL; } if( chan!=NULL ){ SndDisposeChannel(chan , true); chan=NULL; } return -1; } } else return -1; sound_mac_set_mixer_volume(512); sound_mac_in_use = TRUE; sound_mac_lock_mem(); return 0; } /* sound_mac_exit: * */ static void sound_mac_exit(int input) { if(input)return; if( chan != NULL ){ SCStatus myStatus; OSErr my_err; int i; myDblHeader.dbhBufferPtr[0]->dbUserInfo[0] =MAC_MSG_CLOSE; myDblHeader.dbhBufferPtr[1]->dbUserInfo[0] =MAC_MSG_CLOSE; do my_err = SndChannelStatus(chan, sizeof(myStatus), &myStatus); while(myStatus.scChannelBusy); for( i = 0 ; i < 2 ; i++ ) if( myDblHeader.dbhBufferPtr[i] != NULL){ DisposePtr( (Ptr) myDblHeader.dbhBufferPtr[i]); myDblHeader.dbhBufferPtr[i]=NULL; } if( myDBUPP != NULL ){ DisposeSndDoubleBackUPP ( myDBUPP ); myDBUPP=NULL; } SndDisposeChannel(chan , true); chan=NULL; } sound_mac_in_use = FALSE; } /* * */ static int sound_mac_buffer_size(void) { return sound_mac_buf_size+(sound_mac_stereo?sound_mac_buf_size:0); } /* * */ static int sound_mac_set_mixer_volume(int volume) { SndCommand theCommand; OSErr e; if(chan){ theCommand.cmd = volumeCmd; theCommand.param1 = 0; theCommand.param2 = (long)(volume+(volume<<16)); e = SndDoImmediate(chan, &theCommand); } printf("smvol = %d",volume); return 0; } /* sound_mac_lock_mem: * Locks memory used by the functions in this file. */ static void sound_mac_lock_mem() { LOCK_VARIABLE(myDblHeader); LOCK_VARIABLE(sound_mac_voice); LOCK_VARIABLE(sound_mac_voices); LOCK_VARIABLE(sound_mac_freq); LOCK_VARIABLE(sound_mac_buf_size); LOCK_VARIABLE(sound_mac_total_buf_size); LOCK_FUNCTION(mix_silent_samples); LOCK_FUNCTION(updatemixer_volume); LOCK_FUNCTION(updatemixer_freq); LOCK_FUNCTION(update_silent_mixer); LOCK_FUNCTION(sound_mac_init_voice); LOCK_FUNCTION(sound_mac_release_voice); LOCK_FUNCTION(sound_mac_start_voice); LOCK_FUNCTION(sound_mac_stop_voice); LOCK_FUNCTION(sound_mac_loop_voice); LOCK_FUNCTION(sound_mac_get_position); LOCK_FUNCTION(sound_mac_set_position); LOCK_FUNCTION(sound_mac_get_volume); LOCK_FUNCTION(sound_mac_set_volume); LOCK_FUNCTION(sound_mac_ramp_volume); LOCK_FUNCTION(sound_mac_stop_volume_ramp); LOCK_FUNCTION(sound_mac_get_frequency); LOCK_FUNCTION(sound_mac_set_frequency); LOCK_FUNCTION(sound_mac_sweep_frequency); LOCK_FUNCTION(sound_mac_stop_frequency_sweep); LOCK_FUNCTION(sound_mac_get_pan); LOCK_FUNCTION(sound_mac_set_pan); LOCK_FUNCTION(sound_mac_sweep_pan); LOCK_FUNCTION(sound_mac_stop_pan_sweep); LOCK_FUNCTION(sound_mac_set_echo); LOCK_FUNCTION(sound_mac_set_tremolo); LOCK_FUNCTION(sound_mac_set_vibrato); LOCK_FUNCTION(mac_mixer_8x1_forward); LOCK_FUNCTION(mac_mixer_8x1_backward); LOCK_FUNCTION(mac_mixer_8x1_loop_forward); LOCK_FUNCTION(mac_mixer_8x1_loop_backward); LOCK_FUNCTION(mac_mixer_8x1_bidir); LOCK_FUNCTION(mac_mixer_8x2_forward); LOCK_FUNCTION(mac_mixer_8x2_backward); LOCK_FUNCTION(mac_mixer_8x2_loop_forward); LOCK_FUNCTION(mac_mixer_8x2_loop_backward); LOCK_FUNCTION(mac_mixer_8x2_bidir); LOCK_FUNCTION(mac_mixer_16x1_forward); LOCK_FUNCTION(mac_mixer_16x1_backward); LOCK_FUNCTION(mac_mixer_16x1_loop_forward); LOCK_FUNCTION(mac_mixer_16x1_loop_backward); LOCK_FUNCTION(mac_mixer_16x1_bidir); LOCK_FUNCTION(mac_mixer_16x2_forward); LOCK_FUNCTION(mac_mixer_16x2_backward); LOCK_FUNCTION(mac_mixer_16x2_loop_forward); LOCK_FUNCTION(mac_mixer_16x2_loop_backward); LOCK_FUNCTION(mac_mixer_16x2_bidir); LOCK_FUNCTION(sound_mac_interrupt); } allegro-4.4.3.1/src/mac/mlock.c0000664000175000017500000000435513437077643015107 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MacOs lock unlock functions. * * By Ronaldo H Yamada. * * See readme.txt for copyright information. */ #include #include #include struct lock_mem; typedef struct lock_mem lock_mem; struct lock_mem{ void * address; unsigned long size; int count; lock_mem * next; }; lock_mem * top=NULL; /* * */ static void mac_unlock_all() { lock_mem * temp; lock_mem * next; for(temp = top;temp != NULL;temp = next){ UnholdMemory(temp->address,temp->size); next = temp->next; DisposePtr((Ptr)temp); } } /* * */ void _mac_lock(void * address,unsigned long size) { static first=1; lock_mem * temp; if(first) atexit(mac_unlock_all); first=0; for(temp = top;temp != NULL;temp=temp->next){ if(address == temp->address){ if(size == temp->size){ temp->count++; } else{ UnholdMemory(temp->address,temp->size); HoldMemory(address,size); temp->address=address; temp->size=size; temp->count=1; } return; } } temp=(lock_mem *)NewPtr(sizeof(lock_mem)); if(temp){ temp->address=address; temp->size=size; temp->count=1; temp->next=top; top=temp; } HoldMemory(address,size); } /* * */ void _mac_unlock(void * address,unsigned long size) { lock_mem * temp; lock_mem * last; last=NULL; for(temp = top;temp != NULL;temp=temp->next){ if(address == temp->address){ temp->count--; if(temp <= 0){ if(last == NULL) top=temp->next; else last->next=temp->next; UnholdMemory(temp->address,temp->size); DisposePtr((Ptr)temp); } return; } else{ last = temp; } } } allegro-4.4.3.1/src/mac/mdraw.c0000664000175000017500000002100613437077643015104 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DrawSprocket graphics drivers. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "macalleg.h" #include "allegro/platform/aintmac.h" #include #define TRACE_MAC_GFX 0 /*Our main display device the display which contains the menubar on macs with more one display*/ GDHandle MainGDevice; /*Our main Color Table for indexed devices*/ CTabHandle MainCTable = NULL; /*Our current deph*/ short dspr_depth; /*Vsync has ocurred*/ volatile short _sync = 0; /*Vsync handler installed ?*/ short dspr_sync_installed = 0; /*the control state of dspr*/ short dspr_state = 0; /*Our dspr context*/ DSpContextReference dspr_context; /*??? Used for DrawSprocket e Vsync callback*/ const char refconst[16]; const RGBColor ForeDef={0,0,0}; const RGBColor BackDef={0xFFFF,0xFFFF,0xFFFF}; static char dspr_desc[256]=EMPTY_STRING; static BITMAP *dspr_init(int w, int h, int v_w, int v_h, int color_depth); static void dspr_exit(struct BITMAP *b); static void dspr_vsync(void); static void dspr_set_palette(const struct RGB *p, int from, int to, int retracesync); static short dspr_active(); static short dspr_pause(); static short dspr_inactive(); static CGrafPtr dspr_get_back(); static CGrafPtr dspr_get_front(); static void dspr_swap(); static Boolean dspr_vsync_interrupt(DSpContextReference inContext, void *inRefCon); #pragma mark GFX_DRIVER GFX_DRIVER gfx_drawsprocket ={ GFX_DRAWSPROCKET, empty_string, empty_string, "DrawSprocket", dspr_init, dspr_exit, NULL, dspr_vsync, dspr_set_palette, NULL, NULL, NULL, NULL, NULL, NULL, NULL, _mac_create_system_bitmap, _mac_destroy_system_bitmap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, 640, 480, TRUE, 0, 0, 0, 0, }; /* * init an gfx mode return an pointer to BITMAP on sucess, NULL fails */ #pragma mark gfx driver routines static BITMAP *dspr_init(int w, int h, int v_w, int v_h, int color_depth) { OSStatus e; CGrafPtr cg; BITMAP* b; DSpContextAttributes Attr; Fixed myfreq; int done; #if(TRACE_MAC_GFX) fprintf(stdout,"dspr_init(%d, %d, %d, %d, %d)\n", w, h, v_w, v_h, color_depth); fflush(stdout); #endif if ((v_w != w && v_w != 0) || (v_h != h && v_h != 0)) return (NULL); Attr.frequency = Long2Fix(_refresh_rate_request); Attr.reserved1 = 0; Attr.reserved2 = 0; Attr.colorNeeds = kDSpColorNeeds_Require; Attr.colorTable = MainCTable; Attr.contextOptions = 0; Attr.gameMustConfirmSwitch = false; Attr.reserved3[0] = 0; Attr.reserved3[1] = 0; Attr.reserved3[2] = 0; Attr.reserved3[3] = 0; Attr.pageCount = 1; Attr.displayWidth = w; Attr.displayHeight = h; Attr.displayBestDepth = color_depth; _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; _rgb_r_shift_16 = 10; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; switch(color_depth){ case 8: dspr_depth = 8; Attr.displayDepthMask = kDSpDepthMask_8; break; case 15: dspr_depth = 15; Attr.displayDepthMask = kDSpDepthMask_16; break; case 24: dspr_depth = 24; Attr.displayDepthMask = kDSpDepthMask_32; break; default: goto Error; } Attr.backBufferBestDepth = color_depth; Attr.backBufferDepthMask = Attr.displayDepthMask; e = DSpFindBestContext(&Attr, &dspr_context); if(e != noErr){ Attr.frequency = 0; e = DSpFindBestContext(&Attr, &dspr_context); } if(e != noErr) goto Error;/* I HATE "GOTO" */ Attr.displayWidth = w; Attr.displayHeight = h; Attr.contextOptions = 0; e = DSpContext_Reserve(dspr_context, &Attr); if(e != noErr) goto Error;/* I HATE "GOTO" */ dspr_state |= kRDDReserved; dspr_active(); e = DSpContext_SetVBLProc (dspr_context, dspr_vsync_interrupt,(void *)refconst); if(e == noErr){dspr_sync_installed = 1;} else{dspr_sync_installed = 0;} cg = dspr_get_front(); b =_CGrafPtr_to_system_bitmap(cg); if(b){ DSpContext_GetMonitorFrequency (dspr_context,&myfreq); _set_current_refresh_rate(Fix2Long(myfreq)); gfx_drawsprocket.w = w; gfx_drawsprocket.h = h; uszprintf(dspr_desc, sizeof(dspr_desc), get_config_text("DrawSprocket %d x %d, %dbpp, %dhz"), w, h, dspr_depth, _current_refresh_rate); gfx_drawsprocket.desc = dspr_desc; return b; } Error: #if(TRACE_MAC_GFX) fprintf(stdout,"dspr_init()failed\n"); fflush(stdout); #endif dspr_exit(b); return NULL; } /* * reservated */ static void dspr_exit(struct BITMAP *b) { #pragma unused b OSStatus e; #if(TRACE_MAC_GFX) fprintf(stdout,"dspr_exit()\n"); fflush(stdout); #endif if((dspr_state & kRDDReserved) != 0){ e = DSpContext_SetState(dspr_context, kDSpContextState_Inactive); e = DSpContext_Release(dspr_context); } dspr_state = 0; gfx_drawsprocket.w = 0; gfx_drawsprocket.h = 0; dspr_depth = 0; } /* * reservated */ static void dspr_vsync(void) { if(dspr_sync_installed){ _sync = 0; while(!_sync){} } } /* * reservated */ static void dspr_set_palette(const struct RGB *p, int from, int to, int retracesync) { int i;OSErr e; #if(TRACE_MAC_GFX) fprintf(stdout,"set_palette"); fflush(stdout); #endif if(MainCTable == NULL){ MainCTable = GetCTable(8); DetachResource((Handle) MainCTable); } for(i = from;i<= to;i ++){ (**MainCTable).ctTable[i].rgb.red = p[i].r*1040; (**MainCTable).ctTable[i].rgb.green = p[i].g*1040; (**MainCTable).ctTable[i].rgb.blue = p[i].b*1040; } if(retracesync)dspr_vsync(); if(dspr_depth == 8){ e = DSpContext_SetCLUTEntries(dspr_context, (**MainCTable).ctTable, from, to - from); } } /* * reservated */ static short dspr_active() { if(! (dspr_state & kRDDActive)){ if(! (dspr_state & kRDDPaused)) if(DSpContext_SetState(dspr_context , kDSpContextState_Active) != noErr) return 1; dspr_state &= (~kRDDPaused); dspr_state |= kRDDActive; } return 0; } /* * reservated */ static short dspr_pause() { if(! (dspr_state & kRDDPaused)){ if(DSpContext_SetState(dspr_context, kDSpContextState_Paused) != noErr)return 1; dspr_state &= (~kRDDActive); dspr_state |= kRDDPaused; DrawMenuBar(); } return 0; } /* * reservated */ static short dspr_inactive() { if(! (dspr_state & (kRDDPaused | kRDDActive))){ if(DSpContext_SetState(dspr_context, kDSpContextState_Inactive) != noErr)return 1; dspr_state &= (~kRDDPaused); dspr_state &= (~kRDDActive); DrawMenuBar(); } return 0; } /* * reservated */ static CGrafPtr dspr_get_back() { CGrafPtr theBuffer; DSpContext_GetBackBuffer(dspr_context, kDSpBufferKind_Normal, &theBuffer); return theBuffer; } /* * reservated */ static CGrafPtr dspr_get_front() { CGrafPtr theBuffer; DSpContext_GetFrontBuffer(dspr_context, &theBuffer); return theBuffer; } /* * reservated */ static void dspr_swap() { DSpContext_SwapBuffers(dspr_context, nil, nil); } /* * our vsync interrupt handle */ static Boolean dspr_vsync_interrupt (DSpContextReference inContext, void *inRefCon) { #pragma unused inContext, inRefCon _sync = 1; return false; } /* * drawsprocket initialization code should be called only one time */ int _dspr_sys_init() { OSErr e; MainGDevice = GetMainDevice(); if (MainGDevice == 0L) return -1; MainCTable = GetCTable(8); DetachResource((Handle) MainCTable); if ((Ptr) DSpStartup == (Ptr) kUnresolvedCFragSymbolAddress) return -2; e = DSpStartup(); if(e != noErr) return -3; dspr_state = 0; HideCursor(); return 0; } /* * drawsprocket exit code to should called only one time */ void _dspr_sys_exit() { DSpShutdown(); ShowCursor(); } allegro-4.4.3.1/src/mac/msys.c0000664000175000017500000003231213437077643014767 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mac system, timer and mouse drivers. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "macalleg.h" #include "allegro/platform/aintmac.h" #define TRACE_MAC_MOUSE 0 #define TRACE_MAC_SYSTEM 0 /*Our TimerManager task entry queue*/ static TMTask tm_entry; /*Our TM task is running*/ short tm_running = 0; long tm_delay = 0; short mac_timer_installed = FALSE; short mac_mouse_installed = FALSE; static int mouse_delay = 0; static int key_delay = 0; extern volatile short _mouse2nd; short _interrupt_time = FALSE; extern volatile KeyMap KeyNow; extern volatile KeyMap KeyOld; extern short _mac_keyboard_installed; extern void _key_mac_interrupt(void); /*Our window title ???*/ char macwindowtitle[256]; /*char buffer for Trace*/ char macsecuremsg[256]; static pascal void tm_interrupt(TMTaskPtr tmTaskPtr); static int mac_timer_init(void); static void mac_timer_exit(void); static int mouse_mac_init(void); static void mouse_mac_exit(void); static int mac_init(void); static void mac_exit(void); static void mac_get_executable_name(char *output, int size); static void mac_set_window_title(const char *name); static void mac_message(const char *msg); static void mac_assert(const char *msg); static BITMAP * mac_create_bitmap(int color_depth, int width, int height); static int mac_desktop_color_depth(void); static void mac_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); static void mac_yield_timeslice(void); static int mac_trace_handler(const char *msg); SYSTEM_DRIVER system_macos ={ SYSTEM_MACOS, /* id */ empty_string, /* name */ empty_string, /* desc */ "MacOs", /* ascii_name */ mac_init, mac_exit, mac_get_executable_name, NULL, /* find_resource */ mac_set_window_title, NULL, /* set_close_button_callback */ mac_message, mac_assert, NULL, /* save_console_state */ NULL, /* restore_console_state */ NULL, /* mac_create_bitmap, */ NULL, /* created_bitmap */ NULL, /* create_sub_bitmap */ NULL, /* created_sub_bitmap */ NULL, /* destroy_bitmap */ NULL, /* read_hardware_palette */ NULL, /* set_palette_range */ NULL, /* get_vtable */ NULL, /* set_display_switch_mode */ NULL, /* display_switch_lock */ mac_desktop_color_depth, NULL, /* get_desktop_resolution */ mac_get_gfx_safe_mode, mac_yield_timeslice, NULL, /* create_mutex */ NULL, /* destroy_mutex */ NULL, /* lock_mutex */ NULL, /* unlock_mutex */ NULL, /* gfx_drivers */ NULL, /* digi_drivers */ NULL, /* midi_drivers */ NULL, /* keyboard_drivers */ NULL, /* mouse_drivers */ NULL, /* joystick_drivers */ NULL /* timer_drivers */ }; MOUSE_DRIVER mouse_macos ={ MOUSE_MACOS, empty_string, empty_string, "MacOs Mouse", mouse_mac_init, mouse_mac_exit, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; TIMER_DRIVER timer_macos ={ TIMER_MACOS, empty_string, empty_string, "MacOs Timer", mac_timer_init, mac_timer_exit, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; /* * */ static int mac_init() { os_type = OSTYPE_MACOS; os_multitasking = TRUE; if (!_al_trace_handler) register_trace_handler(mac_trace_handler); #if (TRACE_MAC_SYSTEM) fprintf(stdout, "mac_init()::OK\n"); fflush(stdout); #endif _rgb_r_shift_15 = 10; /*Ours truecolor pixel format */ _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; return 0; } /* * */ static void mac_exit() { #if (TRACE_MAC_SYSTEM) fprintf(stdout, "mac_exit()\n"); fflush(stdout); #endif } /* * */ void _mac_get_executable_name(char *output, int size) { Str255 appName; OSErr e; ProcessInfoRec info; ProcessSerialNumber curPSN; e = GetCurrentProcess(&curPSN); info.processInfoLength = sizeof(ProcessInfoRec); info.processName = appName; info.processAppSpec = NULL; e = GetProcessInformation(&curPSN, &info); size = MIN(size, (unsigned char)appName[0]); _al_sane_strncpy(output, (char const *)appName+1, size); output[size] = 0; } /* * */ static void mac_get_executable_name(char *output, int size) { _mac_get_executable_name(output, size); } /* * */ static void mac_set_window_title(const char *name) { #if (TRACE_MAC_SYSTEM) fprintf(stdout, "mac_set_window_title(%s)\n", name); fflush(stdout); #endif memcpy(macwindowtitle, name, 254); macwindowtitle[254] = 0; } /* * */ void _mac_message(const char *msg) { #if (TRACE_MAC_SYSTEM) fprintf(stdout, "mac_message(%s)\n", msg); fflush(stdout); #endif memcpy(macsecuremsg, msg, 254); macsecuremsg[254] = 0; paramtext(macsecuremsg, "\0", "\0", "\0"); if(keyboard_driver) keyboard_driver->exit(); if(mouse_driver) mouse_driver->exit(); ShowCursor(); Alert(rmac_message, nil); HideCursor(); if(keyboard_driver) keyboard_driver->init(); if(mouse_driver) mouse_driver->init(); } /* * */ static void mac_message(const char *msg) { _mac_message(msg); } /* * */ static void mac_assert(const char *msg) { debugstr(msg); } /* create_bitmap_ex * Creates a new memory bitmap in the specified color_depth */ BITMAP *mac_create_bitmap(int color_depth, int width, int height) { GFX_VTABLE *vtable; BITMAP *bitmap; int i,width_bytes; vtable = _get_vtable(color_depth); if (!vtable) return NULL; bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * height)); if (!bitmap) return NULL; width_bytes=(width * BYTES_PER_PIXEL(color_depth) + (MEMORY_ALIGN - 1) ) & -MEMORY_ALIGN; bitmap->dat = _AL_MALLOC(width_bytes * height + MEMORY_ALIGN); if (!bitmap->dat) { _AL_FREE(bitmap); return NULL; } bitmap->w = bitmap->cr = width; bitmap->h = bitmap->cb = height; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->vtable = vtable; bitmap->write_bank = bitmap->read_bank = _stub_bank_switch; bitmap->id = 0; bitmap->extra = NULL; bitmap->x_ofs = 0; bitmap->y_ofs = 0; bitmap->seg = _default_ds(); bitmap->line[0] =( (long)bitmap->dat + (MEMORY_ALIGN - 1)) & -MEMORY_ALIGN; for (i=1; iline[i] = bitmap->line[i-1] + width_bytes; if (system_driver->created_bitmap) system_driver->created_bitmap(bitmap); return bitmap; } /* * */ static int mac_desktop_color_depth(void) { return 0; } /* mac_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void mac_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_DRAWSPROCKET; mode->width = 320; mode->height = 200; mode->bpp = 8; } /* * */ static void mac_yield_timeslice(void) { /* SystemTask();*/ } /* * */ static int mac_trace_handler(const char *msg) { debugstr(msg); return 0; } /* * */ static int mac_timer_init(void) { if (!tm_running) _tm_sys_init(); mac_timer_installed = 1; return 0; } /* * */ static void mac_timer_exit(void) { mac_timer_installed = 0; } /* * */ static int mouse_mac_init(void) { #if (TRACE_MAC_MOUSE) fprintf(stdout, "mouse_mac_init()\n"); fflush(stdout); #endif if (!tm_running) _tm_sys_init(); mac_mouse_installed = 1; return 2;/*emulated two button command-click*/ } /* * */ static void mouse_mac_exit(void) { #if (TRACE_MAC_MOUSE) fprintf(stdout, "mouse_mac_exit()\n"); fflush(stdout); #endif mac_mouse_installed = 0; } /* * */ static pascal void tm_interrupt(TMTaskPtr tmTaskPtr) { int m_b, t; t = tm_delay; if (mac_timer_installed){ t = _handle_timer_tick(t*TIMERS_PER_SECOND/1000)*1000/TIMERS_PER_SECOND; if (t < 5) t = 5; } if (mac_mouse_installed) { mouse_delay += t; if(mouse_delay > 50){ Point pt; mouse_delay=0; pt = (*((volatile Point *)0x082C)); m_b = (*((volatile UInt8 *)0x0172)) & 0x80 ? 0: _mouse2nd ? 2 : 1; if(_mouse_b != m_b || _mouse_x != pt.h || _mouse_y != pt.v ){ _mouse_b = m_b; _mouse_x = pt.h; _mouse_y = pt.v; _handle_mouse_input(); }; }; } if (_mac_keyboard_installed){ key_delay += t; if(key_delay > 50){ key_delay = 0; _key_mac_interrupt(); } } PrimeTime((QElemPtr)tmTaskPtr, t); tm_delay = t; } /* * */ int _tm_sys_init() { if (!tm_running) { LOCK_VARIABLE(tm_entry); LOCK_VARIABLE(tm_delay); LOCK_VARIABLE(mouse_delay); LOCK_VARIABLE(key_delay); tm_entry.tmAddr = NewTimerProc(tm_interrupt); tm_entry.tmWakeUp = 0; tm_entry.tmReserved = 0; InsXTime((QElemPtr)&tm_entry); tm_delay = 40; PrimeTime((QElemPtr)&tm_entry, tm_delay); tm_running = TRUE; } return 0; } /* * */ void _tm_sys_exit() { if (tm_running){ RmvTime((QElemPtr)&tm_entry); tm_running = FALSE; } } /*The our QuickDraw globals */ QDGlobals qd; /* * an strdup function to mac */ char *strdup(const char *p){ char *tmp=_AL_MALLOC(strlen(p)+1); if(tmp){ _al_sane_strncpy(tmp,p,strlen(p)+1); } return tmp; } /* * convert pascal strings to c strings */ void ptoc(StringPtr pstr,char *cstr) { BlockMove(pstr+1,cstr,pstr[0]); cstr[pstr[0]]='\0'; } /* * Simple function that returns TRUE if we're running on a Mac that * is running Color Quickdraw. */ static Boolean DoWeHaveColor (void) { SysEnvRec thisWorld; SysEnvirons(2, &thisWorld); // Call the old SysEnvirons() function. return (thisWorld.hasColorQD); // And return whether it has Color QuickDraw. } /* Another simple "environment" function.Returns TRUE if the Mac we're running * on has System 6.0.5 or more recent.(6.0.5 introduced the ability to switch * color depths.) */ static Boolean DoWeHaveSystem605 (void) { SysEnvRec thisWorld; Boolean haveIt; SysEnvirons(2, &thisWorld); // Call the old SysEnvirons() function. if (thisWorld.systemVersion >= 0x0605) haveIt = TRUE; // Check the System version for 6.0.5 else // or more recent haveIt = FALSE; return (haveIt); } /* * */ Boolean RTrapAvailable(short tNumber,TrapType tType) { return NGetTrapAddress( tNumber, tType ) != NGetTrapAddress( _Unimplemented, ToolTrap); } /* * Executs an cleanup before return to system called from atexit() */ static void mac_cleanup(){ _tm_sys_exit(); _dspr_sys_exit(); FlushEvents(nullEvent|mouseDown|mouseUp|keyDown|keyUp|autoKey|updateEvt,0); } /* * *The entry point for MacAllegro programs setup mac toolbox application memory *This routine should be called before main() this is do by -main MacEntry option in final Link *if not called then the program can crash!!! */ void MacEntry(){ char argbuf[512]; char *argv[64]; int argc; int i, q; /* ControlHandle ch;*/ SysEnvRec envRec;long heapSize; OSErr e; InitGraf((Ptr) &qd.thePort); /*init the normal mac toolbox*/ InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); InitPalettes(); /*memory setup*/ SysEnvirons( curSysEnvVers, &envRec ); if (envRec.machineType < 0 ) ExitToShell(); if (kStackNeeded > StackSpace()){ SetApplLimit((Ptr) ((long) GetApplLimit() - kStackNeeded + StackSpace())); } heapSize = (long) GetApplLimit() - (long) ApplicationZone(); if ( heapSize < kHeapNeeded){ _mac_message("no enough memory"); ExitToShell(); } MaxApplZone(); if(!(RTrapAvailable(_WaitNextEvent, ToolTrap)))ExitToShell(); GetDateTime((unsigned long*) &qd.randSeed); /* memcpy(macsecuremsg, "teste", 254);*/ /**/ /* paramtext(macsecuremsg, "\0", "\0", "\0");*/ /**/ /* Alert(rmac_command, nil);*/ /* */ /* e=GetDialogItemAsControl(ch);*/ /* */ /* printf("%d",e);*/ if(_dspr_sys_init()){ _mac_message("no could start drawsprocket"); return; } _mac_file_sys_init(); _mac_init_system_bitmap(); /*init our system bitmap vtable*/ atexit(&mac_cleanup); _mac_get_executable_name(argbuf,511);/*get command line*/ argc = 0; i = 0; /* parse commandline into argc/argv format */ while (argbuf[i]) { while ((argbuf[i]) && (uisspace(argbuf[i])))i++; if (argbuf[i]) { if ((argbuf[i] == '\'') || (argbuf[i] == '"')){ q = argbuf[i++]; if (!argbuf[i])break; } else q = 0; argv[argc++] = &argbuf[i]; while ((argbuf[i]) && ((q) ? (argbuf[i] != q) : (!uisspace(argbuf[i]))))i++; if (argbuf[i]) { argbuf[i] = 0; i++; } } } #if (TRACE_MAC_SYSTEM) fprintf(stdout,"MacEntry Done\n"); fflush(stdout); #endif main(argc, argv); FlushEvents(everyEvent,0); } allegro-4.4.3.1/src/mac/mfile.c0000664000175000017500000003522713437077643015100 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mac files support. * * By Ronaldo Hideki Yamada. * * See readme.txt for copyright information. */ #include "allegro.h" #include "macalleg.h" #include "allegro/platform/aintmac.h" #include #define TRACE_MAC_FILE 0 /*main volume name*/ char volname[32]="\0\0"; /*main volume number*/ short MainVol=0; /*main directory ID*/ long MainDir=0; Str255 mname="\0"; static short parent(short vRefNum, long dirID); static char *getfilename(const char *fullpath); static void getpath(char *filename, unsigned int filename_size); static long finddirect(void *pdta); void getcwd(char *p, int size); /* * */ static void getfullpath(short vRefNum,long dirID, char * fullname, unsigned int fullname_size) { CInfoPBRec myPB; Str255 dirName; char tmp1[1024]; char tmp2[1024]; OSErr myErr; dirName[0]=0; dirName[1]=0; dirName[2]=0; dirName[3]=0; _al_sane_strncpy(fullname,"",fullname_size); myPB.dirInfo.ioNamePtr = dirName; myPB.dirInfo.ioVRefNum = vRefNum; myPB.dirInfo.ioDrParID = dirID; myPB.dirInfo.ioFDirIndex = -1; myErr = PBGetCatInfoSync(&myPB); ptoc(dirName,tmp2); if(tmp2[0]){ _al_sane_strncpy(fullname,"/",fullname_size); strncat(fullname,tmp2,fullname_size-1); } while(myPB.dirInfo.ioDrDirID != fsRtDirID){ myPB.dirInfo.ioDrDirID = myPB.dirInfo.ioDrParID; myErr = PBGetCatInfoSync(&myPB); _al_sane_strncpy(tmp1,fullname,1024); ptoc(dirName,tmp2); _al_sane_strncpy(fullname,"/",fullname_size); strncat(fullname,tmp2,fullname_size-1); strncat(fullname,tmp1,fullname_size-1); } printf("%s\n",fullname); } /* * this routine get the parent id of dir or file by ours id */ static short parent(short vRefNum,long dirID) { FSSpec spec; FSMakeFSSpec(vRefNum,dirID,NULL,&spec); return spec.parID; } #pragma mark Find First /* *code modifyed from allegro/src/libc.c */ struct ff_match_data { int type; const char *s1; const char *s2; }; typedef struct ff_match_data ff_match_data; typedef ff_match_data *ffmatchdataPtr; #define FF_MATCH_TRY 0 #define FF_MATCH_ONE 1 #define FF_MATCH_ANY 2 /* ff_match: *Match two strings ('*' matches any number of characters, *'?' matches any character). */ static int ff_match(const char *s1, const char *s2) { static int size = 0; static ffmatchdataPtr data = 0; const char *s1end = s1 + strlen(s1); int index, c1, c2; /* allocate larger working area if necessary */ if ((data != 0) && (size < strlen(s2))){ _AL_FREE(data); data = 0; } if (data == 0){ size = strlen(s2); data = (ffmatchdataPtr)_AL_MALLOC(sizeof(ff_match_data)* size * 2 + 1); if (data == 0) return 0; } index = 0; data[0].s1 = s1; data[0].s2 = s2; data[0].type = FF_MATCH_TRY; while (index >= 0){ s1 = data[index].s1; s2 = data[index].s2; c1 = *s1; c2 = *s2; switch (data[index].type){ case FF_MATCH_TRY: if (c2 == 0){ /* pattern exhausted */ if (c1 == 0) return 1; else index--; } else if (c1 == 0){ /* string exhausted */ while (*s2 == '*') s2++; if (*s2 == 0) return 1; else index--; } else if (c2 == '*'){ /* try to match the rest of pattern with empty string */ data[index++].type = FF_MATCH_ANY; data[index].s1 = s1end; data[index].s2 = s2 + 1; data[index].type = FF_MATCH_TRY; } else if ((c2 == '?') || (c1 == c2)){ /* try to match the rest */ data[index++].type = FF_MATCH_ONE; data[index].s1 = s1 + 1; data[index].s2 = s2 + 1; data[index].type = FF_MATCH_TRY; } else index--; break; case FF_MATCH_ONE: /* the rest of string did not match, try earlier */ index--; break; case FF_MATCH_ANY: /* rest of string did not match, try add more chars to string tail */ if (--data[index + 1].s1 >= s1) { data[index + 1].type = FF_MATCH_TRY; index++; } else index--; break; default: /* this is a bird? This is a plane? No it's a bug!!! */ return 0; } } return 0; } /* * */ static char *getfilename(const char *fullpath) { char *p = (char*)fullpath + strlen(fullpath); while ((p > fullpath) && (*(p - 1) != '/')&&(*(p - 1) != '\\'))p--; return p; } /* * */ static void getpath(char *filename, unsigned int filename_size) { char *temp,*d,*s,*last; int div; temp=_AL_MALLOC(strlen(filename)+1); if(temp!=NULL){ d=temp; div=0; last=d; for(s=(char *)filename;*s;s++){ if(*s=='/'||*s=='\\'){ if(!div){ *d++='/'; last=d; div=1; } } else{ *d++=*s; div=0; } } *d=0; *last=0; _al_sane_strncpy(filename,temp,filename_size); _AL_FREE(temp); } } #define FF_MAXPATHLEN 1024 struct ffblk{ char dirname[FF_MAXPATHLEN]; char pattern[FF_MAXPATHLEN]; int dattr; long dirbase; long attrib; CInfoPBRec cpb; }; typedef struct ffblk ffblk; typedef ffblk *ffblkPtr; /* * */ static long finddirect(void *pdta){ ffblkPtr dta=(ffblkPtr)pdta; char *p,cname[256]; OSErr err=noErr; int done; short buffersize=strlen(dta->dirname); char *buffer=_AL_MALLOC(buffersize+1); if(!buffer)return 0; _al_sane_strncpy(buffer,dta->dirname,buffersize+1); dta->dirbase=MainDir; p=buffer; UppercaseStripDiacritics(buffer,buffersize,smSystemScript); if(p[0]=='/'){ dta->dirbase=fsRtDirID; p++; p=strtok(p,"\\/"); if(strcmp(p,volname)==0) p=strtok(NULL,"\\/"); } else p=strtok(p,"\\/"); while(p!=NULL&&err==noErr&&(*p!=0)){ if(strcmp(p,".")==0){} else if(strcmp(p,"..")==0) dta->dirbase=parent(dta->cpb.dirInfo.ioVRefNum,dta->dirbase); else if(strcmp(p,"...")==0) dta->dirbase=parent(dta->cpb.dirInfo.ioVRefNum,parent(dta->cpb.dirInfo.ioVRefNum,dta->dirbase)); else{ for(dta->cpb.dirInfo.ioFDirIndex=1, done=false; err == noErr && done != true; dta->cpb.dirInfo.ioFDirIndex++){ dta->cpb.dirInfo.ioDrDirID=dta->dirbase; dta->cpb.dirInfo.ioACUser = 0; if ((err = PBGetCatInfoSync(&dta->cpb)) == noErr){ if (dta->cpb.dirInfo.ioFlAttrib&ioDirMask){ ptoc(dta->cpb.dirInfo.ioNamePtr,cname); UppercaseStripDiacritics(cname,strlen(cname),smSystemScript); if(strcmp(p,cname)==0){ dta->dirbase=dta->cpb.dirInfo.ioDrDirID; done=true; } } } } } p=strtok(NULL,"\\/"); } dta->cpb.dirInfo.ioFDirIndex=1; _AL_FREE(buffer); if(err)dta->dirbase=0; return dta->dirbase; } /* * */ void _al_findclose(void *dta) { if(dta)_AL_FREE(dta); } /* * */ int _al_findnext(void *pdta, char *nameret, unsigned int nameret_size, int *aret) { ffblkPtr dta=(ffblkPtr)pdta; char cname[256]; OSErr err=noErr; int curattr; int list; #if (TRACE_MAC_FILE) fprintf(stdout,"_al_findnext()p=%s\n",dta->pattern); fflush(stdout); #endif if(aret)*aret=0; for(;err == noErr;dta->cpb.hFileInfo.ioFDirIndex++){ dta->cpb.hFileInfo.ioDirID = dta->dirbase; dta->cpb.hFileInfo.ioACUser = 0; if ((err = PBGetCatInfoSync(&dta->cpb)) == noErr){ ptoc(dta->cpb.hFileInfo.ioNamePtr,cname); UppercaseStripDiacritics(cname,strlen(cname),smSystemScript); list=true; curattr=(dta->cpb.dirInfo.ioFlAttrib & kioFlAttribDirMask)?FA_DIREC:0; curattr|=(dta->cpb.dirInfo.ioFlAttrib & (kioFlAttribLockedMask | kioFlAttribCopyProtMask)) ?FA_RDONLY:0; if(curattr & ~dta->dattr)list=false; if(list){ if(ff_match(cname, dta->pattern)){ if(nameret){ _al_sane_strncpy(nameret,dta->dirname,nameret_size); strncat(nameret,cname,nameret_size-1); } if(aret)*aret=curattr; err='OK'; } } } } if(err=='OK'){ return (*allegro_errno=errno=0); } return (*allegro_errno=errno=ENOENT); } /* * */ void * _al_findfirst(const char *pattern,int attrib, char *nameret, unsigned int nameret_size, int *aret) { ffblkPtr dta=(ffblkPtr)_AL_MALLOC(sizeof(ffblk)); #if (TRACE_MAC_FILE) fprintf(stdout,"_al_findfirst(%s, %d, .,.)\n",pattern,attrib); fflush(stdout); #endif if(volname[0]==0) _mac_file_sys_init(); if (dta){ dta->attrib = attrib; _al_sane_strncpy(dta->dirname, pattern,FF_MAXPATHLEN); getpath(dta->dirname,FF_MAXPATHLEN); _al_sane_strncpy(dta->pattern, getfilename(pattern),FF_MAXPATHLEN); if (dta->dirname[0] == 0)_al_sane_strncpy(dta->dirname, "./",FF_MAXPATHLEN); if (strcmp(dta->pattern, "*.*") == 0)_al_sane_strncpy(dta->pattern, "*",FF_MAXPATHLEN); UppercaseStripDiacritics(dta->pattern,strlen(dta->pattern),smSystemScript); dta->cpb.dirInfo.ioCompletion=NULL; dta->cpb.dirInfo.ioVRefNum=MainVol; dta->cpb.dirInfo.ioNamePtr=mname; #if (TRACE_MAC_FILE) fprintf(stdout,"directory name %s\n",dta->dirname); fflush(stdout); #endif if((finddirect(dta))!=0){ getfullpath(MainVol,dta->dirbase,dta->dirname,FF_MAXPATHLEN); strncat(dta->dirname,"/",FF_MAXPATHLEN-1); dta->dattr=attrib; if(attrib & FA_DIREC){ if(nameret){ _al_sane_strncpy(nameret,dta->dirname,nameret_size); strncat(nameret,"..",nameret_size-1); } if(aret) *aret=FA_DIREC; } else if ((_al_findnext(dta,nameret,nameret_size,aret))!=0){ #if (TRACE_MAC_FILE) fprintf(stdout,"_al_findfirst failed no files found\n"); fflush(stdout); #endif _al_findclose(dta); dta=NULL; } } else{ #if (TRACE_MAC_FILE) fprintf(stdout,"_al_findfirst failed direct not found\n"); fflush(stdout); #endif _al_findclose(dta); dta=NULL; } } #if (TRACE_MAC_FILE) else {fprintf(stdout,"_al_findfirst lowmem\n"); fflush(stdout);} #endif #if (TRACE_MAC_FILE) if(dta==NULL)fprintf(stdout,"_al_findfirst failed\n"); #endif if(dta!=NULL) *allegro_errno=0; return dta; } int _al_file_isok(const char *filename){ #if (TRACE_MAC_FILE) fprintf(stdout,"_al_file_isok(%s)\n",filename); fflush(stdout); #else #endif return true; } /* * */ int _al_file_exists(const char *filename, int attrib, int *aret){ void *dta; int x=false; dta=_al_findfirst(filename,attrib,NULL,0,aret); if(dta){ _al_findclose(dta); x=true; } #if (TRACE_MAC_FILE) fprintf(stdout,"fileexists(%s)=%d\n",filename,x); fflush(stdout); #endif return x; } /* * */ long _al_file_size(const char *filename){ void *dta; long fs; dta = _al_findfirst(filename,0/*FA_RDONLY | FA_HIDDEN | FA_ARCH*/,NULL,0,NULL); if (dta){ fs=((ffblkPtr)dta)->cpb.hFileInfo.ioFlLgLen; _al_findclose(dta); } else {fs=0;} #if (TRACE_MAC_FILE) fprintf(stdout,"filesize(%s)=%d\n",filename,fs); fflush(stdout); #endif return fs; } /* * */ time_t _al_file_time(const char *filename){ void *dta; time_t ft; dta = _al_findfirst(filename,0/*FA_RDONLY | FA_HIDDEN | FA_ARCH*/,NULL,0,NULL); if (dta){ ft=((ffblkPtr)dta)->cpb.hFileInfo.ioFlMdDat; _al_findclose(dta); } else {ft=0;} #if (TRACE_MAC_FILE) fprintf(stdout,"filetime(%s)=%d\n",filename,ft); fflush(stdout); #endif return ft; } /* * */ void _al_getdcwd(int drive, char *buf, int size){ char * fullname; fullname=_AL_MALLOC(1024); if(volname[0]==0) _mac_file_sys_init(); getfullpath(MainVol,MainDir,fullname,1024); #if (TRACE_MAC_FILE) fprintf(stdout,"_al_getdcwd(%d,%s,&d)\n",drive,fullname,size); fflush(stdout); #endif if(strlen(fullname)= 0) { c = ugetat(tmp, hline_pos); usetat(tmp, hline_pos, 0); hline_pos = text_length(font, tmp); c = usetc(tmp, c); usetc(tmp+c, 0); c = text_length(font, tmp); hline(bmp, x+hline_pos, y+text_height(font)-gui_font_baseline, x+hline_pos+c-1, color); } } return pix_len; } /* gui_strlen: * Returns the length of a string in pixels, ignoring '&' characters. */ int gui_strlen(AL_CONST char *s) { ASSERT(s); return gui_textout_ex(NULL, s, 0, 0, 0, 0, 0); } /* dotted_rect: * Draws a dotted rectangle, for showing an object has the input focus. */ static void dotted_rect(int x1, int y1, int x2, int y2, int fg, int bg) { BITMAP *gui_bmp = gui_get_screen(); int x = ((x1+y1) & 1) ? 1 : 0; int c; /* two loops to avoid bank switches */ for (c=x1; c<=x2; c++) putpixel(gui_bmp, c, y1, (((c+y1) & 1) == x) ? fg : bg); for (c=x1; c<=x2; c++) putpixel(gui_bmp, c, y2, (((c+y2) & 1) == x) ? fg : bg); for (c=y1+1; cproc; #endif if (msg == MSG_DRAW) { BITMAP *gui_bmp = gui_get_screen(); int w, h; /* Get width and height of target bitmap. We can't use SCREEN_W and * SCREEN_H because the target might not be the screen, but we cannot use * bmp->w and bmp->h either because if it is the screen these are actually * wrong. Ugh! */ w = (gui_bmp == screen) ? SCREEN_W: gui_bmp->w; h = (gui_bmp == screen) ? SCREEN_H: gui_bmp->h; set_clip_rect(gui_bmp, 0, 0, w-1, h-1); set_clip_state(gui_bmp, TRUE); clear_to_color(gui_bmp, d->bg); } return D_O_K; } /* d_box_proc: * Simple dialog procedure: just draws a box. */ int d_box_proc(int msg, DIALOG *d, int c) { ASSERT(d); if (msg==MSG_DRAW) { int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; BITMAP *gui_bmp = gui_get_screen(); rectfill(gui_bmp, d->x+1, d->y+1, d->x+d->w-2, d->y+d->h-2, d->bg); rect(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h-1, fg); } return D_O_K; } /* d_shadow_box_proc: * Simple dialog procedure: draws a box with a shadow. */ int d_shadow_box_proc(int msg, DIALOG *d, int c) { ASSERT(d); if (msg==MSG_DRAW) { int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; int black = makecol(0,0,0); BITMAP *gui_bmp = gui_get_screen(); rectfill(gui_bmp, d->x+1, d->y+1, d->x+d->w-3, d->y+d->h-3, d->bg); rect(gui_bmp, d->x, d->y, d->x+d->w-2, d->y+d->h-2, fg); vline(gui_bmp, d->x+d->w-1, d->y+1, d->y+d->h-1, black); hline(gui_bmp, d->x+1, d->y+d->h-1, d->x+d->w-1, black); } return D_O_K; } /* d_bitmap_proc: * Simple dialog procedure: draws the bitmap which is pointed to by dp. */ int d_bitmap_proc(int msg, DIALOG *d, int c) { BITMAP *b; ASSERT(d); b = (BITMAP *)d->dp; if (msg==MSG_DRAW) blit(b, gui_get_screen(), 0, 0, d->x, d->y, d->w, d->h); return D_O_K; } /* d_text_proc: * Simple dialog procedure: draws the text string which is pointed to by dp. */ int d_text_proc(int msg, DIALOG *d, int c) { ASSERT(d); if (msg==MSG_DRAW) { int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; FONT *oldfont = font; if (d->dp2) font = d->dp2; gui_textout_ex(gui_get_screen(), d->dp, d->x, d->y, fg, d->bg, FALSE); font = oldfont; } return D_O_K; } /* d_ctext_proc: * Simple dialog procedure: draws the text string which is pointed to by dp, * centering it around the object's x coordinate. */ int d_ctext_proc(int msg, DIALOG *d, int c) { ASSERT(d); if (msg==MSG_DRAW) { int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; FONT *oldfont = font; if (d->dp2) font = d->dp2; gui_textout_ex(gui_get_screen(), d->dp, d->x + d->w/2, d->y, fg, d->bg, TRUE); font = oldfont; } return D_O_K; } /* d_rtext_proc: * Simple dialog procedure: draws the text string which is pointed to by dp, * right aligning it. */ int d_rtext_proc(int msg, DIALOG *d, int c) { ASSERT(d); if (msg==MSG_DRAW) { int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; FONT *oldfont = font; if (d->dp2) font = d->dp2; gui_textout_ex(gui_get_screen(), d->dp, d->x + d->w - gui_strlen(d->dp), d->y, fg, d->bg, FALSE); font = oldfont; } return D_O_K; } /* d_button_proc: * A button object (the dp field points to the text string). This object * can be selected by clicking on it with the mouse or by pressing its * keyboard shortcut. If the D_EXIT flag is set, selecting it will close * the dialog, otherwise it will toggle on and off. */ int d_button_proc(int msg, DIALOG *d, int c) { BITMAP *gui_bmp; int state1, state2; int black; int swap; int g; ASSERT(d); gui_bmp = gui_get_screen(); switch (msg) { case MSG_DRAW: if (d->flags & D_SELECTED) { g = 1; state1 = d->bg; state2 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; } else { g = 0; state1 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; state2 = d->bg; } rectfill(gui_bmp, d->x+1+g, d->y+1+g, d->x+d->w-3+g, d->y+d->h-3+g, state2); rect(gui_bmp, d->x+g, d->y+g, d->x+d->w-2+g, d->y+d->h-2+g, state1); gui_textout_ex(gui_bmp, d->dp, d->x+d->w/2+g, d->y+d->h/2-text_height(font)/2+g, state1, -1, TRUE); if (d->flags & D_SELECTED) { vline(gui_bmp, d->x, d->y, d->y+d->h-2, d->bg); hline(gui_bmp, d->x, d->y, d->x+d->w-2, d->bg); } else { black = makecol(0,0,0); vline(gui_bmp, d->x+d->w-1, d->y+1, d->y+d->h-2, black); hline(gui_bmp, d->x+1, d->y+d->h-1, d->x+d->w-1, black); } if ((d->flags & D_GOTFOCUS) && (!(d->flags & D_SELECTED) || !(d->flags & D_EXIT))) dotted_rect(d->x+1+g, d->y+1+g, d->x+d->w-3+g, d->y+d->h-3+g, state1, state2); break; case MSG_WANTFOCUS: return D_WANTFOCUS; case MSG_KEY: /* close dialog? */ if (d->flags & D_EXIT) { return D_CLOSE; } /* or just toggle */ d->flags ^= D_SELECTED; object_message(d, MSG_DRAW, 0); break; case MSG_CLICK: /* what state was the button originally in? */ state1 = d->flags & D_SELECTED; if (d->flags & D_EXIT) swap = FALSE; else swap = state1; /* track the mouse until it is released */ while (gui_mouse_b()) { state2 = ((gui_mouse_x() >= d->x) && (gui_mouse_y() >= d->y) && (gui_mouse_x() < d->x + d->w) && (gui_mouse_y() < d->y + d->h)); if (swap) state2 = !state2; /* redraw? */ if (((state1) && (!state2)) || ((state2) && (!state1))) { d->flags ^= D_SELECTED; state1 = d->flags & D_SELECTED; object_message(d, MSG_DRAW, 0); } /* let other objects continue to animate */ broadcast_dialog_message(MSG_IDLE, 0); } /* should we close the dialog? */ if ((d->flags & D_SELECTED) && (d->flags & D_EXIT)) { d->flags ^= D_SELECTED; return D_CLOSE; } break; } return D_O_K; } /* d_check_proc: * Who needs C++ after all? This is derived from d_button_proc, * but overrides the drawing routine to provide a check box. */ int d_check_proc(int msg, DIALOG *d, int c) { BITMAP *gui_bmp = gui_get_screen(); int x, y, h; int fg, bg; ASSERT(d); if (msg==MSG_DRAW) { fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; bg = (d->bg < 0) ? gui_bg_color : d->bg; h = text_height(font); rectfill(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h-1, bg); if (d->flags & D_GOTFOCUS) dotted_rect(d->x, d->y, d->x+d->w-1, d->y+d->h-1, fg, bg); y = d->y + ((d->h-(h-gui_font_baseline))/2); x = d->x + ((d->d1) ? 0 : gui_textout_ex(gui_bmp, d->dp, d->x, y, fg, -1, FALSE) + h/2); rect(gui_bmp, x, y, x+h-1, y+h-1, fg); if (d->d1) gui_textout_ex(gui_bmp, d->dp, x+h+h/2, y, fg, -1, FALSE); if (d->flags & D_SELECTED) { line(gui_bmp, x, y, x+h-1, y+h-1, fg); line(gui_bmp, x, y+h-1, x+h-1, y, fg); } return D_O_K; } return d_button_proc(msg, d, 0); } /* d_radio_proc: * GUI procedure for radio buttons. * Parameters: d1-button group number; d2-button style (0=circle,1=square); * dp-text to appear as label to the right of the button. */ int d_radio_proc(int msg, DIALOG *d, int c) { BITMAP *gui_bmp = gui_get_screen(); int x, y, h, r, ret, fg, bg; int centerx, centery; ASSERT(d); switch(msg) { case MSG_DRAW: fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; bg = (d->bg < 0) ? gui_bg_color : d->bg; rectfill(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h-1, bg); if (d->flags & D_GOTFOCUS) dotted_rect(d->x, d->y, d->x+d->w-1, d->y+d->h-1, fg, bg); h = text_height(font); y = d->y+(d->h-(h-gui_font_baseline))/2; gui_textout_ex(gui_bmp, d->dp, d->x+h+h/2, y, fg, -1, FALSE); x = d->x; r = h/2; centerx = d->x+r; centery = d->y+d->h/2; switch (d->d2) { case 1: rect(gui_bmp, d->x, y, x+h-1, y+h-1, fg); if (d->flags & D_SELECTED) rectfill(gui_bmp, centerx-r/2, centery-r/2, centerx+r/2-1, centery+r/2-1, fg); break; default: circle(gui_bmp, centerx, centery, r, fg); if (d->flags & D_SELECTED) circlefill(gui_bmp, centerx, centery, r/2, fg); break; } return D_O_K; case MSG_KEY: case MSG_CLICK: if (d->flags & D_SELECTED) { return D_O_K; } break; case MSG_RADIO: if ((c == d->d1) && (d->flags & D_SELECTED)) { d->flags &= ~D_SELECTED; object_message(d, MSG_DRAW, 0); } break; } ret = d_button_proc(msg, d, 0); if (((msg==MSG_KEY) || (msg==MSG_CLICK)) && (d->flags & D_SELECTED) && (!(d->flags & D_EXIT))) { d->flags &= ~D_SELECTED; broadcast_dialog_message(MSG_RADIO, d->d1); d->flags |= D_SELECTED; } return ret; } /* d_icon_proc: * Allows graphic icons to be used as buttons. * * Parameters: * fg = color dotted line showing focus will be drawn in * bg = shadow color used to fill in top and left sides of * button when "pressed" * d1 = "push depth": number of pixels icon will be shifted * to right and down when selected (default=2) if there is * no "selected" image * d2 = distance dotted line showing focus is indented (default=2) * dp = pointer to a bitmap for the icon * dp2 = pointer to a "selected" bitmap for the icon (OPTIONAL) * dp3 = pointer to a "disabled" bitmap for the icon (OPTIONAL) */ int d_icon_proc(int msg, DIALOG *d, int c) { BITMAP *butimage; BITMAP *gui_bmp; int butx; int buty; int index; int indent; int depth; ASSERT(d); butimage = (BITMAP *)d->dp; gui_bmp = gui_get_screen(); if ((msg == MSG_DRAW) && (!(d->flags & D_HIDDEN))) { depth = 0; if ((d->dp2 == NULL) && (d->flags & D_SELECTED)) { depth = d->d1; if (depth<1) depth = 2; } if ((d->dp2 != NULL) && (d->flags & D_SELECTED)) { butimage = (BITMAP *)d->dp2; } if ((d->dp3 != NULL) && (d->flags & D_DISABLED)) { butimage = (BITMAP *)d->dp3; } indent = d->d2; if (indent==0) indent = 2; /* put the graphic on screen, scaled as needed */ butx = butimage->w; buty = butimage->h; stretch_blit(butimage, gui_bmp, 0, 0, butx-depth, buty-depth, d->x+depth, d->y+depth, d->w-depth, d->h-depth); if ((d->flags & D_GOTFOCUS) && (!(d->flags & D_SELECTED) || !(d->flags & D_EXIT))) { /* draw focus lines */ for (index=indent; indexw-(indent+1); index+=2) { putpixel(gui_bmp, d->x+index+depth, d->y+indent+depth,d->fg); putpixel(gui_bmp, d->x+index+depth, d->y+d->h-(indent+1)+depth, d->fg); } for (index=indent; indexh-(indent+1); index+=2) { putpixel(gui_bmp, d->x+indent+depth, d->y+index+depth, d->fg); putpixel(gui_bmp, d->x+d->w-(indent+1)+depth, d->y+index+depth, d->fg); } } /* draw shadowing */ for (index=0; indexx, d->y+index, d->x+d->w-1, d->bg); vline(gui_bmp, d->x+index, d->y, d->y+d->h-1, d->bg); } return D_O_K; } return d_button_proc(msg, d, c); } /* d_keyboard_proc: * Invisible object for implementing keyboard shortcuts. When its key * is pressed, it calls the function pointed to by dp. This should return * an integer, which will be passed back to the dialog manager. The key * can be specified by putting an ASCII code in the key field or by * putting scancodes in d1 and d2. */ int d_keyboard_proc(int msg, DIALOG *d, int c) { int (*proc)(void); int ret = D_O_K; ASSERT(d); switch (msg) { case MSG_START: d->w = d->h = 0; break; case MSG_XCHAR: if (((c>>8) != d->d1) && ((c>>8) != d->d2)) break; ret |= D_USED_CHAR; /* fall through */ case MSG_KEY: proc = d->dp; ret |= (*proc)(); break; } return ret; } /* d_edit_proc: * An editable text object (the dp field points to the string). When it * has the input focus (obtained by clicking on it with the mouse), text * can be typed into this object. The d1 field specifies the maximum * number of characters that it will accept, and d2 is the text cursor * position within the string. */ int d_edit_proc(int msg, DIALOG *d, int c) { static int ignore_next_uchar = FALSE; BITMAP *gui_bmp; int last_was_space, new_pos, i, k; int f, l, p, w, x, fg, b, scroll; char buf[16]; char *s, *t; ASSERT(d); gui_bmp = gui_get_screen(); s = d->dp; l = ustrlen(s); if (d->d2 > l) d->d2 = l; /* calculate maximal number of displayable characters */ if (d->d2 == l) { usetc(buf+usetc(buf, ' '), 0); x = text_length(font, buf); } else x = 0; b = 0; for (p=d->d2; p>=0; p--) { usetc(buf+usetc(buf, ugetat(s, p)), 0); x += text_length(font, buf); b++; if (x > d->w) break; } if (x <= d->w) { b = l; scroll = FALSE; } else { b--; scroll = TRUE; } switch (msg) { case MSG_START: d->d2 = l; break; case MSG_DRAW: fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; x = 0; if (scroll) { p = d->d2-b+1; b = d->d2; } else p = 0; for (; p<=b; p++) { f = ugetat(s, p); usetc(buf+usetc(buf, (f) ? f : ' '), 0); w = text_length(font, buf); if (x+w > d->w) break; f = ((p == d->d2) && (d->flags & D_GOTFOCUS)); textout_ex(gui_bmp, font, buf, d->x+x, d->y, (f) ? d->bg : fg, (f) ? fg : d->bg); x += w; } if (x < d->w) rectfill(gui_bmp, d->x+x, d->y, d->x+d->w-1, d->y+text_height(font)-1, d->bg); break; case MSG_CLICK: x = d->x; if (scroll) { p = d->d2-b+1; b = d->d2; } else p = 0; for (; p gui_mouse_x()) break; } d->d2 = CLAMP(0, p, l); object_message(d, MSG_DRAW, 0); break; case MSG_WANTFOCUS: case MSG_LOSTFOCUS: case MSG_KEY: return D_WANTFOCUS; case MSG_CHAR: ignore_next_uchar = FALSE; if ((c >> 8) == KEY_LEFT) { if (d->d2 > 0) { if (key_shifts & KB_CTRL_FLAG) { last_was_space = TRUE; new_pos = 0; t = s; for (i = 0; i < d->d2; i++) { k = ugetx(&t); if (uisspace(k)) last_was_space = TRUE; else if (last_was_space) { last_was_space = FALSE; new_pos = i; } } d->d2 = new_pos; } else d->d2--; } } else if ((c >> 8) == KEY_RIGHT) { if (d->d2 < l) { if (key_shifts & KB_CTRL_FLAG) { t = s + uoffset(s, d->d2); for (k = ugetx(&t); uisspace(k); k = ugetx(&t)) d->d2++; for (; k && !uisspace(k); k = ugetx(&t)) d->d2++; } else d->d2++; } } else if ((c >> 8) == KEY_HOME) { d->d2 = 0; } else if ((c >> 8) == KEY_END) { d->d2 = l; } else if ((c >> 8) == KEY_DEL) { if (d->d2 < l) uremove(s, d->d2); } else if ((c >> 8) == KEY_BACKSPACE) { if (d->d2 > 0) { d->d2--; uremove(s, d->d2); } } else if ((c >> 8) == KEY_ENTER) { if (d->flags & D_EXIT) { object_message(d, MSG_DRAW, 0); return D_CLOSE; } else return D_O_K; } else if ((c >> 8) == KEY_TAB) { ignore_next_uchar = TRUE; return D_O_K; } else { /* don't process regular keys here: MSG_UCHAR will do that */ break; } object_message(d, MSG_DRAW, 0); return D_USED_CHAR; case MSG_UCHAR: if ((c >= ' ') && (uisok(c)) && (!ignore_next_uchar)) { if (l < d->d1) { uinsert(s, d->d2, c); d->d2++; object_message(d, MSG_DRAW, 0); } return D_USED_CHAR; } break; } return D_O_K; } /* _handle_scrollable_click: * Helper to process a click on a scrollable object. */ void _handle_scrollable_scroll_click(DIALOG *d, int listsize, int *offset, int height) { int xx, yy; int hh = d->h - 5; while (gui_mouse_b()) { int i = (hh * height + listsize/2) / listsize; int len = (hh * (*offset) + listsize/2) / listsize + 2; if ((gui_mouse_y() >= d->y+len) && (gui_mouse_y() <= d->y+len+i)) { xx = gui_mouse_y() - len + 2; while (gui_mouse_b()) { yy = (listsize * (gui_mouse_y() - xx) + hh/2) / hh; if (yy > listsize-height) yy = listsize-height; if (yy < 0) yy = 0; if (yy != *offset) { *offset = yy; object_message(d, MSG_DRAW, 0); } /* let other objects continue to animate */ broadcast_dialog_message(MSG_IDLE, 0); } } else { if (gui_mouse_y() <= d->y+len) yy = *offset - height; else yy = *offset + height; if (yy > listsize-height) yy = listsize-height; if (yy < 0) yy = 0; if (yy != *offset) { *offset = yy; object_message(d, MSG_DRAW, 0); } } /* let other objects continue to animate */ broadcast_dialog_message(MSG_IDLE, 0); } } /* _handle_scrollable_scroll: * Helper function to scroll through a scrollable object. */ void _handle_scrollable_scroll(DIALOG *d, int listsize, int *index, int *offset) { int height = (d->h-4) / text_height(font); if (listsize <= 0) { *index = *offset = 0; return; } /* check selected item */ if (*index < 0) *index = 0; else if (*index >= listsize) *index = listsize - 1; /* check scroll position */ while ((*offset > 0) && (*offset + height > listsize)) (*offset)--; if (*offset >= *index) { if (*index < 0) *offset = 0; else *offset = *index; } else { while ((*offset + height - 1) < *index) (*offset)++; } } /* idle_cb: * rest_callback() routine to keep dialogs animating nice and smoothly. */ static void idle_cb(void) { broadcast_dialog_message(MSG_IDLE, 0); } /* _handle_listbox_click: * Helper to process a click on a listbox, doing hit-testing and moving * the selection. */ void _handle_listbox_click(DIALOG *d) { char *sel = d->dp2; int listsize, height; int i, j; (*(getfuncptr)d->dp)(-1, &listsize); if (!listsize) return; height = (d->h-4) / text_height(font); i = CLAMP(0, ((gui_mouse_y() - d->y - 2) / text_height(font)), ((d->h-4) / text_height(font) - 1)); i += d->d2; if (i < d->d2) i = d->d2; else { if (i > d->d2 + height-1) i = d->d2 + height-1; if (i >= listsize) i = listsize-1; } if (gui_mouse_y() <= d->y) i = MAX(i-1, 0); else if (gui_mouse_y() >= d->y+d->h-1) i = MIN(i+1, listsize-1); if (i != d->d1) { if (sel) { if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG)) { if ((key_shifts & KB_SHIFT_FLAG) || (d->flags & D_INTERNAL)) { for (j=MIN(i, d->d1); j<=MAX(i, d->d1); j++) sel[j] = TRUE; } else sel[i] = !sel[i]; } else sel[i] = TRUE; } d->d1 = i; i = d->d2; _handle_scrollable_scroll(d, listsize, &d->d1, &d->d2); d->flags |= D_DIRTY; if (i != d->d2) rest_callback(CLAMP(10, text_height(font)*16-d->h-1, 100), idle_cb); } else { if (!(d->flags & D_INTERNAL)) { if (sel) { if((key_shifts & KB_CTRL_FLAG)) sel[i] = !sel[i]; else sel[i] = TRUE; d->flags |= D_DIRTY; } } } } /* _draw_scrollable_frame: * Helper function to draw a frame for all objects with vertical scrollbars. */ void _draw_scrollable_frame(DIALOG *d, int listsize, int offset, int height, int fg_color, int bg) { BITMAP *gui_bmp = gui_get_screen(); int i, len; BITMAP *pattern; int xx, yy; /* draw frame */ rect(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h-1, fg_color); /* possibly draw scrollbar */ if (listsize > height) { vline(gui_bmp, d->x+d->w-13, d->y+1, d->y+d->h-2, fg_color); /* scrollbar with focus */ if (d->flags & D_GOTFOCUS) { dotted_rect(d->x+1, d->y+1, d->x+d->w-14, d->y+d->h-2, fg_color, bg); dotted_rect(d->x+d->w-12, d->y+1, d->x+d->w-2, d->y+d->h-2, fg_color, bg); } else { rect(gui_bmp, d->x+1, d->y+1, d->x+d->w-14, d->y+d->h-2, bg); rect(gui_bmp, d->x+d->w-12, d->y+1, d->x+d->w-2, d->y+d->h-2, bg); } /* create and draw the scrollbar */ pattern = create_bitmap(2, 2); i = ((d->h-5) * height + listsize/2) / listsize; xx = d->x+d->w-11; yy = d->y+2; putpixel(pattern, 0, 1, bg); putpixel(pattern, 1, 0, bg); putpixel(pattern, 0, 0, fg_color); putpixel(pattern, 1, 1, fg_color); if (offset > 0) { len = (((d->h-5) * offset) + listsize/2) / listsize; rectfill(gui_bmp, xx, yy, xx+8, yy+len, bg); yy += len; } if (yy+i < d->y+d->h-3) { drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0); rectfill(gui_bmp, xx, yy, xx+8, yy+i, 0); solid_mode(); yy += i+1; rectfill(gui_bmp, xx, yy, xx+8, d->y+d->h-3, bg); } else { drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0); rectfill(gui_bmp, xx, yy, xx+8, d->y+d->h-3, 0); solid_mode(); } destroy_bitmap(pattern); } else { /* no scrollbar necessary */ if (d->flags & D_GOTFOCUS) dotted_rect(d->x+1, d->y+1, d->x+d->w-2, d->y+d->h-2, fg_color, bg); else rect(gui_bmp, d->x+1, d->y+1, d->x+d->w-2, d->y+d->h-2, bg); } } /* draw_listbox: * Helper function to draw a listbox object. */ void _draw_listbox(DIALOG *d) { BITMAP *gui_bmp = gui_get_screen(); int height, listsize, i, len, bar, x, y, w; int fg_color, fg, bg; char *sel = d->dp2; char s[1024]; (*(getfuncptr)d->dp)(-1, &listsize); height = (d->h-4) / text_height(font); bar = (listsize > height); w = (bar ? d->w-15 : d->w-3); fg_color = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; /* draw box contents */ for (i=0; id2+i < listsize) { if (sel) { if ((sel[d->d2+i]) && (d->d2+i == d->d1)) { fg = d->bg; bg = fg_color; } else if (sel[d->d2+i]) { fg = d->bg; bg = gui_mg_color; } else { fg = fg_color; bg = d->bg; } } else if (d->d2+i == d->d1) { fg = d->bg; bg = fg_color; } else { fg = fg_color; bg = d->bg; } ustrzcpy(s, sizeof(s), (*(getfuncptr)d->dp)(i+d->d2, NULL)); x = d->x + 2; y = d->y + 2 + i*text_height(font); rectfill(gui_bmp, x, y, x+7, y+text_height(font)-1, bg); x += 8; len = ustrlen(s); while (text_length(font, s) >= MAX(d->w - 1 - (bar ? 22 : 10), 1)) { len--; usetat(s, len, 0); } textout_ex(gui_bmp, font, s, x, y, fg, bg); x += text_length(font, s); if (x <= d->x+w) rectfill(gui_bmp, x, y, d->x+w, y+text_height(font)-1, bg); if (d->d2+i == d->d1) dotted_rect(d->x+2, y, d->x+d->w-(bar ? 15 : 3), y+text_height(font)-1,d->fg, d->bg); } else { rectfill(gui_bmp, d->x+2, d->y+2+i*text_height(font), d->x+w, d->y+1+(i+1)*text_height(font), d->bg); } } if (d->y+2+i*text_height(font) <= d->y+d->h-3) rectfill(gui_bmp, d->x+2, d->y+2+i*text_height(font), d->x+w, d->y+d->h-3, d->bg); /* draw frame, maybe with scrollbar */ _draw_scrollable_frame(d, listsize, d->d2, height, fg_color, d->bg); } /* d_list_proc: * A list box object. The dp field points to a function which it will call * to obtain information about the list. This should follow the form: * const char * (int index, int *list_size); * If index is zero or positive, the function should return a pointer to * the string which is to be displayed at position index in the list. If * index is negative, it should return null and list_size should be set * to the number of items in the list. The list box object will allow the * user to scroll through the list and to select items list by clicking * on them, and if it has the input focus also by using the arrow keys. If * the D_EXIT flag is set, double clicking on a list item will cause it to * close the dialog. The index of the selected item is held in the d1 * field, and d2 is used to store how far it has scrolled through the list. */ int d_list_proc(int msg, DIALOG *d, int c) { int listsize, i, bottom, height, bar, orig; char *sel = d->dp2; int redraw = FALSE; ASSERT(d); switch (msg) { case MSG_START: (*(getfuncptr)d->dp)(-1, &listsize); _handle_scrollable_scroll(d, listsize, &d->d1, &d->d2); break; case MSG_DRAW: _draw_listbox(d); break; case MSG_CLICK: (*(getfuncptr)d->dp)(-1, &listsize); height = (d->h-4) / text_height(font); bar = (listsize > height); if ((!bar) || (gui_mouse_x() < d->x+d->w-13)) { if ((sel) && (!(key_shifts & KB_CTRL_FLAG))) { for (i=0; iflags |= D_INTERNAL; _handle_listbox_click(d); d->flags &= ~D_INTERNAL; } } else { _handle_scrollable_scroll_click(d, listsize, &d->d2, height); } break; case MSG_DCLICK: (*(getfuncptr)d->dp)(-1, &listsize); height = (d->h-4) / text_height(font); bar = (listsize > height); if ((!bar) || (gui_mouse_x() < d->x+d->w-13)) { if (d->flags & D_EXIT) { if (listsize) { i = d->d1; object_message(d, MSG_CLICK, 0); if (i == d->d1) return D_CLOSE; } } } break; case MSG_WHEEL: (*(getfuncptr)d->dp)(-1, &listsize); height = (d->h-4) / text_height(font); if (height < listsize) { int delta = (height > 3) ? 3 : 1; if (c > 0) i = MAX(0, d->d2-delta); else i = MIN(listsize-height, d->d2+delta); if (i != d->d2) { d->d2 = i; object_message(d, MSG_DRAW, 0); } } break; case MSG_KEY: (*(getfuncptr)d->dp)(-1, &listsize); if ((listsize) && (d->flags & D_EXIT)) return D_CLOSE; break; case MSG_WANTFOCUS: return D_WANTFOCUS; case MSG_CHAR: (*(getfuncptr)d->dp)(-1, &listsize); if (listsize) { c >>= 8; bottom = d->d2 + (d->h-4)/text_height(font) - 1; if (bottom >= listsize-1) bottom = listsize-1; orig = d->d1; if (c == KEY_UP) d->d1--; else if (c == KEY_DOWN) d->d1++; else if (c == KEY_HOME) d->d1 = 0; else if (c == KEY_END) d->d1 = listsize-1; else if (c == KEY_PGUP) { if (d->d1 > d->d2) d->d1 = d->d2; else d->d1 -= (bottom - d->d2) ? bottom - d->d2 : 1; } else if (c == KEY_PGDN) { if (d->d1 < bottom) d->d1 = bottom; else d->d1 += (bottom - d->d2) ? bottom - d->d2 : 1; } else return D_O_K; if (sel) { if (!(key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG))) { for (i=0; id1); i<=MAX(orig, d->d1); i++) { if (key_shifts & KB_CTRL_FLAG) sel[i] = (i != d->d1); else sel[i] = TRUE; } } } /* if we changed something, better redraw... */ _handle_scrollable_scroll(d, listsize, &d->d1, &d->d2); d->flags |= D_DIRTY; return D_USED_CHAR; } break; } return D_O_K; } /* d_text_list_proc: * Like d_list_proc, but allows the user to type in the first few characters * of a listbox entry in order to select it. Uses dp3 internally, so you * mustn't store anything important there yourself. */ int d_text_list_proc(int msg, DIALOG *d, int c) { int listsize, i, a, failure; char *selected, *thisitem; char *sel = d->dp2; ASSERT(d); switch (msg) { case MSG_START: case MSG_CLICK: case MSG_DCLICK: case MSG_WANTFOCUS: case MSG_LOSTFOCUS: d->dp3 = 0; break; case MSG_CHAR: if ((c & 0xFF) < ' ') d->dp3 = 0; break; case MSG_UCHAR: (*(getfuncptr)d->dp)(-1, &listsize); if (listsize) { if (c >= ' ') { selected = (*(getfuncptr)d->dp)(d->d1, NULL); i = d->d1; do { thisitem = (*(getfuncptr)d->dp)(i, NULL); failure = FALSE; if ((int)((unsigned long)d->dp3) < ustrlen(thisitem)) { for (a=0; a < (int)((unsigned long)d->dp3); a++) { if (utolower(ugetat(thisitem, a)) != utolower(ugetat(selected, a))) { failure = TRUE; break; } } if ((!failure) && (utolower(ugetat(thisitem, (int)(unsigned long)d->dp3)) == utolower(c))) { d->d1 = i; d->dp3 = (void *)((unsigned long)d->dp3 + 1); if (sel) { for (i=0; id1, &d->d2); object_message(d, MSG_DRAW, 0); return D_USED_CHAR; } } i++; if (i >= listsize) i = 0; } while (i != d->d1); if (d->dp3) { d->dp3 = 0; return d_text_list_proc(msg, d, c); } } } break; } return d_list_proc(msg, d, c); } /* _draw_textbox: * Helper function to draw a textbox object. */ void _draw_textbox(char *thetext, int *listsize, int draw, int offset, int wword, int tabsize, int x, int y, int w, int h, int disabled, int fore, int deselect, int disable) { BITMAP *gui_bmp = gui_get_screen(); int fg = fore; int y1 = y+4; int x1; int len; int ww = w-6; char s[16]; char text[16]; char space[16]; char *printed = text; char *scanned = text; char *oldscan = text; char *ignore = NULL; char *tmp, *ptmp; int width; int line = 0; int i = 0; int noignore; usetc(s+usetc(s, '.'), 0); usetc(text+usetc(text, ' '), 0); usetc(space+usetc(space, ' '), 0); /* find the correct text */ if (thetext != NULL) { printed = thetext; scanned = thetext; } /* do some drawing setup */ if (draw) { /* initial start blanking at the top */ rectfill(gui_bmp, x+2, y+2, x+w-3, y1-1, deselect); } /* choose the text color */ if (disabled) fg = disable; /* loop over the entire string */ while (1) { width = 0; /* find the next break */ while (ugetc(scanned)) { /* check for a forced break */ if (ugetc(scanned) == '\n') { scanned += uwidth(scanned); /* we are done parsing the line end */ break; } /* the next character length */ usetc(s+usetc(s, ugetc(scanned)), 0); len = text_length(font, s); /* modify length if its a tab */ if (ugetc(s) == '\t') len = tabsize * text_length(font, space); /* check for the end of a line by excess width of next char */ if (width+len >= ww) { /* we have reached end of line do we go back to find start */ if (wword) { /* remember where we were */ oldscan = scanned; noignore = FALSE; /* go backwards looking for start of word */ while (!uisspace(ugetc(scanned))) { /* don't wrap too far */ if (scanned == printed) { /* the whole line is filled, so stop here */ tmp = ptmp = scanned; while (ptmp != oldscan) { ptmp = tmp; tmp += uwidth(tmp); } scanned = ptmp; noignore = TRUE; break; } /* look further backwards to wrap */ tmp = ptmp = printed; while (tmp < scanned) { ptmp = tmp; tmp += uwidth(tmp); } scanned = ptmp; } /* put the space at the end of the line */ if (!noignore) { ignore = scanned; scanned += uwidth(scanned); } else ignore = NULL; /* check for endline at the convenient place */ if (ugetc(scanned) == '\n') scanned += uwidth(scanned); } /* we are done parsing the line end */ break; } /* the character can be added */ scanned += uwidth(scanned); width += len; } /* check if we are to print it */ if ((draw) && (line >= offset) && (y1+text_height(font) < (y+h-3))) { x1 = x+4; /* the initial blank bit */ rectfill(gui_bmp, x+2, y1, x1-1, y1+text_height(font), deselect); /* print up to the marked character */ while (printed != scanned) { /* do special stuff for each charater */ switch (ugetc(printed)) { case '\r': case '\n': /* don't print endlines in the text */ break; /* possibly expand the tabs */ case '\t': for (i=0; iflags & D_DISABLED) ? gui_mg_color : d->fg; /* calculate the actual height */ height = (d->h-8) / text_height(font); switch (msg) { case MSG_START: /* measure how many lines of text we contain */ _draw_textbox(d->dp, &d->d1, 0, /* DONT DRAW anything */ d->d2, !(d->flags & D_SELECTED), 8, d->x, d->y, d->w, d->h, (d->flags & D_DISABLED), 0, 0, 0); break; case MSG_DRAW: /* tell the object to sort of draw, but only calculate the listsize */ _draw_textbox(d->dp, &d->d1, 0, /* DONT DRAW anything */ d->d2, !(d->flags & D_SELECTED), 8, d->x, d->y, d->w, d->h, (d->flags & D_DISABLED), 0, 0, 0); if (d->d1 > height) { bar = 12; } else { bar = 0; d->d2 = 0; } /* now do the actual drawing */ _draw_textbox(d->dp, &d->d1, 1, d->d2, !(d->flags & D_SELECTED), 8, d->x, d->y, d->w-bar, d->h, (d->flags & D_DISABLED), fg_color, d->bg, gui_mg_color); /* draw the frame around */ _draw_scrollable_frame(d, d->d1, d->d2, height, fg_color, d->bg); break; case MSG_CLICK: /* figure out if it's on the text or the scrollbar */ bar = (d->d1 > height); if ((!bar) || (gui_mouse_x() < d->x+d->w-13)) { /* clicked on the text area */ ret = D_O_K; } else { /* clicked on the scroll area */ _handle_scrollable_scroll_click(d, d->d1, &d->d2, height); } break; case MSG_CHAR: start = d->d2; used = D_USED_CHAR; if (d->d1 > 0) { if (d->d2 > 0) top = d->d2+1; else top = 0; l = (d->h-8)/text_height(font); bottom = d->d2 + l - 1; if (bottom >= d->d1-1) bottom = d->d1-1; else bottom--; if ((c>>8) == KEY_UP) d->d2--; else if ((c>>8) == KEY_DOWN) d->d2++; else if ((c>>8) == KEY_HOME) d->d2 = 0; else if ((c>>8) == KEY_END) d->d2 = d->d1-l; else if ((c>>8) == KEY_PGUP) d->d2 -= (bottom-top) ? bottom-top : 1; else if ((c>>8) == KEY_PGDN) d->d2 += (bottom-top) ? bottom-top : 1; else used = D_O_K; /* make sure that the list stays in bounds */ if (d->d2 > d->d1-l) d->d2 = d->d1-l; if (d->d2 < 0) d->d2 = 0; } else used = D_O_K; /* if we changed something, better redraw... */ if (d->d2 != start) d->flags |= D_DIRTY; ret = used; break; case MSG_WHEEL: l = (d->h-8)/text_height(font); delta = (l > 3) ? 3 : 1; /* scroll, making sure that the list stays in bounds */ start = d->d2; d->d2 = (c > 0) ? MAX(0, d->d2-delta) : MIN(d->d1-l, d->d2+delta); /* if we changed something, better redraw... */ if (d->d2 != start) d->flags |= D_DIRTY; ret = D_O_K; break; case MSG_WANTFOCUS: /* if we don't have a scrollbar we can't do anything with the focus */ if (d->d1 > height) ret = D_WANTFOCUS; break; default: ret = D_O_K; } return ret; } /* d_slider_proc: * A slider control object. This object returns a value in d2, in the * range from 0 to d1. It will display as a vertical slider if h is * greater than or equal to w; otherwise, it will display as a horizontal * slider. dp can contain an optional bitmap to use for the slider handle; * dp2 can contain an optional callback function, which is called each * time d2 changes. The callback function should have the following * prototype: * * int function(void *dp3, int d2); * * The d_slider_proc object will return the value of the callback function. */ int d_slider_proc(int msg, DIALOG *d, int c) { BITMAP *gui_bmp = gui_get_screen(); BITMAP *slhan = NULL; int oldpos, newpos; int sfg; /* slider foreground color */ int vert = TRUE; /* flag: is slider vertical? */ int hh = 7; /* handle height (width for horizontal sliders) */ int hmar; /* handle margin */ int slp; /* slider position */ int mp; /* mouse position */ int irange; int slx, sly, slh, slw; int msx, msy; int retval = D_O_K; int upkey, downkey; int pgupkey, pgdnkey; int homekey, endkey; int delta; fixed slratio, slmax, slpos; int (*proc)(void *cbpointer, int d2value); int oldval; ASSERT(d); /* check for slider direction */ if (d->h < d->w) vert = FALSE; /* set up the metrics for the control */ if (d->dp != NULL) { slhan = (BITMAP *)d->dp; if (vert) hh = slhan->h; else hh = slhan->w; } hmar = hh/2; irange = (vert) ? d->h : d->w; slmax = itofix(irange-hh); slratio = slmax / (d->d1); slpos = slratio * d->d2; slp = fixtoi(slpos); switch (msg) { case MSG_DRAW: sfg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; if (vert) { rectfill(gui_bmp, d->x, d->y, d->x+d->w/2-2, d->y+d->h-1, d->bg); rectfill(gui_bmp, d->x+d->w/2-1, d->y, d->x+d->w/2+1, d->y+d->h-1, sfg); rectfill(gui_bmp, d->x+d->w/2+2, d->y, d->x+d->w-1, d->y+d->h-1, d->bg); } else { rectfill(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h/2-2, d->bg); rectfill(gui_bmp, d->x, d->y+d->h/2-1, d->x+d->w-1, d->y+d->h/2+1, sfg); rectfill(gui_bmp, d->x, d->y+d->h/2+2, d->x+d->w-1, d->y+d->h-1, d->bg); } /* okay, background and slot are drawn, now draw the handle */ if (slhan) { if (vert) { slx = d->x+(d->w/2)-(slhan->w/2); sly = d->y+(d->h-1)-(hh+slp); } else { slx = d->x+slp; sly = d->y+(d->h/2)-(slhan->h/2); } draw_sprite(gui_bmp, slhan, slx, sly); } else { /* draw default handle */ if (vert) { slx = d->x; sly = d->y+(d->h)-(hh+slp); slw = d->w-1; slh = hh-1; } else { slx = d->x+slp; sly = d->y; slw = hh-1; slh = d->h-1; } /* draw body */ rectfill(gui_bmp, slx+2, sly, slx+(slw-2), sly+slh, sfg); vline(gui_bmp, slx+1, sly+1, sly+slh-1, sfg); vline(gui_bmp, slx+slw-1, sly+1, sly+slh-1, sfg); vline(gui_bmp, slx, sly+2, sly+slh-2, sfg); vline(gui_bmp, slx+slw, sly+2, sly+slh-2, sfg); vline(gui_bmp, slx+1, sly+2, sly+slh-2, d->bg); hline(gui_bmp, slx+2, sly+1, slx+slw-2, d->bg); putpixel(gui_bmp, slx+2, sly+2, d->bg); } if (d->flags & D_GOTFOCUS) dotted_rect(d->x, d->y, d->x+d->w-1, d->y+d->h-1, sfg, d->bg); break; case MSG_WANTFOCUS: case MSG_LOSTFOCUS: return D_WANTFOCUS; case MSG_KEY: if (!(d->flags & D_GOTFOCUS)) return D_WANTFOCUS; else return D_O_K; case MSG_CHAR: /* handle movement keys to move slider */ c >>= 8; if (vert) { upkey = KEY_UP; downkey = KEY_DOWN; pgupkey = KEY_PGUP; pgdnkey = KEY_PGDN; homekey = KEY_END; endkey = KEY_HOME; } else { upkey = KEY_RIGHT; downkey = KEY_LEFT; pgupkey = KEY_PGDN; pgdnkey = KEY_PGUP; homekey = KEY_HOME; endkey = KEY_END; } if (c == upkey) delta = 1; else if (c == downkey) delta = -1; else if (c == pgdnkey) delta = -d->d1 / 16; else if (c == pgupkey) delta = d->d1 / 16; else if (c == homekey) delta = -d->d2; else if (c == endkey) delta = d->d1 - d->d2; else delta = 0; if (delta) { oldpos = slp; oldval = d->d2; while (1) { d->d2 = d->d2+delta; slpos = slratio*d->d2; slp = fixtoi(slpos); if ((slp != oldpos) || (d->d2 <= 0) || (d->d2 >= d->d1)) break; } if (d->d2 < 0) d->d2 = 0; if (d->d2 > d->d1) d->d2 = d->d1; retval = D_USED_CHAR; if (d->d2 != oldval) { /* call callback function here */ if (d->dp2) { proc = d->dp2; retval |= (*proc)(d->dp3, d->d2); } object_message(d, MSG_DRAW, 0); } } break; case MSG_WHEEL: oldval = d->d2; d->d2 = CLAMP(0, d->d2+c, d->d1); if (d->d2 != oldval) { /* call callback function here */ if (d->dp2) { proc = d->dp2; retval |= (*proc)(d->dp3, d->d2); } object_message(d, MSG_DRAW, 0); } break; case MSG_CLICK: /* track the mouse until it is released */ mp = slp; while (gui_mouse_b()) { msx = gui_mouse_x(); msy = gui_mouse_y(); oldval = d->d2; if (vert) mp = (d->y+d->h-hmar)-msy; else mp = msx-(d->x+hmar); if (mp < 0) mp = 0; if (mp > irange-hh) mp = irange-hh; slpos = itofix(mp); slmax = fixdiv(slpos, slratio); newpos = fixtoi(slmax); if (newpos != oldval) { d->d2 = newpos; /* call callback function here */ if (d->dp2 != NULL) { proc = d->dp2; retval |= (*proc)(d->dp3, d->d2); } object_message(d, MSG_DRAW, 0); } /* let other objects continue to animate */ broadcast_dialog_message(MSG_IDLE, 0); } break; } return retval; } /* Overridable procedures used by standard GUI dialogs. */ #define MAKE_PROC(proc, default) \ int (*proc)(int, DIALOG *, int); \ int _##proc(int msg, DIALOG *d, int c) \ { \ return proc ? proc(msg, d, c) : default(msg, d, c); \ } MAKE_PROC(gui_shadow_box_proc, d_shadow_box_proc); MAKE_PROC(gui_ctext_proc, d_ctext_proc); MAKE_PROC(gui_button_proc, d_button_proc); MAKE_PROC(gui_edit_proc, d_edit_proc); MAKE_PROC(gui_list_proc, d_text_list_proc); MAKE_PROC(gui_text_list_proc, d_text_list_proc); allegro-4.4.3.1/src/keyboard.c0000664000175000017500000004416213437077643015042 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Keyboard input routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* thedmd: Keyboard driver hit GCC bug 43614. * Details: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43614 */ #if defined(NDEBUG) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 4) #define GCC_440_BUG_WORKAROUND __attribute__ ((optimize("O1"))) #else #define GCC_440_BUG_WORKAROUND #endif KEYBOARD_DRIVER *keyboard_driver = NULL; /* the active driver */ int _keyboard_installed = FALSE; static int keyboard_polled = FALSE; /* are we in polling mode? */ int three_finger_flag = TRUE; /* mode flags */ int key_led_flag = TRUE; volatile char key[KEY_MAX]; /* key pressed flags */ volatile char _key[KEY_MAX]; volatile int key_shifts = 0; /* current shift state */ volatile int _key_shifts = 0; int (*keyboard_callback)(int key) = NULL; /* callback functions */ int (*keyboard_ucallback)(int key, int *scancode) = NULL; void (*keyboard_lowlevel_callback)(int scancode) = NULL; static int (*keypressed_hook)(void) = NULL; /* hook functions */ static int (*readkey_hook)(void) = NULL; static int waiting_for_input = FALSE; /* idle flag */ static int repeat_delay = 250; /* auto key repeat */ static int repeat_rate = 33; static int repeat_key = -1; static int repeat_scan = -1; static int rate_changed = FALSE; /* Provide a default ASCII mapping for the most common keys. Keys whose * mapping changes dependind on the layout aren't listed - it's up to * the keyboard driver to do that. The reason for this it portability: * With an English keyboard, it makes sense to just list the KEY_* names, * but not with other keyboards. Ideally, every keyboard driver would * be able to fill in all the keys - but where it doesn't, this table * is a good compromise. */ static int common_ascii[KEY_MAX] = { 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 9, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', '*', '-', '+', 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '=', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* The same as above, but with descriptive names. Again, only keys which are * likely to be found on every keyboard are named. All keyboard drivers should * provide their own implementation though, especially if they use positional * mapping. */ AL_CONST char *_keyboard_common_names[KEY_MAX] = { "(none)", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0 PAD", "1 PAD", "2 PAD", "3 PAD", "4 PAD", "5 PAD", "6 PAD", "7 PAD", "8 PAD", "9 PAD", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "ESC", "KEY60", "KEY61", "KEY62", "BACKSPACE", "TAB", "KEY65", "KEY66", "ENTER", "KEY68", "KEY69", "BACKSLASH", "KEY71", "KEY72", "KEY73", "KEY74", "SPACE", "INSERT", "DEL", "HOME", "END", "PGUP", "PGDN", "LEFT", "RIGHT", "UP", "DOWN", "/ PAD", "* PAD", "- PAD", "+ PAD", "DEL PAD", "ENTER PAD", "PRINT", "PAUSE", "KEY94", "KEY95", "KEY96", "KEY97", "KEY98", "KEY99", "KEY100", "KEY101", "KEY102", "= PAD", "KEY104", "KEY105", "KEY106", "KEY107", "KEY108", "KEY109", "KEY110", "KEY111", "KEY112", "KEY113", "KEY114", "LSHIFT", "RSHIFT", "LCONTROL", "RCONTROL", "ALT", "ALTGR", "LWIN", "RWIN", "MENU", "SCRLOCK", "NUMLOCK", "CAPSLOCK" }; #define KEY_BUFFER_SIZE 64 /* character ring buffer */ typedef struct KEY_BUFFER { volatile int lock; volatile int start; volatile int end; volatile int key[KEY_BUFFER_SIZE]; volatile unsigned char scancode[KEY_BUFFER_SIZE]; } KEY_BUFFER; static volatile KEY_BUFFER key_buffer; static volatile KEY_BUFFER _key_buffer; /* add_key: * Helper function to add a keypress to a buffer. */ static INLINE void add_key(volatile KEY_BUFFER *buffer, int key, int scancode) { int c, d; if (buffer == &key_buffer) { if (keyboard_ucallback) { key = keyboard_ucallback(key, &scancode); if ((!key) && (!scancode)) return; } else if (keyboard_callback) { c = ((key <= 0xFF) ? key : '^') | (scancode << 8); d = keyboard_callback(c); if (!d) return; if (d != c) { key = (d & 0xFF); scancode = (d >> 8); } } } buffer->lock++; if (buffer->lock != 1) { buffer->lock--; return; } if ((waiting_for_input) && (keyboard_driver) && (keyboard_driver->stop_waiting_for_input)) keyboard_driver->stop_waiting_for_input(); if (buffer->end < KEY_BUFFER_SIZE-1) c = buffer->end+1; else c = 0; if (c != buffer->start) { buffer->key[buffer->end] = key; buffer->scancode[buffer->end] = scancode; buffer->end = c; } buffer->lock--; } /* clear_keybuf: * Clears the keyboard buffer. */ void clear_keybuf(void) { if (keyboard_polled) poll_keyboard(); key_buffer.lock++; _key_buffer.lock++; key_buffer.start = key_buffer.end = 0; _key_buffer.start = _key_buffer.end = 0; key_buffer.lock--; _key_buffer.lock--; if ((keypressed_hook) && (readkey_hook)) while (keypressed_hook()) readkey_hook(); } /* clear_key: * Helper function to clear the key[] array. */ static void clear_key(void) { int c; for (c=0; c> 8); return (c & 0xFF); } while (key_buffer.start == key_buffer.end) { if ((keyboard_driver) && (keyboard_driver->wait_for_input)) { waiting_for_input = TRUE; keyboard_driver->wait_for_input(); waiting_for_input = FALSE; } if (keyboard_polled) poll_keyboard(); rest(1); } c = key_buffer.key[key_buffer.start]; if (scancode) *scancode = key_buffer.scancode[key_buffer.start]; if (key_buffer.start < KEY_BUFFER_SIZE-1) key_buffer.start++; else key_buffer.start = 0; return c; } /* simulate_keypress: * Pushes a key into the keyboard buffer, as if it has just been pressed. */ void simulate_keypress(int key) { add_key(&key_buffer, key&0xFF, key>>8); } /* simulate_ukeypress: * Pushes a key into the keyboard buffer, as if it has just been pressed. */ void simulate_ukeypress(int key, int scancode) { add_key(&key_buffer, key, scancode); } /* set_leds: * Overrides the state of the keyboard LED indicators. * Set to -1 to return to default behavior. */ void set_leds(int leds) { if (leds < 0) { key_led_flag = TRUE; leds = key_shifts; } else key_led_flag = FALSE; if ((keyboard_driver) && (keyboard_driver->set_leds)) keyboard_driver->set_leds(leds); } /* set_keyboard_rate: * Sets the keyboard repeat rate. Times are given in milliseconds. * Passing zero times will disable the key repeat. */ void set_keyboard_rate(int delay, int repeat) { repeat_delay = delay; repeat_rate = repeat; if ((repeat_delay) && (keyboard_driver) && (keyboard_driver->set_rate)) { keyboard_driver->set_rate(delay, repeat); rate_changed = TRUE; } } /* repeat_timer: * Timer callback for doing automatic key repeats. */ static void repeat_timer(void) { if (keyboard_driver) _handle_key_press(repeat_key, repeat_scan); install_int(repeat_timer, repeat_rate); } END_OF_STATIC_FUNCTION(repeat_timer); /* install_keyboard_hooks: * You should only use this function if you *aren't* using the rest of the * keyboard handler. It can be called in the place of install_keyboard(), * and lets you provide callback routines to detect and read keypresses, * which will be used by the main keypressed() and readkey() functions. This * can be useful if you want to use Allegro's GUI code with a custom * keyboard handler, as it provides a way for the GUI to access keyboard * input from your own code. */ void install_keyboard_hooks(int (*keypressed)(void), int (*readkey)(void)) { key_buffer.lock = _key_buffer.lock = 0; clear_keybuf(); clear_key(); keypressed_hook = keypressed; readkey_hook = readkey; } /* update_shifts: * Helper function to update the key_shifts variable and LED state. */ static INLINE void update_shifts(void) { #define LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG) if (key_shifts != _key_shifts) { if ((keyboard_driver->set_leds) && (key_led_flag) && ((key_shifts ^ _key_shifts) & LED_FLAGS)) keyboard_driver->set_leds(_key_shifts); key_shifts = _key_shifts; } } /* _handle_key_press: * Called by the hardware driver to tell us when a key has been pressed. */ void _handle_key_press(int keycode, int scancode) { if ((keyboard_driver->poll) || (!keyboard_polled)) { /* process immediately */ if (scancode > 0) { if ((!repeat_delay) && (key[scancode])) return; key[scancode] = -1; if (keyboard_lowlevel_callback) keyboard_lowlevel_callback(scancode); } /* e.g. for F1, keycode=0, and scancode=KEY_F1 */ if (keycode >= 0) add_key(&key_buffer, keycode, scancode); update_shifts(); } else { /* deal with this during the next poll_keyboard() */ if (scancode > 0) { if ((!repeat_delay) && (_key[scancode])) return; _key[scancode] = -1; } if (keycode >= 0) add_key(&_key_buffer, keycode, scancode); } /* autorepeat? */ if ((keyboard_driver->autorepeat) && (repeat_delay) && (keycode >= 0) && (scancode > 0) && (scancode != KEY_PAUSE) && ((keycode != repeat_key) || (scancode != repeat_scan))) { repeat_key = keycode; repeat_scan = scancode; remove_int(repeat_timer); install_int(repeat_timer, repeat_delay); } } END_OF_FUNCTION(_handle_key_press); /* _handle_key_release: * Called by the hardware driver to tell us when a key has been released. */ void _handle_key_release(int scancode) { /* turn off autorepeat for the previous key */ if (repeat_scan == scancode) { remove_int(repeat_timer); repeat_key = -1; repeat_scan = -1; } if ((keyboard_driver->poll) || (!keyboard_polled)) { /* process immediately */ key[scancode] = 0; if (keyboard_lowlevel_callback) keyboard_lowlevel_callback(scancode | 0x80); update_shifts(); } else { /* deal with this during the next poll_keyboard() */ _key[scancode] = 0; } } END_OF_FUNCTION(_handle_key_release); /* poll_keyboard: * Polls the current keyboard state, and updates the user-visible * information accordingly. On some drivers this is actually required * to get the input, while on others it is only present to keep * compatibility with systems that do need it. So that people can test * their polling code even on platforms that don't strictly require it, * after this function has been called once, the entire system will * switch into polling mode and will no longer operate asynchronously * even if the driver actually does support that. */ int poll_keyboard(void) GCC_440_BUG_WORKAROUND; int poll_keyboard(void) { int i; if (!keyboard_driver) return -1; if (keyboard_driver->poll) { /* poll the driver */ keyboard_driver->poll(); } else if (!keyboard_polled) { /* switch into polling emulation mode */ for (i=0; i= 0 && scancode < KEY_MAX); if (keyboard_driver->scancode_to_ascii) return keyboard_driver->scancode_to_ascii(scancode); else return common_ascii[scancode]; } /* scancode_to_name: * Converts the given scancode to a description of the key. */ AL_CONST char *scancode_to_name(int scancode) { AL_CONST char *name = NULL; ASSERT(keyboard_driver); ASSERT((scancode >= 0) && (scancode < KEY_MAX)); if (keyboard_driver->scancode_to_name) name = keyboard_driver->scancode_to_name(scancode); if (!name) name = _keyboard_common_names[scancode]; ASSERT(name); return name; } /* install_keyboard: * Installs Allegro's keyboard handler. You must call this before using * any of the keyboard input routines. Returns -1 on failure. */ int install_keyboard(void) { _DRIVER_INFO *driver_list; int i; if (keyboard_driver) return 0; LOCK_VARIABLE(keyboard_driver); LOCK_VARIABLE(keyboard_polled); LOCK_VARIABLE(key); LOCK_VARIABLE(_key); LOCK_VARIABLE(key_shifts); LOCK_VARIABLE(_key_shifts); LOCK_VARIABLE(key_buffer); LOCK_VARIABLE(_key_buffer); LOCK_VARIABLE(three_finger_flag); LOCK_VARIABLE(key_led_flag); LOCK_VARIABLE(keyboard_callback); LOCK_VARIABLE(keyboard_ucallback); LOCK_VARIABLE(keyboard_lowlevel_callback); LOCK_VARIABLE(waiting_for_input); LOCK_VARIABLE(repeat_delay); LOCK_VARIABLE(repeat_rate); LOCK_VARIABLE(repeat_key); LOCK_VARIABLE(repeat_scan); LOCK_FUNCTION(_handle_key_press); LOCK_FUNCTION(_handle_key_release); LOCK_FUNCTION(repeat_timer); key_buffer.lock = _key_buffer.lock = 0; clear_keybuf(); clear_key(); if (system_driver->keyboard_drivers) driver_list = system_driver->keyboard_drivers(); else driver_list = _keyboard_driver_list; for (i=0; driver_list[i].driver; i++) { keyboard_driver = driver_list[i].driver; keyboard_driver->name = keyboard_driver->desc = get_config_text(keyboard_driver->ascii_name); if (keyboard_driver->init() == 0) break; } if (!driver_list[i].driver) { keyboard_driver = NULL; return -1; } keyboard_polled = (keyboard_driver->poll) ? TRUE : FALSE; set_leds(-1); _add_exit_func(remove_keyboard, "remove_keyboard"); _keyboard_installed = TRUE; if ((keyboard_driver->autorepeat) && (!_timer_installed)) install_timer(); update_shifts(); return 0; } /* remove_keyboard: * Removes the keyboard handler. You don't normally need to call this, * because allegro_exit() will do it for you. */ void remove_keyboard(void) { if (!keyboard_driver) return; set_leds(-1); if (rate_changed) { set_keyboard_rate(250, 33); rate_changed = FALSE; } keyboard_driver->exit(); keyboard_driver = NULL; if (repeat_key >= 0) { remove_int(repeat_timer); repeat_key = -1; repeat_scan = -1; } _keyboard_installed = FALSE; keyboard_polled = FALSE; clear_keybuf(); clear_key(); key_shifts = _key_shifts = 0; _remove_exit_func(remove_keyboard); } allegro-4.4.3.1/src/graphics.c0000664000175000017500000013663113437077643015045 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Graphics mode set and bitmap creation routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" extern void blit_end(void); /* for LOCK_FUNCTION; defined in blit.c */ #define PREFIX_I "al-gfx INFO: " #define PREFIX_W "al-gfx WARNING: " #define PREFIX_E "al-gfx ERROR: " static int gfx_virgin = TRUE; /* is the graphics system active? */ int _sub_bitmap_id_count = 1; /* hash value for sub-bitmaps */ int _gfx_mode_set_count = 0; /* has the graphics mode changed? */ int _screen_split_position = 0; /* has the screen been split? */ int _safe_gfx_mode_change = 0; /* are we getting through GFX_SAFE? */ RGB_MAP *rgb_map = NULL; /* RGB -> palette entry conversion */ COLOR_MAP *color_map = NULL; /* translucency/lighting table */ int _color_depth = 8; /* how many bits per pixel? */ int _refresh_rate_request = 0; /* requested refresh rate */ static int current_refresh_rate = 0; /* refresh rate set by the driver */ int _wait_for_vsync = TRUE; /* vsync when page-flipping? */ int _color_conv = COLORCONV_TOTAL; /* which formats to auto convert? */ static int color_conv_set = FALSE; /* has the user set conversion mode? */ int _palette_color8[256]; /* palette -> pixel mapping */ int _palette_color15[256]; int _palette_color16[256]; int _palette_color24[256]; int _palette_color32[256]; int *palette_color = _palette_color8; BLENDER_FUNC _blender_func15 = NULL; /* truecolor pixel blender routines */ BLENDER_FUNC _blender_func16 = NULL; BLENDER_FUNC _blender_func24 = NULL; BLENDER_FUNC _blender_func32 = NULL; BLENDER_FUNC _blender_func15x = NULL; BLENDER_FUNC _blender_func16x = NULL; BLENDER_FUNC _blender_func24x = NULL; int _blender_col_15 = 0; /* for truecolor lit sprites */ int _blender_col_16 = 0; int _blender_col_24 = 0; int _blender_col_32 = 0; int _blender_alpha = 0; /* for truecolor translucent drawing */ int _rgb_r_shift_15 = DEFAULT_RGB_R_SHIFT_15; /* truecolor pixel format */ int _rgb_g_shift_15 = DEFAULT_RGB_G_SHIFT_15; int _rgb_b_shift_15 = DEFAULT_RGB_B_SHIFT_15; int _rgb_r_shift_16 = DEFAULT_RGB_R_SHIFT_16; int _rgb_g_shift_16 = DEFAULT_RGB_G_SHIFT_16; int _rgb_b_shift_16 = DEFAULT_RGB_B_SHIFT_16; int _rgb_r_shift_24 = DEFAULT_RGB_R_SHIFT_24; int _rgb_g_shift_24 = DEFAULT_RGB_G_SHIFT_24; int _rgb_b_shift_24 = DEFAULT_RGB_B_SHIFT_24; int _rgb_r_shift_32 = DEFAULT_RGB_R_SHIFT_32; int _rgb_g_shift_32 = DEFAULT_RGB_G_SHIFT_32; int _rgb_b_shift_32 = DEFAULT_RGB_B_SHIFT_32; int _rgb_a_shift_32 = DEFAULT_RGB_A_SHIFT_32; /* lookup table for scaling 5 bit colors up to 8 bits */ int _rgb_scale_5[32] = { 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255 }; /* lookup table for scaling 6 bit colors up to 8 bits */ int _rgb_scale_6[64] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255 }; GFX_VTABLE _screen_vtable; /* accelerated drivers change this */ typedef struct VRAM_BITMAP /* list of video memory bitmaps */ { int x, y, w, h; BITMAP *bmp; struct VRAM_BITMAP *next_x, *next_y; } VRAM_BITMAP; static VRAM_BITMAP *vram_bitmap_list = NULL; #define BMP_MAX_SIZE 46340 /* sqrt(INT_MAX) */ /* the product of these must fit in an int */ static int failed_bitmap_w = BMP_MAX_SIZE; static int failed_bitmap_h = BMP_MAX_SIZE; static int _set_gfx_mode(int card, int w, int h, int v_w, int v_h, int allow_config); static int _set_gfx_mode_safe(int card, int w, int h, int v_w, int v_h); /* lock_bitmap: * Locks all the memory used by a bitmap structure. */ void lock_bitmap(BITMAP *bmp) { LOCK_DATA(bmp, sizeof(BITMAP) + sizeof(char *) * bmp->h); if (bmp->dat) { LOCK_DATA(bmp->dat, bmp->w * bmp->h * BYTES_PER_PIXEL(bitmap_color_depth(bmp))); } } /* request_refresh_rate: * Requests that the next call to set_gfx_mode() use the specified refresh * rate. */ void request_refresh_rate(int rate) { _refresh_rate_request = rate; } /* get_refresh_rate: * Returns the refresh rate set by the most recent call to set_gfx_mode(). */ int get_refresh_rate(void) { return current_refresh_rate; } /* _set_current_refresh_rate: * Sets the current refresh rate. * (This function must be called by the gfx drivers) */ void _set_current_refresh_rate(int rate) { /* sanity check to discard bogus values */ if ((rate<40) || (rate>200)) rate = 0; current_refresh_rate = rate; /* adjust retrace speed */ _vsync_speed = rate ? BPS_TO_TIMER(rate) : BPS_TO_TIMER(70); } /* sort_gfx_mode_list: * Callback for quick-sorting a mode-list. */ static int sort_gfx_mode_list(GFX_MODE *entry1, GFX_MODE *entry2) { if (entry1->width > entry2->width) { return +1; } else if (entry1->width < entry2->width) { return -1; } else { if (entry1->height > entry2->height) { return +1; } else if (entry1->height < entry2->height) { return -1; } else { if (entry1->bpp > entry2->bpp) { return +1; } else if (entry1->bpp < entry2->bpp) { return -1; } else { return 0; } } } } /* get_gfx_mode_list: * Attempts to create a list of all the supported video modes for a certain * GFX driver. */ GFX_MODE_LIST *get_gfx_mode_list(int card) { _DRIVER_INFO *list_entry; GFX_DRIVER *drv = NULL; GFX_MODE_LIST *gfx_mode_list = NULL; ASSERT(system_driver); /* ask the system driver for a list of graphics hardware drivers */ if (system_driver->gfx_drivers) list_entry = system_driver->gfx_drivers(); else list_entry = _gfx_driver_list; /* find the graphics driver, and if it can fetch mode lists, do so */ while (list_entry->driver) { if (list_entry->id == card) { drv = list_entry->driver; if (!drv->fetch_mode_list) return NULL; gfx_mode_list = drv->fetch_mode_list(); if (!gfx_mode_list) return NULL; break; } list_entry++; } if (!drv) return NULL; /* sort the list and finish */ qsort(gfx_mode_list->mode, gfx_mode_list->num_modes, sizeof(GFX_MODE), (int (*) (AL_CONST void *, AL_CONST void *))sort_gfx_mode_list); return gfx_mode_list; } /* destroy_gfx_mode_list: * Removes the mode list created by get_gfx_mode_list() from memory. */ void destroy_gfx_mode_list(GFX_MODE_LIST *gfx_mode_list) { if (gfx_mode_list) { if (gfx_mode_list->mode) _AL_FREE(gfx_mode_list->mode); _AL_FREE(gfx_mode_list); } } /* set_color_depth: * Sets the pixel size (in bits) which will be used by subsequent calls to * set_gfx_mode() and create_bitmap(). Valid depths are 8, 15, 16, 24 and 32. */ void set_color_depth(int depth) { _color_depth = depth; switch (depth) { case 8: palette_color = _palette_color8; break; case 15: palette_color = _palette_color15; break; case 16: palette_color = _palette_color16; break; case 24: palette_color = _palette_color24; break; case 32: palette_color = _palette_color32; break; default: ASSERT(FALSE); } } /* get_color_depth: * Returns the current color depth. */ int get_color_depth(void) { return _color_depth; } /* set_color_conversion: * Sets a bit mask specifying which types of color format conversions are * valid when loading data from disk. */ void set_color_conversion(int mode) { _color_conv = mode; color_conv_set = TRUE; } /* get_color_conversion: * Returns the bitmask specifying which types of color format * conversion are valid when loading data from disk. */ int get_color_conversion(void) { return _color_conv; } /* _color_load_depth: * Works out which color depth an image should be loaded as, given the * current conversion mode. */ int _color_load_depth(int depth, int hasalpha) { typedef struct CONVERSION_FLAGS { int flag; int in_depth; int out_depth; int hasalpha; } CONVERSION_FLAGS; static CONVERSION_FLAGS conversion_flags[] = { { COLORCONV_8_TO_15, 8, 15, FALSE }, { COLORCONV_8_TO_16, 8, 16, FALSE }, { COLORCONV_8_TO_24, 8, 24, FALSE }, { COLORCONV_8_TO_32, 8, 32, FALSE }, { COLORCONV_15_TO_8, 15, 8, FALSE }, { COLORCONV_15_TO_16, 15, 16, FALSE }, { COLORCONV_15_TO_24, 15, 24, FALSE }, { COLORCONV_15_TO_32, 15, 32, FALSE }, { COLORCONV_16_TO_8, 16, 8, FALSE }, { COLORCONV_16_TO_15, 16, 15, FALSE }, { COLORCONV_16_TO_24, 16, 24, FALSE }, { COLORCONV_16_TO_32, 16, 32, FALSE }, { COLORCONV_24_TO_8, 24, 8, FALSE }, { COLORCONV_24_TO_15, 24, 15, FALSE }, { COLORCONV_24_TO_16, 24, 16, FALSE }, { COLORCONV_24_TO_32, 24, 32, FALSE }, { COLORCONV_32_TO_8, 32, 8, FALSE }, { COLORCONV_32_TO_15, 32, 15, FALSE }, { COLORCONV_32_TO_16, 32, 16, FALSE }, { COLORCONV_32_TO_24, 32, 24, FALSE }, { COLORCONV_32A_TO_8, 32, 8 , TRUE }, { COLORCONV_32A_TO_15, 32, 15, TRUE }, { COLORCONV_32A_TO_16, 32, 16, TRUE }, { COLORCONV_32A_TO_24, 32, 24, TRUE } }; int i; ASSERT((_gfx_mode_set_count > 0) || (color_conv_set)); if (depth == _color_depth) return depth; for (i=0; i < (int)(sizeof(conversion_flags)/sizeof(CONVERSION_FLAGS)); i++) { if ((conversion_flags[i].in_depth == depth) && (conversion_flags[i].out_depth == _color_depth) && ((conversion_flags[i].hasalpha != 0) == (hasalpha != 0))) { if (_color_conv & conversion_flags[i].flag) return _color_depth; else return depth; } } ASSERT(FALSE); return 0; } /* _get_vtable: * Returns a pointer to the linear vtable for the specified color depth. */ GFX_VTABLE *_get_vtable(int color_depth) { GFX_VTABLE *vt; int i; ASSERT(system_driver); if (system_driver->get_vtable) { vt = system_driver->get_vtable(color_depth); if (vt) { LOCK_DATA(vt, sizeof(GFX_VTABLE)); LOCK_CODE(vt->draw_sprite, (long)vt->draw_sprite_end - (long)vt->draw_sprite); LOCK_CODE(vt->blit_from_memory, (long)vt->blit_end - (long)vt->blit_from_memory); return vt; } } for (i=0; _vtable_list[i].vtable; i++) { if (_vtable_list[i].color_depth == color_depth) { LOCK_DATA(_vtable_list[i].vtable, sizeof(GFX_VTABLE)); LOCK_CODE(_vtable_list[i].vtable->draw_sprite, (long)_vtable_list[i].vtable->draw_sprite_end - (long)_vtable_list[i].vtable->draw_sprite); LOCK_CODE(_vtable_list[i].vtable->blit_from_memory, (long)_vtable_list[i].vtable->blit_end - (long)_vtable_list[i].vtable->blit_from_memory); return _vtable_list[i].vtable; } } return NULL; } /* shutdown_gfx: * Used by allegro_exit() to return the system to text mode. */ static void shutdown_gfx(void) { if (gfx_driver) set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); if (system_driver->restore_console_state) system_driver->restore_console_state(); _remove_exit_func(shutdown_gfx); gfx_virgin = TRUE; } #define GFX_DRIVER_FULLSCREEN_FLAG 0x01 #define GFX_DRIVER_WINDOWED_FLAG 0x02 /* gfx_driver_is_valid: * Checks that the graphics driver 'drv' fulfills the condition * expressed by the bitmask 'flags'. */ static int gfx_driver_is_valid(GFX_DRIVER *drv, int flags) { if ((flags & GFX_DRIVER_FULLSCREEN_FLAG) && drv->windowed) return FALSE; if ((flags & GFX_DRIVER_WINDOWED_FLAG) && !drv->windowed) return FALSE; return TRUE; } /* get_gfx_driver_from_id: * Retrieves a pointer to the graphics driver identified by 'card' from * the list 'driver_list' or NULL if it doesn't exist. */ static GFX_DRIVER *get_gfx_driver_from_id(int card, _DRIVER_INFO *driver_list) { int c; for (c=0; driver_list[c].driver; c++) { if (driver_list[c].id == card) return driver_list[c].driver; } return NULL; } /* init_gfx_driver: * Helper function for initializing a graphics driver. */ static BITMAP *init_gfx_driver(GFX_DRIVER *drv, int w, int h, int v_w, int v_h) { drv->name = drv->desc = get_config_text(drv->ascii_name); /* set gfx_driver so that it is visible when initializing the driver */ gfx_driver = drv; return drv->init(w, h, v_w, v_h, _color_depth); } /* get_config_gfx_driver: * Helper function for set_gfx_mode: it reads the gfx_card* config variables and * tries to set the graphics mode if a matching driver is found. Returns TRUE if * at least one matching driver was found, FALSE otherwise. */ static int get_config_gfx_driver(char *gfx_card, int w, int h, int v_w, int v_h, int flags, _DRIVER_INFO *driver_list) { char buf[512], tmp[64]; GFX_DRIVER *drv; int found = FALSE; int card, n; /* try the drivers that are listed in the config file */ for (n=-2; n<255; n++) { switch (n) { case -2: /* example: gfx_card_640x480x16 = */ uszprintf(buf, sizeof(buf), uconvert_ascii("%s_%dx%dx%d", tmp), gfx_card, w, h, _color_depth); break; case -1: /* example: gfx_card_24bpp = */ uszprintf(buf, sizeof(buf), uconvert_ascii("%s_%dbpp", tmp), gfx_card, _color_depth); break; case 0: /* example: gfx_card = */ uszprintf(buf, sizeof(buf), uconvert_ascii("%s", tmp), gfx_card); break; default: /* example: gfx_card1 = */ uszprintf(buf, sizeof(buf), uconvert_ascii("%s%d", tmp), gfx_card, n); break; } card = get_config_id(uconvert_ascii("graphics", tmp), buf, 0); if (card) { drv = get_gfx_driver_from_id(card, driver_list); if (drv && gfx_driver_is_valid(drv, flags)) { found = TRUE; screen = init_gfx_driver(drv, w, h, v_w, v_h); if (screen) break; } } else { /* Stop searching the gfx_card#n (n>0) family at the first missing member, * except gfx_card1 which could have been identified with gfx_card. */ if (n > 1) break; } } return found; } /* set_gfx_mode: * Sets the graphics mode. The card should be one of the GFX_* constants * from allegro.h, or GFX_AUTODETECT to accept any graphics driver. Pass * GFX_TEXT to return to text mode (although allegro_exit() will usually * do this for you). The w and h parameters specify the screen resolution * you want, and v_w and v_h specify the minumum virtual screen size. * The graphics drivers may actually create a much larger virtual screen, * so you should check the values of VIRTUAL_W and VIRTUAL_H after you * set the mode. If unable to select an appropriate mode, this function * returns -1. */ int set_gfx_mode(int card, int w, int h, int v_w, int v_h) { TRACE(PREFIX_I "Called set_gfx_mode(%d, %d, %d, %d, %d).\n", card, w, h, v_w, v_h); /* TODO: shouldn't this be incremented only IF successful? */ _gfx_mode_set_count++; /* special bodge for the GFX_SAFE driver */ if (card == GFX_SAFE) return _set_gfx_mode_safe(card, w, h, v_w, v_h); else return _set_gfx_mode(card, w, h, v_w, v_h, TRUE); } /* _set_gfx_mode: * Called by set_gfx_mode(). Separated to make a clear difference between * the virtual GFX_SAFE driver and the rest. The allow_config parameter, * if true, allows the configuration to override the graphics card/driver * when using GFX_AUTODETECT. */ static int _set_gfx_mode(int card, int w, int h, int v_w, int v_h, int allow_config) { _DRIVER_INFO *driver_list; GFX_DRIVER *drv; char tmp1[64], tmp2[64]; AL_CONST char *dv; int flags = 0; int c; ASSERT(system_driver); ASSERT(card != GFX_SAFE); /* remember the current console state */ if (gfx_virgin) { TRACE(PREFIX_I "First call, remembering console state.\n"); LOCK_FUNCTION(_stub_bank_switch); LOCK_FUNCTION(blit); if (system_driver->save_console_state) system_driver->save_console_state(); _add_exit_func(shutdown_gfx, "shutdown_gfx"); gfx_virgin = FALSE; } timer_simulate_retrace(FALSE); _screen_split_position = 0; /* close down any existing graphics driver */ if (gfx_driver) { TRACE(PREFIX_I "Closing graphics driver (%p) ", gfx_driver); TRACE("%s.\n", gfx_driver->ascii_name); if (_al_linker_mouse) _al_linker_mouse->show_mouse(NULL); while (vram_bitmap_list) destroy_bitmap(vram_bitmap_list->bmp); bmp_read_line(screen, 0); bmp_write_line(screen, 0); bmp_unwrite_line(screen); if (gfx_driver->scroll) gfx_driver->scroll(0, 0); if (gfx_driver->exit) gfx_driver->exit(screen); destroy_bitmap(screen); gfx_driver = NULL; screen = NULL; gfx_capabilities = 0; } /* We probably don't want to do this because it makes * Allegro "forget" the color layout of previously set * graphics modes. But it should be retained if bitmaps * created in those modes are to be used in the new mode. */ #if 0 /* restore default truecolor pixel format */ _rgb_r_shift_15 = 0; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 10; _rgb_r_shift_16 = 0; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 11; _rgb_r_shift_24 = 0; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 16; _rgb_r_shift_32 = 0; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 16; _rgb_a_shift_32 = 24; #endif gfx_capabilities = 0; _set_current_refresh_rate(0); /* return to text mode? */ if (card == GFX_TEXT) { TRACE(PREFIX_I "Closing, restoring original console state.\n"); if (system_driver->restore_console_state) system_driver->restore_console_state(); if (_gfx_bank) { _AL_FREE(_gfx_bank); _gfx_bank = NULL; } TRACE(PREFIX_I "Graphic mode closed.\n"); return 0; } /* now to the interesting part: let's try to find a graphics driver */ usetc(allegro_error, 0); /* ask the system driver for a list of graphics hardware drivers */ if (system_driver->gfx_drivers) driver_list = system_driver->gfx_drivers(); else driver_list = _gfx_driver_list; /* filter specific fullscreen/windowed driver requests */ if (card == GFX_AUTODETECT_FULLSCREEN) { flags |= GFX_DRIVER_FULLSCREEN_FLAG; card = GFX_AUTODETECT; } else if (card == GFX_AUTODETECT_WINDOWED) { flags |= GFX_DRIVER_WINDOWED_FLAG; card = GFX_AUTODETECT; } if (card == GFX_AUTODETECT) { /* autodetect the driver */ int found = FALSE; tmp1[0] = '\0'; /* first try the config variables */ if (allow_config) { /* try the gfx_card variable if GFX_AUTODETECT or GFX_AUTODETECT_FULLSCREEN was selected */ if (!(flags & GFX_DRIVER_WINDOWED_FLAG)) found = get_config_gfx_driver(uconvert_ascii("gfx_card", tmp1), w, h, v_w, v_h, flags, driver_list); /* try the gfx_cardw variable if GFX_AUTODETECT or GFX_AUTODETECT_WINDOWED was selected */ if (!(flags & GFX_DRIVER_FULLSCREEN_FLAG) && !found) found = get_config_gfx_driver(uconvert_ascii("gfx_cardw", tmp1), w, h, v_w, v_h, flags, driver_list); } /* go through the list of autodetected drivers if none was previously found */ if (!found) { TRACE(PREFIX_I "Autodetecting graphic driver.\n"); for (c=0; driver_list[c].driver; c++) { if (driver_list[c].autodetect) { drv = driver_list[c].driver; if (gfx_driver_is_valid(drv, flags)) { screen = init_gfx_driver(drv, w, h, v_w, v_h); if (screen) break; } } } } else { TRACE(PREFIX_I "GFX_AUTODETECT overridden through configuration:" " %s.\n", tmp1); } } else { /* search the list for the requested driver */ drv = get_gfx_driver_from_id(card, driver_list); if (drv) screen = init_gfx_driver(drv, w, h, v_w, v_h); } /* gracefully handle failure */ if (!screen) { gfx_driver = NULL; /* set by init_gfx_driver() */ if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to find a suitable graphics driver")); TRACE(PREFIX_E "Failed setting graphic driver %d.\n", card); return -1; } /* set the basic capabilities of the driver */ if ((VIRTUAL_W > SCREEN_W) || (VIRTUAL_H > SCREEN_H)) { if (gfx_driver->scroll) gfx_capabilities |= GFX_CAN_SCROLL; if ((gfx_driver->request_scroll) || (gfx_driver->request_video_bitmap)) gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; } /* check whether we are instructed to disable vsync */ dv = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("disable_vsync", tmp2), NULL); if ((dv) && ((c = ugetc(dv)) != 0) && ((c == 'y') || (c == 'Y') || (c == '1'))) _wait_for_vsync = FALSE; else _wait_for_vsync = TRUE; TRACE(PREFIX_I "The driver %s wait for vsync.\n", (_wait_for_vsync) ? "will" : "won't"); /* Give the gfx driver an opportunity to set the drawing mode */ if ((gfx_driver->drawing_mode) && (!_dispsw_status)) gfx_driver->drawing_mode(); clear_bitmap(screen); /* set up the default colors */ for (c=0; c<256; c++) _palette_color8[c] = c; set_palette(default_palette); if (_color_depth == 8) { gui_fg_color = 255; gui_mg_color = 8; gui_bg_color = 0; } else { gui_fg_color = makecol(0, 0, 0); gui_mg_color = makecol(128, 128, 128); gui_bg_color = makecol(255, 255, 255); } if (_al_linker_mouse) _al_linker_mouse->set_mouse_etc(); LOCK_DATA(gfx_driver, sizeof(GFX_DRIVER)); _register_switch_bitmap(screen, NULL); TRACE(PREFIX_I "set_gfx_card success for %dx%dx%d.\n", screen->w, screen->h, bitmap_color_depth(screen)); return 0; } /* _set_gfx_mode_safe: * Special wrapper used when the card parameter of set_gfx_mode() * is GFX_SAFE. In this case the function tries to query the * system driver for a "safe" resolution+driver it knows it will * work, and set it. If the system driver cannot get a "safe" * resolution+driver, it will try the given parameters. */ static int _set_gfx_mode_safe(int card, int w, int h, int v_w, int v_h) { char buf[ALLEGRO_ERROR_SIZE], tmp1[64]; struct GFX_MODE mode; int ret, driver; ASSERT(card == GFX_SAFE); ASSERT(system_driver); TRACE(PREFIX_I "Trying to set a safe graphics mode.\n"); if (system_driver->get_gfx_safe_mode) { ustrzcpy(buf, sizeof(buf), allegro_error); /* retrieve the safe graphics mode */ system_driver->get_gfx_safe_mode(&driver, &mode); TRACE(PREFIX_I "The system driver suggests %dx%dx%d\n", mode.width, mode.height, mode.bpp); /* try using the specified resolution but current depth */ if (_set_gfx_mode(driver, w, h, 0, 0, TRUE) == 0) return 0; ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, buf); /* finally use the safe settings */ set_color_depth(mode.bpp); if (_set_gfx_mode(driver, mode.width, mode.height, 0, 0, TRUE) == 0) return 0; ASSERT(FALSE); /* the safe graphics mode must always work */ } else { TRACE(PREFIX_W "The system driver was unable to get a safe mode, " "I'll try with the specified parameters...\n"); /* no safe graphics mode, try hard-coded autodetected modes with * custom settings */ _safe_gfx_mode_change = 1; ret = _set_gfx_mode(GFX_AUTODETECT, w, h, 0, 0, TRUE); _safe_gfx_mode_change = 0; if (ret == 0) return 0; } /* failing to set GFX_SAFE is a fatal error */ TRACE(PREFIX_E "Bad bad, not even GFX_SAFE works?\n"); _set_gfx_mode(GFX_TEXT, 0, 0, 0, 0, TRUE); allegro_message(uconvert_ascii("%s\n", tmp1), get_config_text("Fatal error: unable to set GFX_SAFE")); return -1; } /* _sort_out_virtual_width: * Decides how wide the virtual screen really needs to be. That is more * complicated than it sounds, because the Allegro graphics primitives * require that each scanline be contained within a single bank. That * causes problems on cards that don't have overlapping banks, unless the * bank size is a multiple of the virtual width. So we may need to adjust * the width just to keep things running smoothly... */ void _sort_out_virtual_width(int *width, GFX_DRIVER *driver) { int w = *width; /* hah! I love VBE 2.0... */ if (driver->linear) return; /* if banks can overlap, we are ok... */ if (driver->bank_size > driver->bank_gran) return; /* damn, have to increase the virtual width */ while (((driver->bank_size / w) * w) != driver->bank_size) { w++; if (w > driver->bank_size) break; /* oh shit */ } *width = w; } /* _make_bitmap: * Helper function for creating the screen bitmap. Sets up a bitmap * structure for addressing video memory at addr, and fills the bank * switching table using bank size/granularity information from the * specified graphics driver. */ BITMAP *_make_bitmap(int w, int h, uintptr_t addr, GFX_DRIVER *driver, int color_depth, int bpl) { GFX_VTABLE *vtable = _get_vtable(color_depth); int i, bank, size; BITMAP *b; if (!vtable) return NULL; size = sizeof(BITMAP) + sizeof(char *) * h; b = (BITMAP *)_AL_MALLOC(size); if (!b) return NULL; _gfx_bank = _AL_REALLOC(_gfx_bank, h * sizeof(int)); if (!_gfx_bank) { _AL_FREE(b); return NULL; } LOCK_DATA(b, size); LOCK_DATA(_gfx_bank, h * sizeof(int)); b->w = b->cr = w; b->h = b->cb = h; b->clip = TRUE; b->cl = b->ct = 0; b->vtable = &_screen_vtable; b->write_bank = b->read_bank = _stub_bank_switch; b->dat = NULL; b->id = BMP_ID_VIDEO; b->extra = NULL; b->x_ofs = 0; b->y_ofs = 0; b->seg = _video_ds(); memcpy(&_screen_vtable, vtable, sizeof(GFX_VTABLE)); LOCK_DATA(&_screen_vtable, sizeof(GFX_VTABLE)); _last_bank_1 = _last_bank_2 = -1; driver->vid_phys_base = addr; b->line[0] = (unsigned char *)addr; _gfx_bank[0] = 0; if (driver->linear) { for (i=1; iline[i] = b->line[i-1] + bpl; _gfx_bank[i] = 0; } } else { bank = 0; for (i=1; iline[i] = b->line[i-1] + bpl; if (b->line[i]+bpl-1 >= (unsigned char *)addr + driver->bank_size) { while (b->line[i] >= (unsigned char *)addr + driver->bank_gran) { b->line[i] -= driver->bank_gran; bank++; } } _gfx_bank[i] = bank; } } return b; } /* create_bitmap_ex * Creates a new memory bitmap in the specified color_depth */ BITMAP *create_bitmap_ex(int color_depth, int width, int height) { GFX_VTABLE *vtable; BITMAP *bitmap; int nr_pointers; int padding; int i; ASSERT(width >= 0); ASSERT(height > 0); ASSERT(system_driver); if (system_driver->create_bitmap) return system_driver->create_bitmap(color_depth, width, height); vtable = _get_vtable(color_depth); if (!vtable) return NULL; /* We need at least two pointers when drawing, otherwise we get crashes with * Electric Fence. We think some of the assembly code assumes a second line * pointer is always available. */ nr_pointers = MAX(2, height); bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers)); if (!bitmap) return NULL; /* This avoids a crash for assembler code accessing the last pixel, as it * read 4 bytes instead of 3. */ padding = (color_depth == 24) ? 1 : 0; bitmap->dat = _AL_MALLOC_ATOMIC(width * height * BYTES_PER_PIXEL(color_depth) + padding); if (!bitmap->dat) { _AL_FREE(bitmap); return NULL; } bitmap->w = bitmap->cr = width; bitmap->h = bitmap->cb = height; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->vtable = vtable; bitmap->write_bank = bitmap->read_bank = _stub_bank_switch; bitmap->id = 0; bitmap->extra = NULL; bitmap->x_ofs = 0; bitmap->y_ofs = 0; bitmap->seg = _default_ds(); if (height > 0) { bitmap->line[0] = bitmap->dat; for (i=1; iline[i] = bitmap->line[i-1] + width * BYTES_PER_PIXEL(color_depth); } if (system_driver->created_bitmap) system_driver->created_bitmap(bitmap); return bitmap; } /* create_bitmap: * Creates a new memory bitmap. */ BITMAP *create_bitmap(int width, int height) { ASSERT(width >= 0); ASSERT(height > 0); return create_bitmap_ex(_color_depth, width, height); } /* create_sub_bitmap: * Creates a sub bitmap, ie. a bitmap sharing drawing memory with a * pre-existing bitmap, but possibly with different clipping settings. * Usually will be smaller, and positioned at some arbitrary point. * * Mark Wodrich is the owner of the brain responsible this hugely useful * and beautiful function. */ BITMAP *create_sub_bitmap(BITMAP *parent, int x, int y, int width, int height) { BITMAP *bitmap; int nr_pointers; int i; ASSERT(parent); ASSERT((x >= 0) && (y >= 0) && (x < parent->w) && (y < parent->h)); ASSERT((width > 0) && (height > 0)); ASSERT(system_driver); if (x+width > parent->w) width = parent->w-x; if (y+height > parent->h) height = parent->h-y; if (parent->vtable->create_sub_bitmap) return parent->vtable->create_sub_bitmap(parent, x, y, width, height); if (system_driver->create_sub_bitmap) return system_driver->create_sub_bitmap(parent, x, y, width, height); /* get memory for structure and line pointers */ /* (see create_bitmap for the reason we need at least two) */ nr_pointers = MAX(2, height); bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers)); if (!bitmap) return NULL; acquire_bitmap(parent); bitmap->w = bitmap->cr = width; bitmap->h = bitmap->cb = height; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->vtable = parent->vtable; bitmap->write_bank = parent->write_bank; bitmap->read_bank = parent->read_bank; bitmap->dat = NULL; bitmap->extra = NULL; bitmap->x_ofs = x + parent->x_ofs; bitmap->y_ofs = y + parent->y_ofs; bitmap->seg = parent->seg; /* All bitmaps are created with zero ID's. When a sub-bitmap is created, * a unique ID is needed to identify the relationship when blitting from * one to the other. This is obtained from the global variable * _sub_bitmap_id_count, which provides a sequence of integers (yes I * know it will wrap eventually, but not for a long time :-) If the * parent already has an ID the sub-bitmap adopts it, otherwise a new * ID is given to both the parent and the child. */ if (!(parent->id & BMP_ID_MASK)) { parent->id |= _sub_bitmap_id_count; _sub_bitmap_id_count = (_sub_bitmap_id_count+1) & BMP_ID_MASK; } bitmap->id = parent->id | BMP_ID_SUB; bitmap->id &= ~BMP_ID_LOCKED; if (is_planar_bitmap(bitmap)) x /= 4; x *= BYTES_PER_PIXEL(bitmap_color_depth(bitmap)); /* setup line pointers: each line points to a line in the parent bitmap */ for (i=0; iline[i] = parent->line[y+i] + x; if (bitmap->vtable->set_clip) bitmap->vtable->set_clip(bitmap); if (parent->vtable->created_sub_bitmap) parent->vtable->created_sub_bitmap(bitmap, parent); if (system_driver->created_sub_bitmap) system_driver->created_sub_bitmap(bitmap, parent); if (parent->id & BMP_ID_VIDEO) _register_switch_bitmap(bitmap, parent); release_bitmap(parent); return bitmap; } /* add_vram_block: * Creates a video memory bitmap out of the specified region * of the larger screen surface, returning a pointer to it. */ static BITMAP *add_vram_block(int x, int y, int w, int h) { VRAM_BITMAP *b, *new_b; VRAM_BITMAP **last_p; new_b = _AL_MALLOC(sizeof(VRAM_BITMAP)); if (!new_b) return NULL; new_b->x = x; new_b->y = y; new_b->w = w; new_b->h = h; new_b->bmp = create_sub_bitmap(screen, x, y, w, h); if (!new_b->bmp) { _AL_FREE(new_b); return NULL; } /* find sorted y-position */ last_p = &vram_bitmap_list; for (b = vram_bitmap_list; b && (b->y < new_b->y); b = b->next_y) last_p = &b->next_y; /* insert */ *last_p = new_b; new_b->next_y = b; return new_b->bmp; } /* create_video_bitmap: * Attempts to make a bitmap object for accessing offscreen video memory. * * The algorithm is similar to algorithms for drawing polygons. Think of * a horizontal stripe whose height is equal to that of the new bitmap. * It is initially aligned to the top of video memory and then it moves * downwards, stopping each time its top coincides with the bottom of a * video bitmap. For each stop, create a list of video bitmaps intersecting * the stripe, sorted by the left coordinate, from left to right, in the * next_x linked list. We look through this list and stop as soon as the * gap between the rightmost right edge seen so far and the current left * edge is big enough for the new video bitmap. In that case, we are done. * If we don't find such a gap, we move the stripe further down. * * To make it efficient to find new bitmaps intersecting the stripe, the * list of all bitmaps is always sorted by top, from top to bottom, in * the next_y linked list. The list of bitmaps intersecting the stripe is * merely updated, not recalculated from scratch, when we move the stripe. * So every bitmap gets bubbled to its correct sorted x-position at most * once. Bubbling a bitmap takes at most as many steps as the number of * video bitmaps. So the algorithm behaves at most quadratically with * regard to the number of video bitmaps. I think that a linear behaviour * is more typical in practical applications (this happens, for instance, * if you allocate many bitmaps of the same height). * * There's one more optimization: if a call fails, we cache the size of the * requested bitmap, so that next time we can detect very quickly that this * size is too large (this needs to be maintained when destroying bitmaps). */ BITMAP *create_video_bitmap(int width, int height) { VRAM_BITMAP *active_list, *b, *vram_bitmap; VRAM_BITMAP **last_p; BITMAP *bmp; int x = 0, y = 0; ASSERT(width >= 0); ASSERT(height > 0); if (_dispsw_status) return NULL; /* let the driver handle the request if it can */ if (gfx_driver->create_video_bitmap) { bmp = gfx_driver->create_video_bitmap(width, height); if (!bmp) return NULL; b = _AL_MALLOC(sizeof(VRAM_BITMAP)); b->x = -1; b->y = -1; b->w = 0; b->h = 0; b->bmp = bmp; b->next_y = vram_bitmap_list; vram_bitmap_list = b; return bmp; } /* check bad args */ if ((width > VIRTUAL_W) || (height > VIRTUAL_H) || (width < 0) || (height < 0)) return NULL; /* check cached bitmap size */ if ((width >= failed_bitmap_w) && (height >= failed_bitmap_h)) return NULL; vram_bitmap = vram_bitmap_list; active_list = NULL; y = 0; while (TRUE) { /* Move the blocks from the VRAM_BITMAP_LIST that intersect the * stripe to the ACTIVE_LIST: look through the VRAM_BITMAP_LIST * following the next_y link, grow the ACTIVE_LIST following * the next_x link and sorting by x-position. * (this loop runs in amortized quadratic time) */ while (vram_bitmap && (vram_bitmap->y < y+height)) { /* find sorted x-position */ last_p = &active_list; for (b = active_list; b && (vram_bitmap->x > b->x); b = b->next_x) last_p = &b->next_x; /* insert */ *last_p = vram_bitmap; vram_bitmap->next_x = b; /* next video bitmap */ vram_bitmap = vram_bitmap->next_y; } x = 0; /* Look for holes to put our bitmap in. * (this loop runs in quadratic time) */ for (b = active_list; b; b = b->next_x) { if (x+width <= b->x) /* hole is big enough? */ return add_vram_block(x, y, width, height); /* Move search x-position to the right edge of the * skipped bitmap if we are not already past it. * And check there is enough room before continuing. */ if (x < b->x + b->w) { x = (b->x + b->w + 15) & ~15; if (x+width > VIRTUAL_W) break; } } /* If the whole ACTIVE_LIST was scanned, there is a big * enough hole to the right of the rightmost bitmap. */ if (b == NULL) return add_vram_block(x, y, width, height); /* Move search y-position to the topmost bottom edge * of the bitmaps intersecting the stripe. * (this loop runs in quadratic time) */ y = active_list->y + active_list->h; for (b = active_list->next_x; b; b = b->next_x) { if (y > b->y + b->h) y = b->y + b->h; } if (y+height > VIRTUAL_H) { /* too close to bottom? */ /* Before failing, cache this bitmap size so that later calls can * learn from it. Use area as a measure to sort the bitmap sizes. */ if (width * height < failed_bitmap_w * failed_bitmap_h) { failed_bitmap_w = width; failed_bitmap_h = height; } return NULL; } /* Remove the blocks that don't intersect the new stripe from ACTIVE_LIST. * (this loop runs in quadratic time) */ last_p = &active_list; for (b = active_list; b; b = b->next_x) { if (y >= b->y + b->h) *last_p = b->next_x; else last_p = &b->next_x; } } } /* create_system_bitmap: * Attempts to make a system-specific (eg. DirectX surface) bitmap object. */ BITMAP *create_system_bitmap(int width, int height) { BITMAP *bmp; ASSERT(width >= 0); ASSERT(height > 0); ASSERT(gfx_driver != NULL); if (gfx_driver->create_system_bitmap) return gfx_driver->create_system_bitmap(width, height); bmp = create_bitmap(width, height); return bmp; } /* destroy_bitmap: * Destroys a memory bitmap. */ void destroy_bitmap(BITMAP *bitmap) { VRAM_BITMAP *prev, *pos; if (bitmap) { if (is_video_bitmap(bitmap)) { /* special case for getting rid of video memory bitmaps */ ASSERT(!_dispsw_status); prev = NULL; pos = vram_bitmap_list; while (pos) { if (pos->bmp == bitmap) { if (prev) prev->next_y = pos->next_y; else vram_bitmap_list = pos->next_y; if (pos->x < 0) { /* the driver is in charge of this object */ gfx_driver->destroy_video_bitmap(bitmap); _AL_FREE(pos); return; } /* Update cached bitmap size using worst case scenario: * the bitmap lies between two holes whose size is the cached * size on each axis respectively. */ failed_bitmap_w = failed_bitmap_w * 2 + ((bitmap->w + 15) & ~15); if (failed_bitmap_w > BMP_MAX_SIZE) failed_bitmap_w = BMP_MAX_SIZE; failed_bitmap_h = failed_bitmap_h * 2 + bitmap->h; if (failed_bitmap_h > BMP_MAX_SIZE) failed_bitmap_h = BMP_MAX_SIZE; _AL_FREE(pos); break; } prev = pos; pos = pos->next_y; } _unregister_switch_bitmap(bitmap); } else if (is_system_bitmap(bitmap)) { /* special case for getting rid of system memory bitmaps */ ASSERT(gfx_driver != NULL); if (gfx_driver->destroy_system_bitmap) { gfx_driver->destroy_system_bitmap(bitmap); return; } } /* normal memory or sub-bitmap destruction */ if (system_driver->destroy_bitmap) { if (system_driver->destroy_bitmap(bitmap)) return; } if (bitmap->dat) _AL_FREE(bitmap->dat); _AL_FREE(bitmap); } } /* set_clip_rect: * Sets the two opposite corners of the clipping rectangle to be used when * drawing to the bitmap. Nothing will be drawn to positions outside of this * rectangle. When a new bitmap is created the clipping rectangle will be * set to the full area of the bitmap. */ void set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2) { ASSERT(bitmap); /* internal clipping is inclusive-exclusive */ x2++; y2++; bitmap->cl = CLAMP(0, x1, bitmap->w-1); bitmap->ct = CLAMP(0, y1, bitmap->h-1); bitmap->cr = CLAMP(0, x2, bitmap->w); bitmap->cb = CLAMP(0, y2, bitmap->h); if (bitmap->vtable->set_clip) bitmap->vtable->set_clip(bitmap); } /* add_clip_rect: * Makes the new clipping rectangle the intersection between the given * rectangle and the current one. */ void add_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2) { int cx1, cy1, cx2, cy2; ASSERT(bitmap); get_clip_rect(bitmap, &cx1, &cy1, &cx2, &cy2); x1 = MAX(x1, cx1); y1 = MAX(y1, cy1); x2 = MIN(x2, cx2); y2 = MIN(y2, cy2); set_clip_rect(bitmap, x1, y1, x2, y2); } /* set_clip: * Sets the two opposite corners of the clipping rectangle to be used when * drawing to the bitmap. Nothing will be drawn to positions outside of this * rectangle. When a new bitmap is created the clipping rectangle will be * set to the full area of the bitmap. If x1, y1, x2 and y2 are all zero * clipping will be turned off, which will slightly speed up drawing * operations but will allow memory to be corrupted if you attempt to draw * off the edge of the bitmap. */ void set_clip(BITMAP *bitmap, int x1, int y1, int x2, int y2) { int t; ASSERT(bitmap); if ((!x1) && (!y1) && (!x2) && (!y2)) { set_clip_rect(bitmap, 0, 0, bitmap->w-1, bitmap->h-1); set_clip_state(bitmap, FALSE); return; } if (x2 < x1) { t = x1; x1 = x2; x2 = t; } if (y2 < y1) { t = y1; y1 = y2; y2 = t; } set_clip_rect(bitmap, x1, y1, x2, y2); set_clip_state(bitmap, TRUE); } /* scroll_screen: * Attempts to scroll the hardware screen, returning 0 on success. * Check the VIRTUAL_W and VIRTUAL_H values to see how far the screen * can be scrolled. Note that a lot of VESA drivers can only handle * horizontal scrolling in four pixel increments. */ int scroll_screen(int x, int y) { int ret = 0; int h; /* can driver handle hardware scrolling? */ if ((!gfx_driver->scroll) || (_dispsw_status)) return -1; /* clip x */ if (x < 0) { x = 0; ret = -1; } else if (x > (VIRTUAL_W - SCREEN_W)) { x = VIRTUAL_W - SCREEN_W; ret = -1; } /* clip y */ if (y < 0) { y = 0; ret = -1; } else { h = (_screen_split_position > 0) ? _screen_split_position : SCREEN_H; if (y > (VIRTUAL_H - h)) { y = VIRTUAL_H - h; ret = -1; } } /* scroll! */ if (gfx_driver->scroll(x, y) != 0) ret = -1; return ret; } /* request_scroll: * Attempts to initiate a triple buffered hardware scroll, which will * take place during the next retrace. Returns 0 on success. */ int request_scroll(int x, int y) { int ret = 0; int h; /* can driver handle triple buffering? */ if ((!gfx_driver->request_scroll) || (_dispsw_status)) { scroll_screen(x, y); return -1; } /* clip x */ if (x < 0) { x = 0; ret = -1; } else if (x > (VIRTUAL_W - SCREEN_W)) { x = VIRTUAL_W - SCREEN_W; ret = -1; } /* clip y */ if (y < 0) { y = 0; ret = -1; } else { h = (_screen_split_position > 0) ? _screen_split_position : SCREEN_H; if (y > (VIRTUAL_H - h)) { y = VIRTUAL_H - h; ret = -1; } } /* scroll! */ if (gfx_driver->request_scroll(x, y) != 0) ret = -1; return ret; } /* poll_scroll: * Checks whether a requested triple buffer flip has actually taken place. */ int poll_scroll(void) { if ((!gfx_driver->poll_scroll) || (_dispsw_status)) return FALSE; return gfx_driver->poll_scroll(); } /* show_video_bitmap: * Page flipping function: swaps to display the specified video memory * bitmap object (this must be the same size as the physical screen). */ int show_video_bitmap(BITMAP *bitmap) { if ((!is_video_bitmap(bitmap)) || (bitmap->w != SCREEN_W) || (bitmap->h != SCREEN_H) || (_dispsw_status)) return -1; if (gfx_driver->show_video_bitmap) return gfx_driver->show_video_bitmap(bitmap); return scroll_screen(bitmap->x_ofs, bitmap->y_ofs); } /* request_video_bitmap: * Triple buffering function: triggers a swap to display the specified * video memory bitmap object, which will take place on the next retrace. */ int request_video_bitmap(BITMAP *bitmap) { if ((!is_video_bitmap(bitmap)) || (bitmap->w != SCREEN_W) || (bitmap->h != SCREEN_H) || (_dispsw_status)) return -1; if (gfx_driver->request_video_bitmap) return gfx_driver->request_video_bitmap(bitmap); return request_scroll(bitmap->x_ofs, bitmap->y_ofs); } /* enable_triple_buffer: * Asks a driver to turn on triple buffering mode, if it is capable * of that. */ int enable_triple_buffer(void) { if (gfx_capabilities & GFX_CAN_TRIPLE_BUFFER) return 0; if (_dispsw_status) return -1; if (gfx_driver->enable_triple_buffer) { gfx_driver->enable_triple_buffer(); if ((gfx_driver->request_scroll) || (gfx_driver->request_video_bitmap)) { gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; return 0; } } return -1; } /* get_gfx_mode_type: * Evaluates the type of the graphics driver card * and tells you whether it is a windowed, fullscreen, * definitely windowed or fullscreen, and/or a magic driver. * See gfx.h for the GFX_TYPE_* defines. */ int get_gfx_mode_type(int graphics_card) { int gfx_type = GFX_TYPE_UNKNOWN; _DRIVER_INFO *gfx_driver_info; GFX_DRIVER *gfx_driver_entry; ASSERT(system_driver); /* Ask the system driver for a list of graphics hardware drivers */ if (system_driver->gfx_drivers) { gfx_driver_info = system_driver->gfx_drivers(); } else { gfx_driver_info = _gfx_driver_list; } ASSERT(gfx_driver_info); while (gfx_driver_info->driver) { if (gfx_driver_info->id == graphics_card) { gfx_driver_entry = (GFX_DRIVER*)gfx_driver_info->driver; if (gfx_driver_entry->windowed) { gfx_type |= (GFX_TYPE_WINDOWED | GFX_TYPE_DEFINITE); } else { gfx_type |= (GFX_TYPE_FULLSCREEN | GFX_TYPE_DEFINITE); } break; } gfx_driver_info++; } switch (graphics_card) { case GFX_AUTODETECT: gfx_type |= GFX_TYPE_MAGIC; break; case GFX_AUTODETECT_FULLSCREEN: gfx_type |= (GFX_TYPE_MAGIC | GFX_TYPE_FULLSCREEN | GFX_TYPE_DEFINITE); break; case GFX_AUTODETECT_WINDOWED: gfx_type |= (GFX_TYPE_MAGIC | GFX_TYPE_WINDOWED | GFX_TYPE_DEFINITE); break; case GFX_SAFE: gfx_type |= GFX_TYPE_MAGIC; break; case GFX_TEXT: gfx_type |= GFX_TYPE_MAGIC; break; } return gfx_type; } /* get_gfx_mode: * Tells you which graphics mode is currently set. * Useful for determining the actual driver that * GFX_AUTODETECT* or GFX_SAFE set successfully. */ int get_gfx_mode(void) { if (!gfx_driver) return GFX_NONE; return gfx_driver->id; } allegro-4.4.3.1/src/qnx/0000775000175000017500000000000013437077643013675 5ustar siegesiegeallegro-4.4.3.1/src/qnx/qphaccel.c0000664000175000017500000002557713437077643015641 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX Photon acceleration. * * By Eric Botcazou. * * Based on src/win/wddaccel by Stephan Schimanski and al. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif /* state variables */ static PgColor_t chroma_color; static int chroma_on = FALSE; /* software version pointers */ static void (*_orig_hline) (BITMAP * bmp, int x1, int y, int x2, int color); static void (*_orig_vline) (BITMAP * bmp, int x, int y1, int y2, int color); static void (*_orig_rectfill) (BITMAP * bmp, int x1, int y1, int x2, int y2, int color); static void (*_orig_draw_sprite) (BITMAP * bmp, BITMAP * sprite, int x, int y); static void (*_orig_masked_blit) (BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); /* photon_blit_to_self: * Accelerated vram -> vram blitting routine. */ static void photon_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { struct Ph_rect source_rect = { { source_x + source->x_ofs, source_y + source->y_ofs }, { source_x + source->x_ofs + width - 1, source_y + source->y_ofs + height - 1 } }; struct Ph_rect dest_rect = { { dest_x + dest->x_ofs, dest_y + dest->y_ofs }, { dest_x + dest->x_ofs + width - 1, dest_y + dest->y_ofs + height - 1 } }; struct BITMAP *source_parent, *dest_parent; /* find parents */ source_parent = source; while (source_parent->id & BMP_ID_SUB) source_parent = (BITMAP *)source_parent->extra; dest_parent = dest; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; PgContextBlit(BMP_EXTRA(source_parent)->context, &source_rect, BMP_EXTRA(dest_parent)->context, &dest_rect); /* only for windowed mode */ if (dest_parent == pseudo_screen) ph_update_window(&dest_rect); } /* ddraw_masked_blit: * Accelerated masked blitting routine. */ static void photon_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { struct Ph_rect source_rect = { { source_x + source->x_ofs, source_y + source->y_ofs }, { source_x + source->x_ofs + width - 1, source_y + source->y_ofs + height - 1 } }; struct Ph_rect dest_rect = { { dest_x + dest->x_ofs, dest_y + dest->y_ofs }, { dest_x + dest->x_ofs + width - 1, dest_y + dest->y_ofs + height - 1 } }; struct BITMAP *dest_parent, *source_parent; if (is_video_bitmap(source)) { if (!chroma_on) { PgChromaOn(); chroma_on = TRUE; } /* find parents */ source_parent = source; while (source_parent->id & BMP_ID_SUB) source_parent = (BITMAP *)source_parent->extra; dest_parent = dest; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; PgContextBlit(BMP_EXTRA(source_parent)->context, &source_rect, BMP_EXTRA(dest_parent)->context, &dest_rect); /* only for windowed mode */ if (dest_parent == pseudo_screen) ph_update_window(&dest_rect); } else { /* have to use the original software version */ _orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height); } } /* photon_draw_sprite: * Accelerated sprite drawing routine. */ static void photon_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) { int sx, sy, w, h; if (is_video_bitmap(sprite)) { sx = sprite->x_ofs; sy = sprite->y_ofs; w = sprite->w; h = sprite->h; if (bmp->clip) { if (x < bmp->cl) { sx += bmp->cl - x; w -= bmp->cl - x; x = bmp->cl; } if (y < bmp->ct) { sy += bmp->ct - y; h -= bmp->ct - y; y = bmp->ct; } if (x + w > bmp->cr) w = bmp->cr - x; if (w <= 0) return; if (y + h > bmp->cb) h = bmp->cb - y; if (h <= 0) return; } photon_masked_blit(sprite, bmp, sx, sy, x, y, w, h); } else { /* have to use the original software version */ _orig_draw_sprite(bmp, sprite, x, y); } } /* photon_clear_to_color: * Accelerated screen clear routine. */ static void photon_clear_to_color(BITMAP *bmp, int color) { struct Ph_rect dest_rect = { { bmp->cl + bmp->x_ofs, bmp->ct + bmp->y_ofs }, { bmp->x_ofs + bmp->cr, bmp->y_ofs + bmp->cb } }; struct BITMAP *parent; /* find parent */ parent = bmp; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; /* set fill color */ /* if (bmp->vtable->color_depth == 8) PgSetFillColor(color); else */ PgSetFillColor(PgRGB(getr(color), getg(color), getb(color))); PhDCSetCurrent(BMP_EXTRA(parent)->context); PgDrawRect(&dest_rect, Pg_DRAW_FILL); if (parent == pseudo_screen) ph_update_window(&dest_rect); else PgFlush(); } /* photon_rectfill: * Accelerated rectangle fill routine. */ static void photon_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { struct Ph_rect dest_rect; struct BITMAP *parent; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_rectfill(bmp, x1, y1, x2, y2, color); return; } if (x2 < x1) { int tmp = x1; x1 = x2; x2 = tmp; } if (y2 < y1) { int tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } dest_rect.ul.x = x1 + bmp->x_ofs; dest_rect.ul.y = y1 + bmp->y_ofs; dest_rect.lr.x = x2 + bmp->x_ofs; dest_rect.lr.y = y2 + bmp->y_ofs; /* find parent */ parent = bmp; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; /* set fill color */ /* if (bmp->vtable->color_depth == 8) PgSetFillColor(color); else */ PgSetFillColor(PgRGB(getr(color), getg(color), getb(color))); PhDCSetCurrent(BMP_EXTRA(parent)->context); PgDrawRect(&dest_rect, Pg_DRAW_FILL); if (parent == pseudo_screen) ph_update_window(&dest_rect); else PgFlush(); } /* ddraw_hline: * Accelerated scanline fill routine. */ static void ddraw_hline(BITMAP *bmp, int x1, int y, int x2, int color) { struct Ph_rect dest_rect; struct BITMAP *parent; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_hline(bmp, x1, y, x2, color); return; } if (x1 > x2) { int tmp = x1; x1 = x2; x2 = tmp; } if (bmp->clip) { if ((y < bmp->ct) || (y >= bmp->cb)) return; if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; } dest_rect.ul.x = x1 + bmp->x_ofs; dest_rect.ul.y = y + bmp->y_ofs; dest_rect.lr.x = x2 + bmp->x_ofs; dest_rect.lr.y = y + bmp->y_ofs; /* find parent */ parent = bmp; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; PhDCSetCurrent(BMP_EXTRA(parent)->context); PgDrawLine(&dest_rect.ul, &dest_rect.lr); if (parent == pseudo_screen) ph_update_window(&dest_rect); else PgFlush(); } /* ddraw_vline: * Accelerated vline routine. */ static void ddraw_vline(BITMAP *bmp, int x, int y1, int y2, int color) { struct Ph_rect dest_rect; struct BITMAP *parent; if (_drawing_mode != DRAW_MODE_SOLID) { _orig_vline(bmp, x, y1, y2, color); return; } if (y1 > y2) { int tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if ((x < bmp->cl) || (x >= bmp->cr)) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } dest_rect.ul.x = x + bmp->x_ofs; dest_rect.ul.y = y1 + bmp->y_ofs; dest_rect.lr.x = x + bmp->x_ofs; dest_rect.lr.y = y2 + bmp->y_ofs; /* find parent */ parent = bmp; while (parent->id & BMP_ID_SUB) parent = (BITMAP *)parent->extra; PhDCSetCurrent(BMP_EXTRA(parent)->context); PgDrawLine(&dest_rect.ul, &dest_rect.lr); if (parent == pseudo_screen) ph_update_window(&dest_rect); else PgFlush(); } /* enable_acceleration: * Checks graphic driver for capabilities to accelerate Allegro. */ void enable_acceleration(GFX_DRIVER * drv) { /* safe pointer to software versions */ _orig_hline = _screen_vtable.hline; _orig_vline = _screen_vtable.vline; _orig_rectfill = _screen_vtable.rectfill; _orig_draw_sprite = _screen_vtable.draw_sprite; _orig_masked_blit = _screen_vtable.masked_blit; /* accelerated video to video blits? */ if (ph_gfx_mode_info.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) { _screen_vtable.blit_to_self = photon_blit_to_self; /* overlapping blits seem not to be supported */ #if 0 _screen_vtable.blit_to_self_forward = photon_blit_to_self; _screen_vtable.blit_to_self_backward = photon_blit_to_self; #endif gfx_capabilities |= GFX_HW_VRAM_BLIT; } /* accelerated color fills? */ if (ph_gfx_mode_info.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) { _screen_vtable.clear_to_color = photon_clear_to_color; _screen_vtable.rectfill = photon_rectfill; gfx_capabilities |= GFX_HW_FILL; } /* accelerated lines? */ if (ph_gfx_mode_info.mode_capabilities2 & PgVM_MODE_CAP2_LINES) { _screen_vtable.hline = ddraw_hline; _screen_vtable.vline = ddraw_vline; gfx_capabilities |= GFX_HW_HLINE; } /* accelerated color key blits? */ if (ph_gfx_mode_info.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) { _screen_vtable.masked_blit = photon_masked_blit; _screen_vtable.draw_sprite = photon_draw_sprite; if (_screen_vtable.color_depth == 8) _screen_vtable.draw_256_sprite = photon_draw_sprite; gfx_capabilities |= GFX_HW_VRAM_BLIT_MASKED; } } /* enable_triple_buffering: * Checks graphic driver for triple buffering capability. */ void enable_triple_buffering(GFX_DRIVER *drv) { if (ph_gfx_mode_info.mode_capabilities1 & PgVM_MODE_CAP1_TRIPLE_BUFFER) { /* drv->poll_scroll = qnx_ph_poll_scroll; */ gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; } } allegro-4.4.3.1/src/qnx/qkeydrv.c0000664000175000017500000000511113437077643015524 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX keyboard driver. * * By Angelo Mottola. * * Based on Unix/X11 version by Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif static int qnx_keyboard_init(void); static void qnx_keyboard_exit(void); KEYBOARD_DRIVER keyboard_qnx = { KEYBOARD_QNX, empty_string, empty_string, "QNX keyboard", TRUE, qnx_keyboard_init, qnx_keyboard_exit, NULL, // AL_METHOD(void, poll, (void)); NULL, // AL_METHOD(void, set_leds, (int leds)); NULL, // AL_METHOD(void, set_rate, (int delay, int rate)); NULL, // AL_METHOD(void, wait_for_input, (void)); NULL, // AL_METHOD(void, stop_waiting_for_input, (void)); _pckey_scancode_to_ascii, _pckey_scancode_to_name }; static int main_pid; /* qnx_keyboard_handler: * Keyboard "interrupt" handler. */ void qnx_keyboard_handler(int pressed, int code) { int scancode; /* Handle scancode. */ scancode = (code & 0x7F) | (pressed ? 0x00 : 0x80); _handle_pckey(scancode); /* Exit by Ctrl-Alt-End. */ if (((scancode == 0x4F) || (scancode == 0x53)) && three_finger_flag && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG)) kill(main_pid, SIGTERM); } /* qnx_keyboard_focused: * Keyboard focus change handler. */ void qnx_keyboard_focused(int focused, int state) { int i, mask; if (focused) { mask = KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG; _key_shifts = (_key_shifts & ~mask) | (state & mask); } else { for (i=0; iid & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; PgWaitHWIdle(); } return (unsigned long)(bmp->line[line]); } /* ph_unwrite_line: * Line updater for video bitmaps. */ void ph_unwrite_line(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); } } #endif /* ph_acquire: * Bitmap locking for video bitmaps. */ void ph_acquire(BITMAP *bmp) { if (!(bmp->id & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; PgWaitHWIdle(); } } /* ph_release: * Bitmap unlocking for video bitmaps. */ void ph_release(BITMAP *bmp) { bmp->id &= ~BMP_ID_LOCKED; } /* _make_video_bitmap: * Helper function for wrapping up video memory in a video bitmap. */ static BITMAP *_make_video_bitmap(int w, int h, unsigned long addr, struct GFX_VTABLE *vtable, int bpl) { int i, size; BITMAP *b; if (!vtable) return NULL; size = sizeof(BITMAP) + sizeof(char *) * h; b = (BITMAP *) _AL_MALLOC(size); if (!b) return NULL; b->w = b->cr = w; b->h = b->cb = h; b->clip = TRUE; b->cl = b->ct = 0; b->vtable = vtable; b->write_bank = b->read_bank = _stub_bank_switch; b->dat = NULL; b->id = BMP_ID_VIDEO; b->extra = NULL; b->x_ofs = 0; b->y_ofs = 0; b->seg = _video_ds(); b->line[0] = (char *)addr; for (i = 1; i < h; i++) b->line[i] = b->line[i - 1] + bpl; return b; } /* make_photon_bitmap: * Connects a Photon context with an Allegro bitmap. */ BITMAP *make_photon_bitmap(PdOffscreenContext_t *context, int w, int h, int id) { struct BITMAP *bmp; char *addr; addr = PdGetOffscreenContextPtr(context); if (!addr) return NULL; /* create Allegro bitmap */ bmp = _make_video_bitmap(w, h, (unsigned long)addr, &_screen_vtable, context->pitch); if (!bmp) return NULL; bmp->id = id; #ifdef ALLEGRO_NO_ASM bmp->write_bank = ph_write_line; bmp->read_bank = ph_write_line; #else bmp->write_bank = ph_write_line_asm; bmp->read_bank = ph_write_line_asm; #endif /* setup surface info structure to store additional information */ bmp->extra = _AL_MALLOC(sizeof(struct BMP_EXTRA_INFO)); BMP_EXTRA(bmp)->context = context; return bmp; } /* destroy_photon_bitmap: * Destroys a video bitmap. */ void destroy_photon_bitmap(BITMAP *bmp) { if (bmp) { _AL_FREE(bmp->extra); _AL_FREE(bmp); } } /* qnx_ph_created_sub_bitmap: */ void qnx_ph_created_sub_bitmap(BITMAP *bmp, BITMAP *parent) { bmp->extra = parent; } /* qnx_ph_create_video_bitmap: */ BITMAP *qnx_ph_create_video_bitmap(int width, int height) { PdOffscreenContext_t *context; int flags = Pg_OSC_MEM_PAGE_ALIGN; if ((width == screen->w) && (height == screen->h)) { if (!reused_screen) { reused_screen = TRUE; return screen; } flags |= Pg_OSC_CRTC_SAFE; } context = PdCreateOffscreenContext(0, width, height, flags); if (!context) return NULL; return make_photon_bitmap(context, width, height, BMP_ID_VIDEO); } /* qnx_ph_destroy_video_bitmap: */ void qnx_ph_destroy_video_bitmap(BITMAP *bmp) { if (bmp == screen) { reused_screen = FALSE; return; } if (bmp == ph_frontbuffer) { /* in this case, 'bmp' points to the visible contents * but 'screen' doesn't, so we first invert that */ qnx_ph_show_video_bitmap(screen); } PhDCRelease(BMP_EXTRA(bmp)->context); destroy_photon_bitmap(bmp); } /* swap_video_bitmap: * Worker function for Photon page flipping. */ static int swap_video_bitmap(BITMAP *bmp, int vsync) { if (PgSwapDisplay(BMP_EXTRA(bmp)->context, vsync ? Pg_SWAP_VSYNC : 0) != 0) return -1; PgFlush(); /* ph_frontbuffer must keep track of the forefront bitmap */ ph_frontbuffer = bmp; return 0; } /* qnx_ph_show_video_bitmap: */ int qnx_ph_show_video_bitmap(BITMAP *bmp) { return swap_video_bitmap(bmp, _wait_for_vsync); } /* qnx_ph_request_video_bitmap: */ int qnx_ph_request_video_bitmap(BITMAP *bmp) { return swap_video_bitmap(bmp, FALSE); } allegro-4.4.3.1/src/qnx/qphoton.c0000664000175000017500000000431013437077643015527 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX Photon helper routines. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif /* Photon globals */ int ph_gfx_mode = PH_GFX_NONE; PgVideoModeInfo_t ph_gfx_mode_info; PgColor_t ph_palette[256]; /* setup_direct_shifts * Setups direct color shifts. */ void setup_direct_shifts(void) { _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; _rgb_a_shift_32 = 24; _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; /* set the source color key */ PgSetChroma(MASK_COLOR_32, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW); } /* setup_driver: * Helper function for initializing the gfx driver. */ void setup_driver(GFX_DRIVER *drv, int w, int h, int color_depth) { PgHWCaps_t caps; /* setup the driver structure */ drv->w = w; drv->h = h; drv->linear = TRUE; if (PgGetGraphicsHWCaps(&caps)) drv->vid_mem = w * h * BYTES_PER_PIXEL(color_depth); else drv->vid_mem = caps.total_video_ram; /* modify the vtable to work with video memory */ memcpy(&_screen_vtable, _get_vtable(color_depth), sizeof(GFX_VTABLE)); _screen_vtable.acquire = ph_acquire; _screen_vtable.release = ph_release; #ifdef ALLEGRO_NO_ASM _screen_vtable.unwrite_bank = ph_unwrite_line; #else _screen_vtable.unwrite_bank = ph_unwrite_line_asm; #endif _screen_vtable.created_sub_bitmap = qnx_ph_created_sub_bitmap; } allegro-4.4.3.1/src/qnx/qswitch.s0000664000175000017500000000515013437077643015544 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX asm line switcher routines. * * By Angelo Mottola. * * Window updating system derived from Win32 version by Eric Botcazou. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" .text #ifndef ALLEGRO_NO_ASM /* ph_write_line_asm: * edx = bitmap * eax = line */ FUNC (ph_write_line_asm) /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked /* set lock and autolock flags */ orl $(BMP_ID_LOCKED | BMP_ID_AUTOLOCK), BMP_ID(%edx) pushl %ecx pushl %eax pushl %edx call GLOBL(PgWaitHWIdle) popl %edx popl %eax popl %ecx Locked: /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* ph_unwrite_line_asm: * edx = bmp */ FUNC (ph_unwrite_line_asm) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock /* clear lock and autolock flags */ andl $~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK), BMP_ID(%edx) No_unlock: ret /* ph_write_line_win_asm: * edx = bitmap * eax = line */ FUNC (ph_write_line_win_asm) pushl %ecx /* clobber the line */ movl GLOBL(ph_dirty_lines), %ecx addl BMP_YOFFSET(%edx), %ecx movb $1, (%ecx,%eax) /* ph_dirty_lines[line] = 1; (line has changed) */ /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked_win /* lock the surface */ pushl %eax pushl %edx call *GLOBL(ptr_ph_acquire_win) popl %edx popl %eax /* set the autolock flag */ orl $BMP_ID_AUTOLOCK, BMP_ID(%edx) Locked_win: popl %ecx /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* ph_unwrite_line_win_asm: * edx = bmp */ FUNC (ph_unwrite_line_win_asm) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock_win /* unlock surface */ pushl %ecx pushl %eax pushl %edx call *GLOBL(ptr_ph_release_win) popl %edx popl %eax popl %ecx /* clear the autolock flag */ andl $~BMP_ID_AUTOLOCK, BMP_ID(%edx) No_unlock_win: ret #endif allegro-4.4.3.1/src/qnx/qmouse.c0000664000175000017500000000740313437077643015356 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX mouse driver. * * By Angelo Mottola. * * Based on Unix/X11 version by Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif static int qnx_mouse_init(void); static void qnx_mouse_exit(void); static void qnx_mouse_position(int, int); static void qnx_mouse_set_range(int, int, int, int); static void qnx_mouse_get_mickeys(int *, int *); MOUSE_DRIVER mouse_qnx = { MOUSE_QNX, empty_string, empty_string, "Photon mouse", qnx_mouse_init, qnx_mouse_exit, NULL, // AL_METHOD(void, poll, (void)); NULL, // AL_METHOD(void, timer_poll, (void)); qnx_mouse_position, qnx_mouse_set_range, NULL, // AL_METHOD(void, set_speed, (int xspeed, int yspeed)); qnx_mouse_get_mickeys, NULL, // AL_METHOD(int, analyse_data, (AL_CONST char *buffer, int size)); NULL, // AL_METHOD(void, enable_hardware_cursor, (AL_CONST int mode)); NULL // AL_METHOD(int, select_system_cursor, (AL_CONST int cursor)); }; /* global variable */ int qnx_mouse_warped = FALSE; static int mouse_minx = 0; static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int mymickey_x = 0; static int mymickey_y = 0; /* qnx_mouse_handler: * Mouse "interrupt" handler for mickey-mode driver. */ void qnx_mouse_handler(int x, int y, int z, int buttons) { _mouse_b = buttons; mymickey_x += x; mymickey_y += y; _mouse_x += x; _mouse_y += y; _mouse_z += z; if ((_mouse_x < mouse_minx) || (_mouse_x > mouse_maxx) || (_mouse_y < mouse_miny) || (_mouse_y > mouse_maxy)) { _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); } _handle_mouse_input(); } /* qnx_mouse_init: * Initializes the mickey-mode driver. */ static int qnx_mouse_init(void) { return 3; } /* qnx_mouse_exit: * Shuts down the mickey-mode driver. */ static void qnx_mouse_exit(void) { } /* qnx_mouse_position: * Sets the position of the mickey-mode mouse. */ static void qnx_mouse_position(int x, int y) { short mx = 0, my = 0; pthread_mutex_lock(&qnx_event_mutex); _mouse_x = x; _mouse_y = y; if (ph_gfx_mode == PH_GFX_WINDOW) PtGetAbsPosition(ph_window, &mx, &my); PhMoveCursorAbs(PhInputGroup(NULL), x + mx, y + my); mymickey_x = mymickey_y = 0; qnx_mouse_warped = TRUE; pthread_mutex_unlock(&qnx_event_mutex); } /* qnx_mouse_set_range: * Sets the range of the mickey-mode mouse. */ static void qnx_mouse_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; pthread_mutex_lock(&qnx_event_mutex); _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); pthread_mutex_unlock(&qnx_event_mutex); } /* qnx_mouse_get_mickeys: * Reads the mickey-mode count. */ static void qnx_mouse_get_mickeys(int *mickeyx, int *mickeyy) { int temp_x = mymickey_x; int temp_y = mymickey_y; mymickey_x -= temp_x; mymickey_y -= temp_y; *mickeyx = temp_x; *mickeyy = temp_y; } allegro-4.4.3.1/src/qnx/qdrivers.c0000664000175000017500000000345513437077643015707 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of QNX drivers. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif _DRIVER_INFO _keyboard_driver_list[] = { { KEYBOARD_QNX, &keyboard_qnx, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _timer_driver_list[] = { { TIMERDRV_UNIX_PTHREADS, &timerdrv_unix_pthreads, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _mouse_driver_list[] = { { MOUSE_QNX, &mouse_qnx, TRUE }, { 0, NULL, 0 } }; BEGIN_GFX_DRIVER_LIST { GFX_PHOTON_ACCEL, &gfx_photon_accel, TRUE }, { GFX_PHOTON_SOFT, &gfx_photon_soft, TRUE }, { GFX_PHOTON_SAFE, &gfx_photon_safe, TRUE }, { GFX_PHOTON_WIN, &gfx_photon_win, TRUE }, END_GFX_DRIVER_LIST BEGIN_DIGI_DRIVER_LIST { DIGI_ALSA, &digi_alsa, TRUE }, END_DIGI_DRIVER_LIST BEGIN_MIDI_DRIVER_LIST { MIDI_ALSA, &midi_alsa, TRUE }, { MIDI_DIGMID, &midi_digmid, TRUE }, END_MIDI_DRIVER_LIST BEGIN_JOYSTICK_DRIVER_LIST END_JOYSTICK_DRIVER_LIST allegro-4.4.3.1/src/qnx/qsystem.c0000664000175000017500000004053013437077643015550 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * System driver for the QNX realtime platform. * * By Angelo Mottola. * * Signals handling derived from Unix version by Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error something is wrong with the makefile #endif #ifndef SCAN_DEPEND #include #include #include #include #include #include #endif static int qnx_sys_init(void); static void qnx_sys_exit(void); static void qnx_sys_message(AL_CONST char *); static void qnx_sys_set_window_title(AL_CONST char *); static int qnx_sys_set_close_button_callback(void (*proc)(void)); static int qnx_sys_set_display_switch_mode(int mode); static void qnx_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); static void qnx_sys_yield_timeslice(void); static int qnx_sys_desktop_color_depth(void); static int qnx_sys_get_desktop_resolution(int *width, int *height); SYSTEM_DRIVER system_qnx = { SYSTEM_QNX, empty_string, empty_string, "QNX Realtime Platform", qnx_sys_init, qnx_sys_exit, _unix_get_executable_name, _unix_find_resource, qnx_sys_set_window_title, qnx_sys_set_close_button_callback, qnx_sys_message, NULL, /* AL_METHOD(void, assert, (AL_CONST char *msg)); */ NULL, /* AL_METHOD(void, save_console_state, (void)); */ NULL, /* AL_METHOD(void, restore_console_state, (void)); */ NULL, /* AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); */ NULL, /* AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); */ NULL, /* AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); */ NULL, /* AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); */ NULL, /* AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(void, read_hardware_palette, (void)); */ NULL, /* AL_METHOD(void, set_palette_range, (AL_CONST struct RGB *p, int from, int to, int retracesync)); */ NULL, /* AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); */ qnx_sys_set_display_switch_mode, NULL, /* AL_METHOD(void, display_switch_lock, (int lock, int foreground)); */ qnx_sys_desktop_color_depth, qnx_sys_get_desktop_resolution, qnx_sys_get_gfx_safe_mode, qnx_sys_yield_timeslice, _unix_create_mutex, _unix_destroy_mutex, _unix_lock_mutex, _unix_unlock_mutex, NULL, /* AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); */ }; /* system globals */ PtWidget_t *ph_window = NULL; pthread_mutex_t qnx_event_mutex; pthread_mutex_t qnx_gfx_mutex; #define EVENT_SIZE (sizeof(PhEvent_t) + 1000) static PhEvent_t *ph_event = NULL; static void (*window_close_hook)(void) = NULL; static int switch_mode = SWITCH_BACKGROUND; #define WINDOW_TITLE_SIZE 256 static char window_title[WINDOW_TITLE_SIZE]; typedef void RETSIGTYPE; static RETSIGTYPE (*old_sig_abrt)(int num); static RETSIGTYPE (*old_sig_fpe)(int num); static RETSIGTYPE (*old_sig_ill)(int num); static RETSIGTYPE (*old_sig_segv)(int num); static RETSIGTYPE (*old_sig_term)(int num); static RETSIGTYPE (*old_sig_int)(int num); #ifdef SIGQUIT static RETSIGTYPE (*old_sig_quit)(int num); #endif /* qnx_signal_handler: * Used to trap various signals, to make sure things get shut down cleanly. */ static RETSIGTYPE qnx_signal_handler(int num) { if (_unix_bg_man->interrupts_disabled()) { /* Can not shutdown X-Windows, restore old signal handlers and slam the door. */ signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); #ifdef SIGQUIT signal(SIGQUIT, old_sig_quit); #endif raise(num); abort(); } else { allegro_exit(); fprintf(stderr, "Shutting down Allegro due to signal #%d\n", num); raise(num); } } /* qnx_event_handler: * Thread to handle pending system events. */ static void qnx_event_handler(int threaded) { static PhRegion_t region; static PhWindowEvent_t *window_event; static PhKeyEvent_t *key_event; static PhPointerEvent_t *mouse_event; static PhCursorInfo_t cursor_info; static int old_x = 0, old_y = 0, ig, dx, dy, buttons = 0, res, i; static short mx, my; pthread_mutex_lock(&qnx_event_mutex); /* special mouse handling for the fullscreen mode */ if (_mouse_installed && (ph_gfx_mode == PH_GFX_DIRECT)) { PtGetAbsPosition(ph_window, &mx, &my); ig = PhInputGroup(NULL); PhQueryCursor(ig, &cursor_info); dx = cursor_info.pos.x - (mx + (SCREEN_W / 2)); dy = cursor_info.pos.y - (my + (SCREEN_H / 2)); if (qnx_mouse_warped) { dx = dy = 0; qnx_mouse_warped = FALSE; } buttons = (cursor_info.button_state & Ph_BUTTON_SELECT ? 0x1 : 0) | (cursor_info.button_state & Ph_BUTTON_MENU ? 0x2 : 0) | (cursor_info.button_state & Ph_BUTTON_ADJUST ? 0x4 : 0); qnx_mouse_handler(dx, dy, 0, buttons); if (dx || dy) PhMoveCursorAbs(ig, mx + (SCREEN_W / 2), my + (SCREEN_H / 2)); } /* check if there is a pending event */ if (PhEventPeek(ph_event, EVENT_SIZE) != Ph_EVENT_MSG) { pthread_mutex_unlock(&qnx_event_mutex); return; } switch(ph_event->type) { /* mouse related events */ case Ph_EV_PTR_MOTION_BUTTON: case Ph_EV_PTR_MOTION_NOBUTTON: case Ph_EV_BUT_PRESS: case Ph_EV_BUT_RELEASE: /* only if we are in windowed mode */ if (_mouse_installed && (ph_gfx_mode == PH_GFX_WINDOW)) { mouse_event = (PhPointerEvent_t *)PhGetData(ph_event); if (qnx_mouse_warped) { dx = 0; dy = 0; qnx_mouse_warped = FALSE; } else { dx = mouse_event->pos.x - old_x; dy = mouse_event->pos.y - old_y; } buttons = (mouse_event->button_state & Ph_BUTTON_SELECT ? 0x1 : 0) | (mouse_event->button_state & Ph_BUTTON_MENU ? 0x2 : 0) | (mouse_event->button_state & Ph_BUTTON_ADJUST ? 0x4 : 0); qnx_mouse_handler(dx, dy, 0, buttons); old_x = mouse_event->pos.x; old_y = mouse_event->pos.y; } break; /* key press/release event */ case Ph_EV_KEY: if (_keyboard_installed) { key_event = (PhKeyEvent_t *)PhGetData(ph_event); /* here we assume key_scan member to be always valid */ if (key_event->key_flags & Pk_KF_Key_Down) qnx_keyboard_handler(TRUE, key_event->key_scan); else qnx_keyboard_handler(FALSE, key_event->key_scan); } break; /* expose event */ case Ph_EV_EXPOSE: if (ph_gfx_mode == PH_GFX_WINDOW) { ph_update_window(NULL); PgFlush(); } break; /* mouse enters/leaves window boundaries */ case Ph_EV_BOUNDARY: /* only if we are in windowed mode */ if (_mouse_installed && (ph_gfx_mode == PH_GFX_WINDOW)) { switch (ph_event->subtype) { case Ph_EV_PTR_ENTER: PhQueryCursor(PhInputGroup(NULL), &cursor_info); PtGetAbsPosition(ph_window, &mx, &my); old_x = cursor_info.pos.x; old_y = cursor_info.pos.y; _mouse_x = old_x - mx; _mouse_y = old_y - my; _handle_mouse_input(); _mouse_on = TRUE; break; case Ph_EV_PTR_LEAVE: _mouse_on = FALSE; _handle_mouse_input(); break; } } break; case Ph_EV_WM: if ((ph_gfx_mode != PH_GFX_NONE) && (ph_event->subtype == Ph_EV_WM_EVENT)) { window_event = (PhWindowEvent_t *)PhGetData(ph_event); switch (window_event->event_f) { case Ph_WM_CLOSE: if (window_close_hook) window_close_hook(); break; case Ph_WM_FOCUS: pthread_mutex_lock(&qnx_gfx_mutex); if (window_event->event_state == Ph_WM_EVSTATE_FOCUS) { qnx_keyboard_focused(TRUE, 0); PgSetPalette(ph_palette, 0, 0, 256, Pg_PALSET_HARDLOCKED, 0); _switch_in(); qnx_mouse_warped = TRUE; } else if (window_event->event_state == Ph_WM_EVSTATE_FOCUSLOST) { qnx_keyboard_focused(FALSE, 0); _switch_out(); PgSetPalette(ph_palette, 0, 0, -1, 0, 0); } pthread_mutex_unlock(&qnx_gfx_mutex); if (ph_gfx_mode == PH_GFX_WINDOW) { ph_update_window(NULL); PgFlush(); } break; } /* end of switch (window_event->event_f) */ } break; case Ph_EV_INFO: /* * TODO: validate offscreen contexts */ break; } pthread_mutex_unlock(&qnx_event_mutex); } /* qnx_sys_init: * Initializes the QNX system driver. */ static int qnx_sys_init(void) { PhRegion_t region; PtArg_t arg[6]; PhDim_t dim; struct sched_param sparam; int spolicy; char tmp[WINDOW_TITLE_SIZE]; /* install emergency-exit signal handlers */ old_sig_abrt = signal(SIGABRT, qnx_signal_handler); old_sig_fpe = signal(SIGFPE, qnx_signal_handler); old_sig_ill = signal(SIGILL, qnx_signal_handler); old_sig_segv = signal(SIGSEGV, qnx_signal_handler); old_sig_term = signal(SIGTERM, qnx_signal_handler); old_sig_int = signal(SIGINT, qnx_signal_handler); #ifdef SIGQUIT old_sig_quit = signal(SIGQUIT, qnx_signal_handler); #endif dim.w = 1; dim.h = 1; _unix_get_executable_name(tmp, WINDOW_TITLE_SIZE); do_uconvert(tmp, U_CURRENT, window_title, U_UTF8, WINDOW_TITLE_SIZE); PtSetArg(&arg[0], Pt_ARG_DIM, &dim, 0); PtSetArg(&arg[1], Pt_ARG_WINDOW_TITLE, window_title, 0); PtSetArg(&arg[2], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE); PtSetArg(&arg[3], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_CLOSE | Ph_WM_FOCUS); PtSetArg(&arg[4], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Ph_WM_RENDER_MAX | Ph_WM_RENDER_RESIZE); ph_event = (PhEvent_t *)_AL_MALLOC(EVENT_SIZE); if (!(ph_window = PtAppInit(NULL, NULL, NULL, 5, arg))) { qnx_sys_exit(); return -1; } PgSetRegion(PtWidgetRid(ph_window)); PgSetClipping(0, NULL); PgSetDrawBufferSize(0xffff); PtRealizeWidget(ph_window); region.cursor_type = Ph_CURSOR_NONE; region.events_sense = Ph_EV_WM | Ph_EV_KEY | Ph_EV_PTR_ALL | Ph_EV_EXPOSE | Ph_EV_BOUNDARY | Ph_EV_INFO; region.rid = PtWidgetRid(ph_window); PhRegionChange(Ph_REGION_CURSOR | Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL); ph_gfx_mode = PH_GFX_NONE; pthread_mutex_init(&qnx_event_mutex, NULL); pthread_mutex_init(&qnx_gfx_mutex, NULL); _unix_bg_man = &_bg_man_pthreads; if (_unix_bg_man->init()) { qnx_sys_exit(); return -1; } _unix_bg_man->register_func(qnx_event_handler); /* Note on the thread scheduling policy: (hot topic under QNX !) * - the primary thread has the lowest priority: -2 * - the _unix_bg_man thread has an intermediate priority: 0 * - the timer thread has the highest priority: +2 */ if (pthread_getschedparam(pthread_self(), &spolicy, &sparam) == EOK) { sparam.sched_priority -= 2; pthread_setschedparam(pthread_self(), spolicy, &sparam); } _unix_read_os_type(); set_display_switch_mode(SWITCH_BACKGROUND); return 0; } /* qnx_sys_exit: * Shuts down the QNX system driver. */ static void qnx_sys_exit(void) { void *status; _unix_bg_man->exit(); signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); #ifdef SIGQUIT signal(SIGQUIT, old_sig_quit); #endif pthread_mutex_destroy(&qnx_event_mutex); pthread_mutex_destroy(&qnx_gfx_mutex); PtUnrealizeWidget(ph_window); if (ph_event) { _AL_FREE(ph_event); ph_event = NULL; } } /* qnx_sys_set_window_title: * Sets the Photon window title. */ static void qnx_sys_set_window_title(AL_CONST char *name) { PtArg_t arg; do_uconvert(name, U_CURRENT, window_title, U_UTF8, WINDOW_TITLE_SIZE); PtSetArg(&arg, Pt_ARG_WINDOW_TITLE, window_title, 0); PtSetResources(ph_window, 1, &arg); } /* qnx_sys_set_close_button_callback: * Sets the close button callback function. */ static int qnx_sys_set_close_button_callback(void (*proc)(void)) { window_close_hook = proc; PtSetResource(ph_window, Pt_ARG_WINDOW_RENDER_FLAGS, (proc ? Pt_TRUE : Pt_FALSE), Ph_WM_RENDER_CLOSE); return 0; } /* qnx_sys_message: * Prints out a message using a system message box. */ static void qnx_sys_message(AL_CONST char *msg) { const char *button[] = { "&Ok" }; char *tmp=_AL_MALLOC(ALLEGRO_MESSAGE_SIZE); fputs(uconvert_toascii(msg, tmp), stderr); qnx_keyboard_focused(FALSE, 0); pthread_mutex_lock(&qnx_event_mutex); DISABLE(); PtAlert(ph_window, NULL, window_title, NULL, uconvert(msg, U_CURRENT, tmp, U_UTF8, ALLEGRO_MESSAGE_SIZE), NULL, 1, button, NULL, 1, 1, Pt_MODAL); ENABLE(); pthread_mutex_unlock(&qnx_event_mutex); qnx_keyboard_focused(TRUE, 0); _AL_FREE(tmp); } /* qnx_sys_set_display_switch_mode: * Sets current display switching behaviour. */ static int qnx_sys_set_display_switch_mode (int mode) { if (mode != SWITCH_BACKGROUND) return -1; switch_mode = mode; return 0; } /* qnx_sys_desktop_color_depth: * Returns the current desktop color depth. */ static int qnx_sys_desktop_color_depth(void) { PgDisplaySettings_t settings; PgVideoModeInfo_t mode_info; PgGetVideoMode(&settings); PgGetVideoModeInfo(settings.mode, &mode_info); return (mode_info.bits_per_pixel); } /* qnx_sys_get_desktop_resolution: * Returns the current desktop resolution. */ static int qnx_sys_get_desktop_resolution(int *width, int *height) { PgDisplaySettings_t settings; PgVideoModeInfo_t mode_info; PgGetVideoMode(&settings); PgGetVideoModeInfo(settings.mode, &mode_info); *width = mode_info.width; *height = mode_info.height; return 0; } /* qnx_sys_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void qnx_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_PHOTON_WIN; mode->width = 320; mode->height = 200; mode->bpp = 8; } /* qnx_sys_yield_timeslice: * Gives some CPU time to other apps to play nice with multitasking. */ static void qnx_sys_yield_timeslice(void) { usleep(0); } /* qnx_get_window: * Returns a handle to the window. */ PtWidget_t *qnx_get_window(void) { return ph_window; } allegro-4.4.3.1/src/qnx/qphfull.c0000664000175000017500000004067013437077643015523 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX Photon fullscreen gfx drivers. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif #include static BITMAP *qnx_ph_init_accel(int, int, int, int, int); static BITMAP *qnx_ph_init_soft(int, int, int, int, int); static BITMAP *qnx_ph_init_safe(int, int, int, int, int); static GFX_MODE_LIST *qnx_ph_fetch_mode_list_accel(void); static GFX_MODE_LIST *qnx_ph_fetch_mode_list_soft(void); static GFX_MODE_LIST *qnx_ph_fetch_mode_list_safe(void); static void qnx_ph_exit(BITMAP *); static void qnx_ph_vsync(void); static void qnx_ph_set_palette(AL_CONST struct RGB *, int, int, int); /* requested capabilities for the drivers */ #define CAPS_ACCEL (PgVM_MODE_CAP1_LINEAR | PgVM_MODE_CAP1_OFFSCREEN | \ PgVM_MODE_CAP1_DOUBLE_BUFFER | PgVM_MODE_CAP1_2D_ACCEL) #define CAPS_SOFT (PgVM_MODE_CAP1_LINEAR | PgVM_MODE_CAP1_OFFSCREEN | \ PgVM_MODE_CAP1_DOUBLE_BUFFER) #define CAPS_SAFE (PgVM_MODE_CAP1_LINEAR) GFX_DRIVER gfx_photon_accel = { GFX_PHOTON_ACCEL, empty_string, empty_string, "Photon accelerated", qnx_ph_init_accel, qnx_ph_exit, NULL, /* AL_METHOD(int, scroll, (int x, int y)); */ qnx_ph_vsync, qnx_ph_set_palette, NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ qnx_ph_create_video_bitmap, qnx_ph_destroy_video_bitmap, qnx_ph_show_video_bitmap, qnx_ph_request_video_bitmap, NULL, /* AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); */ NULL, /* AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); */ NULL, /* AL_METHOD(void, hide_mouse, (void)); */ NULL, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ qnx_ph_fetch_mode_list_accel, 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ FALSE }; GFX_DRIVER gfx_photon_soft = { GFX_PHOTON_SOFT, empty_string, empty_string, "Photon soft", qnx_ph_init_soft, qnx_ph_exit, NULL, /* AL_METHOD(int, scroll, (int x, int y)); */ qnx_ph_vsync, qnx_ph_set_palette, NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ qnx_ph_create_video_bitmap, qnx_ph_destroy_video_bitmap, qnx_ph_show_video_bitmap, qnx_ph_request_video_bitmap, NULL, /* AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); */ NULL, /* AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); */ NULL, /* AL_METHOD(void, hide_mouse, (void)); */ NULL, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ qnx_ph_fetch_mode_list_soft, 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ FALSE }; GFX_DRIVER gfx_photon_safe = { GFX_PHOTON_SAFE, empty_string, empty_string, "Photon safe", qnx_ph_init_safe, qnx_ph_exit, NULL, /* AL_METHOD(int, scroll, (int x, int y)); */ qnx_ph_vsync, qnx_ph_set_palette, NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ NULL, /* AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); */ NULL, /* AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); */ NULL, /* AL_METHOD(void, hide_mouse, (void)); */ NULL, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ qnx_ph_fetch_mode_list_safe, 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ FALSE }; static PdDirectContext_t *ph_direct_context = NULL; static PdOffscreenContext_t *ph_screen_context = NULL; static char driver_desc[256]; static PgDisplaySettings_t original_settings; /* find_video_mode: * Scans the list of available video modes and returns the index of a * suitable mode, -1 on failure. */ static int find_video_mode(int w, int h, int depth, unsigned int flags) { PgVideoModes_t mode_list; PgVideoModeInfo_t mode_info; int i; if (PgGetVideoModeList(&mode_list)) return -1; for (i=0; imode = _AL_MALLOC(sizeof(GFX_MODE) * (ph_mode_list.num_modes + 1)); if (!mode_list->mode) { _AL_FREE(mode_list); return NULL; } for (i=0; imode[count].width = ph_mode_info.width; mode_list->mode[count].height = ph_mode_info.height; mode_list->mode[count].bpp = ph_mode_info.bits_per_pixel; count++; } } mode_list->mode[count].width = 0; mode_list->mode[count].height = 0; mode_list->mode[count].bpp = 0; mode_list->num_modes = count; return mode_list; } /* qnx_private_ph_init: * Real screen initialization runs here. */ static BITMAP *qnx_private_ph_init(GFX_DRIVER *drv, int w, int h, int v_w, int v_h, int color_depth, int flags) { static int first = 1; PhDim_t dim; PtArg_t arg; PgHWCaps_t caps; PgDisplaySettings_t settings; int mode_num; char tmp1[128], tmp2[128]; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (color_depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((w == 0) && (h == 0)) { w = 640; h = 480; } if (v_w < w) v_w = w; if (v_h < h) v_h = h; if ((v_w != w) || (v_h != h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } dim.w = w; dim.h = h; PtSetArg(&arg, Pt_ARG_DIM, &dim, 0); PtSetResources(ph_window, 1, &arg); if (first) { PgGetVideoMode(&original_settings); first = 0; } mode_num = find_video_mode(w, h, color_depth, flags); if (mode_num == -1) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } /* retrieve infos for the selected mode */ PgGetVideoModeInfo(mode_num, &ph_gfx_mode_info); /* set the selected mode */ settings.mode = mode_num; settings.refresh = _refresh_rate_request; settings.flags = 0; if (PgSetVideoMode(&settings)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } PgGetVideoMode(&settings); _set_current_refresh_rate(settings.refresh); if (!(ph_direct_context = PdCreateDirectContext())) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot create direct context")); PgSetVideoMode(&original_settings); return NULL; } if (!PdDirectStart(ph_direct_context)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot start direct context")); return NULL; } if (!(ph_screen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot access the framebuffer")); return NULL; } ph_frontbuffer = make_photon_bitmap(ph_screen_context, w, h, BMP_ID_VIDEO); if (!ph_frontbuffer) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot access the framebuffer")); return NULL; } setup_driver(drv, w, h, color_depth); setup_direct_shifts(); PgGetGraphicsHWCaps(&caps); uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("Photon direct (%s)", tmp1), uconvert(caps.chip_name, U_UTF8, tmp2, U_CURRENT, sizeof(tmp2))); drv->desc = driver_desc; _mouse_on = TRUE; PgFlush(); PgWaitHWIdle(); return ph_frontbuffer; } /* qnx_private_ph_exit: * This is where the video driver is actually closed. */ static void qnx_private_ph_exit(BITMAP *bmp) { PhDim_t dim; if (bmp) clear_bitmap(bmp); ph_gfx_mode = PH_GFX_NONE; if (ph_screen_context) { PhDCRelease(ph_screen_context); ph_screen_context = NULL; } if (bmp) _AL_FREE(bmp->extra); if (ph_direct_context) { PdReleaseDirectContext(ph_direct_context); ph_direct_context = NULL; PgFlush(); PgSetVideoMode(&original_settings); } dim.w = 1; dim.h = 1; PtSetResource(ph_window, Pt_ARG_DIM, &dim, 0); } /* qnx_ph_init_accel: * Initializes the accelerated fullscreen Photon gfx driver. */ static BITMAP *qnx_ph_init_accel(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; pthread_mutex_lock(&qnx_event_mutex); ph_gfx_mode = PH_GFX_DIRECT; bmp = qnx_private_ph_init(&gfx_photon_accel, w, h, v_w, v_h, color_depth, CAPS_ACCEL); if (bmp) { enable_acceleration(&gfx_photon_accel); enable_triple_buffering(&gfx_photon_accel); } else { qnx_private_ph_exit(NULL); } pthread_mutex_unlock(&qnx_event_mutex); return bmp; } /* qnx_ph_init_soft: * Initializes the soft fullscreen Photon gfx driver. */ static BITMAP *qnx_ph_init_soft(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; pthread_mutex_lock(&qnx_event_mutex); ph_gfx_mode = PH_GFX_DIRECT; bmp = qnx_private_ph_init(&gfx_photon_soft, w, h, v_w, v_h, color_depth, CAPS_SOFT); if (bmp) { enable_triple_buffering(&gfx_photon_soft); } else { qnx_private_ph_exit(NULL); } pthread_mutex_unlock(&qnx_event_mutex); return bmp; } /* qnx_ph_init_safe: * Initializes the safe fullscreen Photon gfx driver. */ static BITMAP *qnx_ph_init_safe(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; pthread_mutex_lock(&qnx_event_mutex); ph_gfx_mode = PH_GFX_DIRECT; bmp = qnx_private_ph_init(&gfx_photon_safe, w, h, v_w, v_h, color_depth, CAPS_SAFE); if (!bmp) qnx_private_ph_exit(NULL); pthread_mutex_unlock(&qnx_event_mutex); return bmp; } /* qnx_ph_exit: * Shuts down photon direct driver. */ static void qnx_ph_exit(BITMAP *bmp) { pthread_mutex_lock(&qnx_event_mutex); qnx_private_ph_exit(bmp); pthread_mutex_unlock(&qnx_event_mutex); } /* qnx_ph_fetch_mode_list_accel: */ static GFX_MODE_LIST *qnx_ph_fetch_mode_list_accel(void) { return qnx_ph_fetch_mode_list(CAPS_ACCEL); } /* qnx_ph_fetch_mode_list_soft: */ static GFX_MODE_LIST *qnx_ph_fetch_mode_list_soft(void) { return qnx_ph_fetch_mode_list(CAPS_SOFT); } /* qnx_ph_fetch_mode_list_safe: */ static GFX_MODE_LIST *qnx_ph_fetch_mode_list_safe(void) { return qnx_ph_fetch_mode_list(CAPS_SAFE); } /* qnx_ph_vsync: * Waits for vertical retrace. */ static void qnx_ph_vsync(void) { PgWaitVSync(); } /* qnx_ph_set_palette: * Sets hardware palette. */ static void qnx_ph_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { int i; for (i=from; i<=to; i++) ph_palette[i] = (p[i].r << 18) | (p[i].g << 10) | (p[i].b << 2); if (vsync) PgWaitVSync(); PgSetPalette(ph_palette, 0, from, to - from + 1, Pg_PALSET_HARDLOCKED, 0); PgFlush(); } allegro-4.4.3.1/src/qnx/qphwin.c0000664000175000017500000004404413437077643015355 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX Photon windowed gfx driver. * * By Angelo Mottola. * * Dirty rectangles mechanism by Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif #include static BITMAP *qnx_ph_init_win(int, int, int, int, int); static void qnx_ph_exit_win(BITMAP *); static void qnx_ph_vsync_win(void); static void qnx_ph_set_palette_win(AL_CONST struct RGB *, int, int, int); static BITMAP *qnx_ph_create_video_bitmap_win(int width, int height); static void qnx_ph_destroy_video_bitmap_win(BITMAP *bmp); static int qnx_ph_show_video_bitmap_win(BITMAP *bmp); GFX_DRIVER gfx_photon_win = { GFX_PHOTON, empty_string, empty_string, "Photon windowed", qnx_ph_init_win, qnx_ph_exit_win, NULL, /* AL_METHOD(int, scroll, (int x, int y)); */ qnx_ph_vsync_win, qnx_ph_set_palette_win, NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ qnx_ph_create_video_bitmap_win, qnx_ph_destroy_video_bitmap_win, qnx_ph_show_video_bitmap_win, NULL, /* AL_METHOD(int, request_video_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(BITMAP *, create_system_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_system_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, set_mouse_sprite, (BITMAP *sprite, int xfocus, int yfocus)); */ NULL, /* AL_METHOD(int, show_mouse, (BITMAP *bmp, int x, int y)); */ NULL, /* AL_METHOD(void, hide_mouse, (void)); */ NULL, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ NULL, /* AL_METHOD(int, fetch_mode_list, (void)); */ 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ TRUE }; /* global variables */ BITMAP *pseudo_screen = NULL; void (*ph_update_window)(PhRect_t* rect) = NULL; /* exported only for qswitch.s */ char *ph_dirty_lines = NULL; static PdOffscreenContext_t *ph_window_context = NULL; static pthread_cond_t vsync_cond; static pthread_mutex_t ph_screen_lock; static int lock_nesting = 0; static char driver_desc[256]; static COLORCONV_BLITTER_FUNC *colorconv_blitter = NULL; static char *pseudo_screen_addr = NULL; static int pseudo_screen_pitch; static int pseudo_screen_depth; static char *window_addr = NULL; static int window_pitch; static int desktop_depth; static GFX_VTABLE _special_vtable; /* special vtable for offscreen bitmap */ static int reused_screen = FALSE; #define RENDER_DELAY (1000/70) /* 70 Hz */ static void update_dirty_lines(void); static void ph_acquire_win(BITMAP *bmp); static void ph_release_win(BITMAP *bmp); #ifdef ALLEGRO_NO_ASM static unsigned long ph_write_line_win(BITMAP *bmp, int line); static void ph_unwrite_line_win(BITMAP *bmp); #else void (*ptr_ph_acquire_win)(BITMAP *) = &ph_acquire_win; void (*ptr_ph_release_win)(BITMAP *) = &ph_release_win; unsigned long ph_write_line_win_asm(BITMAP *bmp, int line); void ph_unwrite_line_win_asm(BITMAP *bmp); #endif /* ph_acquire_win: * Bitmap locking for Photon windowed mode. */ static void ph_acquire_win(BITMAP *bmp) { /* to prevent the drawing threads and the rendering proc from concurrently accessing the dirty lines array */ pthread_mutex_lock(&ph_screen_lock); PgWaitHWIdle(); lock_nesting++; bmp->id |= BMP_ID_LOCKED; } /* ph_release_win: * Bitmap unlocking for Photon windowed mode. */ static void ph_release_win(BITMAP *bmp) { if (lock_nesting > 0) { lock_nesting--; if (!lock_nesting) bmp->id &= ~BMP_ID_LOCKED; pthread_mutex_unlock(&ph_screen_lock); } } #ifdef ALLEGRO_NO_ASM /* ph_write_line_win: * Line switcher for Photon windowed mode. */ static unsigned long ph_write_line_win(BITMAP *bmp, int line) { ph_dirty_lines[line + bmp->y_ofs] = 1; if (!(bmp->id & BMP_ID_LOCKED)) { ph_acquire(bmp); bmp->id |= BMP_ID_AUTOLOCK; } return (unsigned long)(bmp->line[line]); } /* ph_unwrite_line_win: * Line updater for Photon windowed mode. */ static void ph_unwrite_line_win(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { ph_release(bmp); bmp->id &= ~BMP_ID_AUTOLOCK; } } #endif /* update_window_hw: * Window updater for matching color depths. */ static void update_window_hw(PhRect_t *rect) { PhRect_t temp; if (!rect) { temp.ul.x = 0; temp.ul.y = 0; temp.lr.x = gfx_photon_win.w; temp.lr.y = gfx_photon_win.h; rect = &temp; } pthread_mutex_lock(&qnx_gfx_mutex); PgContextBlit(BMP_EXTRA(pseudo_screen)->context, rect, NULL, rect); pthread_mutex_unlock(&qnx_gfx_mutex); } /* update_window: * Window updater for non matching color depths, performing color conversion. */ static void update_window(PhRect_t *rect) { struct GRAPHICS_RECT src_gfx_rect, dest_gfx_rect; PhRect_t temp; if (!rect) { temp.ul.x = 0; temp.ul.y = 0; temp.lr.x = gfx_photon_win.w; temp.lr.y = gfx_photon_win.h; rect = &temp; } /* fill in source graphics rectangle description */ src_gfx_rect.width = rect->lr.x - rect->ul.x; src_gfx_rect.height = rect->lr.y - rect->ul.y; src_gfx_rect.pitch = pseudo_screen_pitch; src_gfx_rect.data = pseudo_screen->line[0] + (rect->ul.y * pseudo_screen_pitch) + (rect->ul.x * BYTES_PER_PIXEL(pseudo_screen_depth)); /* fill in destination graphics rectangle description */ dest_gfx_rect.pitch = window_pitch; dest_gfx_rect.data = window_addr + (rect->ul.y * window_pitch) + (rect->ul.x * BYTES_PER_PIXEL(desktop_depth)); /* function doing the hard work */ colorconv_blitter(&src_gfx_rect, &dest_gfx_rect); pthread_mutex_lock(&qnx_gfx_mutex); PgContextBlit(ph_window_context, rect, NULL, rect); pthread_mutex_unlock(&qnx_gfx_mutex); } /* qnx_private_ph_init_win: * Real screen initialization runs here. */ static BITMAP *qnx_private_ph_init_win(GFX_DRIVER *drv, int w, int h, int v_w, int v_h, int color_depth) { PgDisplaySettings_t settings; PtArg_t arg; PhDim_t dim; char tmp1[128], tmp2[128]; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (color_depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((w == 0) && (h == 0)) { w = 320; h = 200; } if (v_w < w) v_w = w; if (v_h < h) v_h = h; if ((v_w != w) || (v_h != h) || (w % 4)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } PgGetVideoMode(&settings); _set_current_refresh_rate(settings.refresh); /* retrieve infos for the selected mode */ PgGetVideoModeInfo(settings.mode, &ph_gfx_mode_info); dim.w = w; dim.h = h; PtSetArg(&arg, Pt_ARG_DIM, &dim, 0); PtSetResources(ph_window, 1, &arg); ph_window_context = PdCreateOffscreenContext(0, w, h, Pg_OSC_MEM_PAGE_ALIGN); if (!ph_window_context) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot create offscreen context")); return NULL; } pseudo_screen_depth = color_depth; desktop_depth = ph_gfx_mode_info.bits_per_pixel; if (color_depth == desktop_depth) { /* the color depths match */ ph_update_window = update_window_hw; /* the pseudo-screen associated with the window context */ pseudo_screen = make_photon_bitmap(ph_window_context, w, h, BMP_ID_VIDEO); } else { /* the color depths don't match, need color conversion */ colorconv_blitter = _get_colorconv_blitter(color_depth, desktop_depth); if (!colorconv_blitter) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } ph_update_window = update_window; /* the window context is a pre-converted offscreen buffer */ window_addr = PdGetOffscreenContextPtr(ph_window_context); window_pitch = ph_window_context->pitch; /* the pseudo-screen is a memory bitmap */ pseudo_screen_addr = _AL_MALLOC(w * h * BYTES_PER_PIXEL(color_depth)); if (!pseudo_screen_addr) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } pseudo_screen_pitch = w * BYTES_PER_PIXEL(color_depth); pseudo_screen = _make_bitmap(w, h, (unsigned long)pseudo_screen_addr, drv, color_depth, pseudo_screen_pitch); } if (!pseudo_screen) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } /* the last flag serves as an end of loop delimiter */ ph_dirty_lines = _AL_MALLOC((h+1) * sizeof(char)); ASSERT(ph_dirty_lines); memset(ph_dirty_lines, 0, (h+1) * sizeof(char)); ph_dirty_lines[h] = 1; setup_driver(drv, w, h, color_depth); setup_direct_shifts(); memcpy(&_special_vtable, &_screen_vtable, sizeof(GFX_VTABLE)); pseudo_screen->vtable = &_special_vtable; _special_vtable.acquire = ph_acquire_win; _special_vtable.release = ph_release_win; #ifdef ALLEGRO_NO_ASM pseudo_screen->write_bank = ph_write_line_win; _special_vtable.unwrite_bank = ph_unwrite_line_win; #else pseudo_screen->write_bank = ph_write_line_win_asm; _special_vtable.unwrite_bank = ph_unwrite_line_win_asm; #endif uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("Photon windowed, %d bpp %s", tmp1), color_depth, uconvert_ascii(color_depth == desktop_depth ? "in matching" : "in fast emulation", tmp2)); drv->desc = driver_desc; PgFlush(); PgWaitHWIdle(); pthread_cond_init(&vsync_cond, NULL); pthread_mutex_init(&ph_screen_lock, NULL); install_int(update_dirty_lines, RENDER_DELAY); return pseudo_screen; } /* qnx_private_ph_exit_win: * This is where the video driver is actually closed. */ static void qnx_private_ph_exit_win(BITMAP *bmp) { PhDim_t dim; if (bmp) clear_bitmap(bmp); remove_int(update_dirty_lines); PgSetPalette(ph_palette, 0, 0, -1, 0, 0); PgFlush(); ph_gfx_mode = PH_GFX_NONE; if (ph_window_context) { PhDCRelease(ph_window_context); ph_window_context = NULL; } if (pseudo_screen_addr) { _AL_FREE(pseudo_screen_addr); pseudo_screen_addr = NULL; } if (ph_dirty_lines) { _AL_FREE(ph_dirty_lines); ph_dirty_lines = NULL; } if (colorconv_blitter) { _release_colorconv_blitter(colorconv_blitter); colorconv_blitter = NULL; } pthread_mutex_destroy(&ph_screen_lock); pthread_cond_destroy(&vsync_cond); dim.w = 1; dim.h = 1; PtSetResource(ph_window, Pt_ARG_DIM, &dim, 0); } /* qnx_ph_init_win: * Initializes normal windowed Photon gfx driver. */ static BITMAP *qnx_ph_init_win(int w, int h, int v_w, int v_h, int color_depth) { struct BITMAP *bmp; pthread_mutex_lock(&qnx_event_mutex); ph_gfx_mode = PH_GFX_WINDOW; bmp = qnx_private_ph_init_win(&gfx_photon_win, w, h, v_w, v_h, color_depth); if (!bmp) qnx_private_ph_exit_win(NULL); pthread_mutex_unlock(&qnx_event_mutex); return bmp; } /* qnx_ph_exit_win: * Shuts down photon windowed gfx driver. */ static void qnx_ph_exit_win(BITMAP *bmp) { pthread_mutex_lock(&qnx_event_mutex); qnx_private_ph_exit_win(bmp); pthread_mutex_unlock(&qnx_event_mutex); } /* update_dirty_lines: * Dirty line updater routine. */ static void update_dirty_lines(void) { PhRect_t rect; /* to prevent the drawing threads and the rendering proc from concurrently accessing the dirty lines array */ pthread_mutex_lock(&ph_screen_lock); PgWaitHWIdle(); /* pseudo dirty rectangles mechanism: * at most only one PgFlush() call is performed for each frame. */ rect.ul.x = 0; rect.lr.x = gfx_photon_win.w; /* find the first dirty line */ rect.ul.y = 0; while (!ph_dirty_lines[rect.ul.y]) rect.ul.y++; if (rect.ul.y < gfx_photon_win.h) { /* find the last dirty line */ rect.lr.y = gfx_photon_win.h; while (!ph_dirty_lines[rect.lr.y-1]) rect.lr.y--; ph_update_window(&rect); /* clean up the dirty lines */ while (rect.ul.y < rect.lr.y) ph_dirty_lines[rect.ul.y++] = 0; } pthread_mutex_unlock(&ph_screen_lock); /* simulate vertical retrace */ pthread_cond_broadcast(&vsync_cond); PgFlush(); } /* qnx_ph_vsync_win: * Waits for vertical retrace. */ static void qnx_ph_vsync_win(void) { pthread_mutex_lock(&ph_screen_lock); pthread_cond_wait(&vsync_cond, &ph_screen_lock); pthread_mutex_unlock(&ph_screen_lock); } /* qnx_ph_set_palette_win: * Sets hardware palette. */ static void qnx_ph_set_palette_win(AL_CONST struct RGB *p, int from, int to, int vsync) { int i; for (i=from; i<=to; i++) ph_palette[i] = (p[i].r << 18) | (p[i].g << 10) | (p[i].b << 2); if (desktop_depth == 8) { if (vsync) PgWaitVSync(); PgSetPalette(ph_palette, 0, from, to - from + 1, Pg_PALSET_HARDLOCKED | Pg_PALSET_FORCE_EXPOSE, 0); PgFlush(); } else { pthread_mutex_lock(&ph_screen_lock); _set_colorconv_palette(p, from, to); /* invalidate the whole screen */ ph_dirty_lines[0] = ph_dirty_lines[gfx_photon_win.h-1] = 1; pthread_mutex_unlock(&ph_screen_lock); } } /* qnx_ph_create_video_bitmap_win: */ static BITMAP *qnx_ph_create_video_bitmap_win(int width, int height) { PdOffscreenContext_t *context; struct BITMAP *bmp; if ((width == screen->w) && (height == screen->h)) { if (!reused_screen) { reused_screen = TRUE; return screen; } } if (colorconv_blitter) { /* If we are in color conversion mode, we fall back to * memory bitmaps because we don't have system bitmaps. */ bmp = create_bitmap(width, height); if (!bmp) return NULL; /* emulate the video bitmap framework */ bmp->id |= BMP_ID_VIDEO; bmp->vtable = &_screen_vtable; #ifdef ALLEGRO_NO_ASM bmp->write_bank = ph_write_line; bmp->read_bank = ph_write_line; #else bmp->write_bank = ph_write_line_asm; bmp->read_bank = ph_write_line_asm; #endif return bmp; } else { context = PdCreateOffscreenContext(0, width, height, Pg_OSC_MEM_PAGE_ALIGN); if (!context) return NULL; return make_photon_bitmap(context, width, height, BMP_ID_VIDEO); } } /* qnx_ph_destroy_video_bitmap_win: */ static void qnx_ph_destroy_video_bitmap_win(BITMAP *bmp) { if (bmp == screen) { reused_screen = FALSE; return; } if (bmp == pseudo_screen) { /* in this case, 'bmp' points to the visible contents * but 'screen' doesn't, so we first invert that */ qnx_ph_show_video_bitmap_win(screen); } if (colorconv_blitter) { bmp->id &= ~BMP_ID_VIDEO; destroy_bitmap(bmp); } else { PhDCRelease(BMP_EXTRA(bmp)->context); destroy_photon_bitmap(bmp); } } /* qnx_ph_show_video_bitmap_win: */ static int qnx_ph_show_video_bitmap_win(BITMAP *bmp) { pthread_mutex_lock(&ph_screen_lock); /* turn the pseudo_screen into a normal video normal */ pseudo_screen->vtable->acquire = ph_acquire; pseudo_screen->vtable->release = ph_release; #ifdef ALLEGRO_NO_ASM pseudo_screen->write_bank = ph_write_line; pseudo_screen->vtable->unwrite_bank = ph_unwrite_line; #else pseudo_screen->write_bank = ph_write_line_asm; pseudo_screen->vtable->unwrite_bank = ph_unwrite_line_asm; #endif /* show the video bitmap */ pseudo_screen = bmp; /* turn the video bitmap into the pseudo_screen */ pseudo_screen->vtable->acquire = ph_acquire_win; pseudo_screen->vtable->release = ph_release_win; #ifdef ALLEGRO_NO_ASM pseudo_screen->write_bank = ph_write_line_win; pseudo_screen->vtable->unwrite_bank = ph_unwrite_line_win; #else pseudo_screen->write_bank = ph_write_line_win_asm; pseudo_screen->vtable->unwrite_bank = ph_unwrite_line_win_asm; #endif /* invalidate the whole screen */ ph_dirty_lines[0] = ph_dirty_lines[gfx_photon_win.h-1] = 1; pthread_mutex_unlock(&ph_screen_lock); return 0; } allegro-4.4.3.1/src/i386/0000775000175000017500000000000013437077643013560 5ustar siegesiegeallegro-4.4.3.1/src/i386/igfx16.s0000664000175000017500000003011513437077643015050 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit linear graphics functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #ifdef ALLEGRO_COLOR16 .text /* void _linear_putpixel16(BITMAP *bmp, int x, int y, int color); * Draws a pixel onto a linear bitmap. */ FUNC(_linear_putpixel16) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ je putpix_noclip cmpl %ecx, BMP_CL(%edx) /* test cl */ jg putpix_done cmpl %ecx, BMP_CR(%edx) /* test cr */ jle putpix_done cmpl %eax, BMP_CT(%edx) /* test ct */ jg putpix_done cmpl %eax, BMP_CB(%edx) /* test cb */ jle putpix_done putpix_noclip: movw BMP_SEG(%edx), %es /* segment selector */ movl ARG4, %ebx /* bx = color */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je putpix_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) je putpix_xor_mode /* XOR? */ cmpl $DRAW_TRANS, GLOBL(_drawing_mode) je putpix_trans_mode /* translucent? */ LOOKUP_PATTERN_POS(%ecx, %eax, %edx) movw (%eax, %ecx, 2), %bx /* read pixel from pattern bitmap */ movl ARG1, %edx /* reload clobbered registers */ movl ARG2, %ecx movl ARG3, %eax cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je putpix_solid_mode /* draw the pattern pixel? */ cmpw $MASK_COLOR_16, %bx /* test the pattern pixel */ je putpix_zero_pattern movl ARG4, %ebx /* if set, draw color */ jmp putpix_solid_mode _align_ putpix_zero_pattern: cmpl $DRAW_MASKED_PATTERN, GLOBL(_drawing_mode) je putpix_done /* skip zero pixels in masked mode */ xorl %ebx, %ebx jmp putpix_solid_mode /* draw zero pixels in solid mode */ _align_ putpix_xor_mode: READ_BANK() /* read pixel from screen */ xorw %es:(%eax, %ecx, 2), %bx /* XOR */ movl ARG3, %eax /* re-read Y position */ jmp putpix_solid_mode _align_ putpix_trans_mode: READ_BANK() pushl %ecx pushl %edx movw %es:(%eax, %ecx, 2), %dx /* read pixel from screen */ pushl GLOBL(_blender_alpha) pushl %edx pushl %ebx /* and the drawing color */ call *GLOBL(_blender_func16) /* blend */ addl $12, %esp popl %edx popl %ecx movl %eax, %ebx movl ARG3, %eax /* re-read Y position */ _align_ putpix_solid_mode: WRITE_BANK() /* select bank */ movw %bx, %es:(%eax, %ecx, 2) /* store the pixel */ putpix_done: popw %es UNWRITE_BANK() popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_putpixel16() */ /* int _linear_getpixel16(BITMAP *bmp, int x, int y); * Reads a pixel from a linear bitmap. */ FUNC(_linear_getpixel16) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es xorl %eax, %eax xorl %edx, %edx movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ testl %ecx, %ecx /* test that we are on the bitmap */ jl getpix_skip cmpl %ecx, BMP_W(%edx) jle getpix_skip testl %eax, %eax jl getpix_skip cmpl %eax, BMP_H(%edx) jg getpix_ok _align_ getpix_skip: /* return -1 if we are off the edge */ movl $-1, %ebx jmp getpix_done _align_ getpix_ok: READ_BANK() /* select the bank */ movw BMP_SEG(%edx), %es /* segment selector */ movl %eax, %ebx movzwl %es:(%ebx, %ecx, 2), %ebx getpix_done: popw %es UNWRITE_BANK() movl %ebx, %eax popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_getpixel16() */ /* void _linear_hline16(BITMAP *bmp, int x1, int y, int x2, int color); * Draws a horizontal line onto a linear bitmap. */ FUNC(_linear_hline16) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ebx /* ebx = x1 */ movl ARG3, %eax /* eax = y */ movl ARG4, %ecx /* ecx = x2 */ cmpl %ebx, %ecx jge hline_no_xswap xchgl %ecx, %ebx hline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je hline_noclip cmpl BMP_CT(%edx), %eax /* test bmp->ct */ jl hline_done cmpl BMP_CB(%edx), %eax /* test bmp->cb */ jge hline_done cmpl BMP_CL(%edx), %ebx /* test x1, bmp->cl */ jge hline_x1_ok cmpl BMP_CL(%edx), %ecx /* test x2, bmp->cl */ jl hline_done movl BMP_CL(%edx), %ebx /* clip x1 */ hline_x1_ok: cmpl BMP_CR(%edx), %ecx /* test x2, bmp->cr */ jl hline_noclip cmpl BMP_CR(%edx), %ebx /* test x1, bmp->cr */ jge hline_done movl BMP_CR(%edx), %ecx /* clip x2 */ decl %ecx hline_noclip: subl %ebx, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* segment selector */ WRITE_BANK() /* select write bank */ leal (%eax, %ebx, 2), %edi /* dest address in edi */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je hline_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) jne hline_not_xor /* XOR? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%eax, %ebx, 2), %esi /* source address in esi */ movw ARG5, %bx /* read the color */ _align_ hline_xor_loop: movw %es:(%esi), %ax /* read a pixel */ xorw %bx, %ax /* xor */ movw %ax, %es:(%edi) /* and write it */ addl $2, %esi addl $2, %edi decl %ecx jg hline_xor_loop jmp hline_done _align_ hline_not_xor: cmpl $DRAW_TRANS, GLOBL(_drawing_mode) jne hline_not_trans /* translucent? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%eax, %ebx, 2), %esi /* source address in esi */ movl %ecx, ARG4 /* loop counter on the stack */ _align_ hline_trans_loop: movw %es:(%esi), %ax /* read pixel from screen */ pushl GLOBL(_blender_alpha) pushl %eax pushl ARG5 /* and the drawing color */ call *GLOBL(_blender_func16) /* blend */ addl $12, %esp movw %ax, %es:(%edi) /* and write it */ addl $2, %esi addl $2, %edi decl ARG4 jg hline_trans_loop jmp hline_done _align_ hline_not_trans: movl ARG3, %eax /* get position in pattern bitmap */ LOOKUP_PATTERN_POS(%ebx, %eax, %edx) movl %eax, %esi movl GLOBL(_drawing_x_mask), %edx cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je hline_copy_pattern_loop cmpl $DRAW_SOLID_PATTERN, GLOBL(_drawing_mode) je hline_solid_pattern_loop _align_ hline_masked_pattern_loop: movw (%esi, %ebx, 2), %ax /* read a pixel */ cmpw $MASK_COLOR_16, %ax /* test it */ je hline_masked_skip movw ARG5, %ax movw %ax, %es:(%edi) /* write a colored pixel */ hline_masked_skip: incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_masked_pattern_loop jmp hline_done _align_ hline_copy_pattern_loop: movw (%esi, %ebx, 2), %ax /* read a pixel */ movw %ax, %es:(%edi) /* and write it */ incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_copy_pattern_loop jmp hline_done _align_ hline_solid_pattern_loop: movw (%esi, %ebx, 2), %ax /* read a pixel */ cmpw $MASK_COLOR_16, %ax /* test it */ je hline_solid_zero movw ARG5, %ax movw %ax, %es:(%edi) /* write a colored pixel */ incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_zero: movw $0, %es:(%edi) /* write a zero pixel */ incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_mode: /* regular hline drawer */ movw ARG5, %ax /* get color */ shll $16, %eax movw ARG5, %ax /* get two copies of the color */ cld testl $2, %edi /* are we long aligned? */ jz hline_l_aligned stosw /* if not, copy a word */ decl %ecx hline_l_aligned: shrl $1, %ecx /* for long copy */ jz hline_no_long rep ; stosl /* do some 32 bit copies */ hline_no_long: jnc hline_done stosw /* do we need a 16 bit copy? */ hline_done: popw %es movl ARG1, %edx UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_hline16 */ /* void _linear_vline16(BITMAP *bmp, int x, int y1, int y2, int color); * Draws a vertical line onto a linear bitmap. */ FUNC(_linear_vline16) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %edi /* edi = x */ movl ARG3, %esi /* esi = y1 */ movl ARG4, %ecx /* ecx = y2 */ cmpl %esi, %ecx jge vline_no_xswap xchgl %ecx, %esi vline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je vline_noclip cmpl BMP_CL(%edx), %edi /* test bmp->cl */ jl vline_done cmpl BMP_CR(%edx), %edi /* test bmp->cr */ jge vline_done cmpl BMP_CT(%edx), %esi /* test y1, bmp->ct */ jge vline_y1_ok cmpl BMP_CT(%edx), %ecx /* test y2, bmp->ct */ jl vline_done movl BMP_CT(%edx), %esi /* clip y1 */ vline_y1_ok: cmpl BMP_CB(%edx), %ecx /* test y2, bmp->cb */ jl vline_noclip cmpl BMP_CB(%edx), %esi /* test y1, bmp->cb */ jge vline_done movl BMP_CB(%edx), %ecx /* clip y2 */ decl %ecx vline_noclip: subl %esi, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* load segment */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je vline_solid_mode /* solid draw? */ movl BMP_CLIP(%edx), %eax /* store destination clipping flag */ pushl %eax movl $0, BMP_CLIP(%edx) /* turn clipping off (we already did it) */ movl ARG5, %eax pushl %eax /* push color */ pushl %esi /* push y */ pushl %edi /* push x */ pushl %edx /* push bitmap */ movl %ecx, %ebx /* ebx = loop counter */ _align_ vline_special_mode_loop: /* vline drawer for funny modes */ call GLOBL(_linear_putpixel16)/* draw the pixel */ incl 8(%esp) /* next y */ decl %ebx jg vline_special_mode_loop /* loop */ popl %edx /* clean up stack */ addl $12, %esp popl %eax movl %eax, BMP_CLIP(%edx) /* restore bitmap clipping flag */ jmp vline_done _align_ vline_solid_mode: /* normal vline drawer */ movl ARG5, %ebx /* get color */ _align_ vline_loop: movl %esi, %eax WRITE_BANK() /* select bank */ movw %bx, %es:(%eax, %edi, 2) /* write pixel */ incl %esi decl %ecx jg vline_loop /* loop */ vline_done: popw %es UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_vline16() */ #endif /* ifdef ALLEGRO_COLOR16 */ allegro-4.4.3.1/src/i386/istretch.c0000664000175000017500000003707213437077643015562 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Bitmap stretching functions for the i386. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "opcodes.h" #ifdef ALLEGRO_UNIX #include "allegro/platform/aintunix.h" /* for _unix_get_page_size */ #endif #ifdef ALLEGRO_WINDOWS #include "winalleg.h" /* For VirtualProtect */ #endif /* ifdef ALLEGRO_WINDOWS */ #ifdef ALLEGRO_HAVE_MPROTECT #include #include #endif /* ifdef ALLEGRO_HAVE_MPROTECT */ /* helper macro for generating stretchers in each color depth */ #define DECLARE_STRETCHER(sz, mask, scale) \ { \ int x, x2; \ int c; \ \ if (sxd == itofix(1)) { /* easy case for 1 -> 1 scaling */ \ if (masked) { \ for (c=0; c itofix(1)) { /* big -> little scaling */ \ for (x=0; x> 16) + 1; \ sx += sxd; \ x2 = (sx >> 16) - x2; \ if (x2*scale > 1) { \ COMPILER_ADD_ESI(x2*scale); \ } \ else if (x2*scale == 1) { \ COMPILER_INC_ESI(); \ } \ } \ } \ else { /* little -> big scaling */ \ x2 = sx >> 16; \ COMPILER_LODS##sz(); \ for (x=0; x> 16) > x2) { \ COMPILER_LODS##sz(); \ x2++; \ } \ } \ } \ } /* make_stretcher_256: * Helper for constructing a 256 color stretcher routine. */ static int make_stretcher_256(int compiler_pos, fixed sx, fixed sxd, int dest_width, int masked) { #ifdef ALLEGRO_COLOR8 DECLARE_STRETCHER(B, mask, 1); #endif return compiler_pos; } /* make_stretcher_15: * Helper for constructing a 15 bit stretcher routine. */ static int make_stretcher_15(int compiler_pos, fixed sx, fixed sxd, int dest_width, int masked) { #ifdef ALLEGRO_COLOR16 DECLARE_STRETCHER(W, MASK_COLOR_15, 2); #endif return compiler_pos; } /* make_stretcher_16: * Helper for constructing a 16 bit stretcher routine. */ static int make_stretcher_16(int compiler_pos, fixed sx, fixed sxd, int dest_width, int masked) { #ifdef ALLEGRO_COLOR16 DECLARE_STRETCHER(W, MASK_COLOR_16, 2); #endif return compiler_pos; } /* make_stretcher_24: * Helper for constructing a 24 bit stretcher routine. */ static int make_stretcher_24(int compiler_pos, fixed sx, fixed sxd, int dest_width, int masked) { #ifdef ALLEGRO_COLOR24 DECLARE_STRETCHER(L2, MASK_COLOR_24, 3); #endif return compiler_pos; } /* make_stretcher_32: * Helper for constructing a 32 bit stretcher routine. */ static int make_stretcher_32(int compiler_pos, fixed sx, fixed sxd, int dest_width, int masked) { #ifdef ALLEGRO_COLOR32 DECLARE_STRETCHER(L, MASK_COLOR_32, 4); #endif return compiler_pos; } /* make_stretcher: * Helper function for stretch_blit(). Builds a machine code stretching * routine in the scratch memory area. */ static int make_stretcher(int compiler_pos, fixed sx, fixed sxd, int dest_width, int masked, int color_depth) { if (dest_width > 0) { switch (color_depth) { case 8: return make_stretcher_256(compiler_pos, sx, sxd, dest_width, masked); case 15: return make_stretcher_15(compiler_pos, sx, sxd, dest_width, masked); case 16: return make_stretcher_16(compiler_pos, sx, sxd, dest_width, masked); case 24: return make_stretcher_24(compiler_pos, sx, sxd, dest_width, masked); case 32: return make_stretcher_32(compiler_pos, sx, sxd, dest_width, masked); } } return compiler_pos; } /* cache of previously constructed stretcher functions */ typedef struct STRETCHER_INFO { fixed sx; fixed sxd; short dest_width; char depth; char flags; int lru; void *exec; /* xr_ mapping in the mmap case, normally both in one. */ int size; #ifdef ALLEGRO_USE_MMAP_GEN_CODE_BUF void *rw; /* _rw mapping for the mmap case. */ int fd; /* mapping backing fd for the mmap case. */ #endif } STRETCHER_INFO; #define NUM_STRETCHERS 8 static STRETCHER_INFO stretcher_info[NUM_STRETCHERS]; static int stretcher_count = 0; static int stretcher_virgin = TRUE; /* free_stretchers: * Clean up atexit. */ static void free_stretchers(void) { int i; for (i=0; ivtable->do_stretch_blit && !is_memory_bitmap(dest)) { source->vtable->do_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked); return; } /* trivial reject for zero sizes */ if ((source_width <= 0) || (source_height <= 0) || (dest_width <= 0) || (dest_height <= 0)) return; /* make sure all allocated memory is freed atexit */ if (stretcher_virgin) { stretcher_virgin = FALSE; memset(stretcher_info, 0, sizeof(stretcher_info)); _add_exit_func(free_stretchers, "free_stretchers"); } /* convert to fixed point */ sx = itofix(source_x); sy = itofix(source_y); /* calculate delta values */ sxd = itofix(source_width) / dest_width; syd = itofix(source_height) / dest_height; /* clip? */ if (dest->clip) { while (dest_x < dest->cl) { dest_x++; dest_width--; sx += sxd; } while (dest_y < dest->ct) { dest_y++; dest_height--; sy += syd; } if (dest_x+dest_width > dest->cr) dest_width = dest->cr - dest_x; if (dest_y+dest_height > dest->cb) dest_height = dest->cb - dest_y; if ((dest_width <= 0) || (dest_height <= 0)) return; } /* compensate for a problem where the first column or row can get * an extra pixel than it should do for little -> big scaling, due * to fixed point number representation imprecisions */ if (sxd < itofix(1)) sx += (sxd >> 1); if (syd < itofix(1)) sy += (syd >> 1); /* search the cache */ stretcher_count++; if (stretcher_count <= 0) { stretcher_count = 1; for (i=0; ivtable->color_depth) && (stretcher_info[i].flags == flags)) { /* use a previously generated routine */ if (stretcher_info[i].flags & 2) dest_x >>= 2; _do_stretch(source, dest, stretcher_info[i].exec, sx>>16, sy, syd, dest_x, dest_y, dest_height, dest->vtable->color_depth); stretcher_info[i].lru = stretcher_count; return; } else { /* decide which cached routine to discard */ if (stretcher_info[i].lru < best_lru) { best = i; best_lru = stretcher_info[i].lru; } } } #ifdef ALLEGRO_USE_MMAP_GEN_CODE_BUF _exec_map = stretcher_info[best].exec; _rw_map = stretcher_info[best].rw; _map_size = stretcher_info[best].size; _map_fd = stretcher_info[best].fd; #else prev_scratch_mem = _scratch_mem; prev_scratch_mem_size = _scratch_mem_size; _scratch_mem = stretcher_info[best].exec; _scratch_mem_size = stretcher_info[best].size; #endif if (is_linear_bitmap(dest)) { /* build a simple linear stretcher */ compiler_pos = make_stretcher(0, sx, sxd, dest_width, masked, dest->vtable->color_depth); } #ifdef ALLEGRO_GFX_HAS_VGA else { int plane, d; /* build four stretchers, one for each mode-X plane */ for (plane=0; plane<4; plane++) { COMPILER_PUSH_ESI(); COMPILER_PUSH_EDI(); COMPILER_MOV_EAX((0x100<<((dest_x+plane)&3))|2); COMPILER_MOV_EDX(0x3C4); COMPILER_OUTW(); compiler_pos = make_stretcher(compiler_pos, sx+sxd*plane, sxd<<2, (dest_width-plane+3)>>2, masked, 8); COMPILER_POP_EDI(); COMPILER_POP_ESI(); if (((dest_x+plane) & 3) == 3) { COMPILER_INC_EDI(); } d = ((sx+sxd*(plane+1))>>16) - ((sx+sxd*plane)>>16); if (d > 0) { COMPILER_ADD_ESI(d); } } dest_x >>= 2; } #endif /* ifdef ALLEGRO_GFX_HAS_VGA */ COMPILER_RET(); /* Play nice with executable memory protection: VirtualProtect on Windows, * mprotect on UNIX based systems. */ #ifdef ALLEGRO_WINDOWS VirtualProtect(_scratch_mem, _scratch_mem_size, PAGE_EXECUTE_READWRITE, &old_protect); #elif defined(ALLEGRO_HAVE_MPROTECT) && !defined(ALLEGRO_USE_MMAP_GEN_CODE_BUF) { char *p = (char *)((uintptr_t)_scratch_mem & ~(_unix_get_page_size() - 1ul)); if (mprotect(p, _scratch_mem_size + ((char *)_scratch_mem - p), PROT_EXEC|PROT_READ|PROT_WRITE)) perror("allegro-error: mprotect failed during stretched blit!"); } #endif /* store it in the cache */ stretcher_info[best].sx = sx; stretcher_info[best].sxd = sxd; stretcher_info[best].dest_width = dest_width; stretcher_info[best].depth = dest->vtable->color_depth; stretcher_info[best].flags = flags; stretcher_info[best].lru = stretcher_count; #ifdef ALLEGRO_USE_MMAP_GEN_CODE_BUF stretcher_info[best].exec = _exec_map; stretcher_info[best].rw = _rw_map; stretcher_info[best].size = _map_size; stretcher_info[best].fd = _map_fd; #else stretcher_info[best].exec = _scratch_mem; stretcher_info[best].size = _scratch_mem_size; _scratch_mem = prev_scratch_mem; _scratch_mem_size = prev_scratch_mem_size; #endif /* and call the stretcher */ _do_stretch(source, dest, stretcher_info[best].exec, sx>>16, sy, syd, dest_x, dest_y, dest_height, dest->vtable->color_depth); } /* stretch_blit: * Opaque bitmap scaling function. */ void stretch_blit(BITMAP *s, BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h) { do_stretch_blit(s, d, s_x, s_y, s_w, s_h, d_x, d_y, d_w, d_h, 0); } /* masked_stretch_blit: * Masked bitmap scaling function. */ void masked_stretch_blit(BITMAP *s, BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h) { do_stretch_blit(s, d, s_x, s_y, s_w, s_h, d_x, d_y, d_w, d_h, 1); } /* stretch_sprite: * Masked version of stretch_blit(). */ void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h) { do_stretch_blit(sprite, bmp, 0, 0, sprite->w, sprite->h, x, y, w, h, 1); } allegro-4.4.3.1/src/i386/iscan.s0000664000175000017500000026551513437077643015057 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Polygon scanline filler helpers (gouraud shading, tmapping, etc). * MMX scanline fillers are defined in 'iscanmmx.s' * * By Calin Andrian. * * See readme.txt for copyright information. */ #include "asmdefs.inc" .text /* all these functions share the same parameters */ #define ADDR ARG1 #define W ARG2 #define INFO ARG3 #ifdef ALLEGRO_COLOR8 /* void _poly_scanline_gcol8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills a single-color gouraud shaded polygon scanline. */ FUNC(_poly_scanline_gcol8) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi movl INFO, %edi /* load registers */ movl POLYSEG_C(%edi), %eax movl POLYSEG_DC(%edi), %esi movl W, %ecx movl ADDR, %edi sarl $8, %eax /* convert 16.16 fixed into 8.8 fixed */ sarl $8, %esi jge gcol_loop incl %esi _align_ gcol_loop: movb %ah, FSEG(%edi) addl %esi, %eax incl %edi decl %ecx jg gcol_loop popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_gcol8() */ /* void _poly_scanline_grgb8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_scanline_grgb8) pushl %ebp movl %esp, %ebp subl $8, %esp /* two local variables: */ #define DRB -4(%ebp) #define DG -8(%ebp) pushl %ebx pushl %esi pushl %edi grgb_entry: movl INFO, %esi /* load registers */ movl POLYSEG_DR(%esi), %eax movl POLYSEG_DB(%esi), %ecx sall $8, %eax movl POLYSEG_DG(%esi), %ebx sarl $8, %ecx andl $0xffff0000, %eax sarl $8, %ebx addl %ecx, %eax movl %ebx, DG movl %eax, DRB movl POLYSEG_R(%esi), %eax movl POLYSEG_B(%esi), %ecx sall $8, %eax movl POLYSEG_G(%esi), %ebx sarl $8, %ecx andl $0xffff0000, %eax sarl $8, %ebx addl %ecx, %eax movl ADDR, %edi decl %edi movl %ebx, %edx /* green */ _align_ grgb_loop: movl %eax, %ecx /* red and blue */ shrl $6, %edx andl $0xf800f800, %ecx addl DRB, %eax shrl $11, %ecx andl $0x3e0, %edx movl %ecx, %esi addl DG, %ebx andl $0xffff, %esi /* blue */ shrl $6, %ecx /* red */ addl %edx, %esi /* green and blue */ addl GLOBL(rgb_map), %ecx movl %ebx, %edx movb (%ecx, %esi), %cl movb %cl, FSEG(%edi) /* write the pixel */ incl %edi decl W jg grgb_loop popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_grgb8() */ #undef DRB #undef DG #define DU -4(%ebp) #define DVL -8(%ebp) #define DVH -12(%ebp) #define VMASK -16(%ebp) #define TEXTURE -20(%ebp) #define C -24(%ebp) #define DC -28(%ebp) #define TMP -32(%ebp) /* helper for setting up an affine texture mapping operation */ #define INIT_ATEX(extra) \ pushl %ebp ;\ movl %esp, %ebp ;\ subl $32, %esp ;\ pushl %ebx ;\ pushl %esi ;\ pushl %edi ;\ ;\ movl INFO, %esi ;\ movl POLYSEG_VSHIFT(%esi), %ecx ;\ movl POLYSEG_VMASK(%esi), %ebx ;\ negl %ecx ;\ addl $16, %ecx ;\ movl %ebx, VMASK ;\ movl POLYSEG_TEXTURE(%esi), %ebx ;\ movl %ebx, TEXTURE ;\ ;\ extra ;\ ;\ xorl %edx, %edx ;\ movl POLYSEG_DV(%esi), %ebx ;\ movl POLYSEG_DU(%esi), %eax ;\ shldl $16, %ebx, %edx ;\ shll %cl, %eax ;\ shll $16, %ebx ;\ movl %eax, DU ;\ movl %edx, DVH ;\ movl %ebx, DVL ;\ ;\ xorl %edx, %edx ;\ movl POLYSEG_V(%esi), %ebx ;\ movl POLYSEG_U(%esi), %eax ;\ shldl $16, %ebx, %edx ;\ shll %cl, %eax ;\ shll $16, %ebx ;\ ;\ movl ADDR, %edi ;\ addl $16, %ecx ;\ decl %edi ;\ ;\ andl VMASK, %edx ;\ movl %eax, %esi ;\ incl %edi ;\ shrdl %cl, %edx, %esi ;\ addl DU, %eax ;\ addl TEXTURE, %esi /* void _poly_scanline_atex8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex8) INIT_ATEX(/**/) addl DVL, %ebx adcl DVH, %edx movb (%esi), %ch movb %ch, FSEG(%edi) decl W jz atex_done _align_ atex_loop: andl VMASK, %edx movl %eax, %esi incl %edi shrdl %cl, %edx, %esi addl DU, %eax addl TEXTURE, %esi addl DVL, %ebx adcl DVH, %edx movb (%esi), %ch movb %ch, FSEG(%edi) decl W jg atex_loop atex_done: popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_atex8() */ /* void _poly_scanline_atex_mask8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask8) INIT_ATEX(/**/) addl DVL, %ebx adcl DVH, %edx _align_ atex_mask_loop: movb (%esi), %ch andl VMASK, %edx movl %eax, %esi incl %edi shrdl %cl, %edx, %esi addl DU, %eax addl TEXTURE, %esi addl DVL, %ebx adcl DVH, %edx orb %ch, %ch jz atex_mask_skip movb %ch, FSEG(%edi) atex_mask_skip: decl W jg atex_mask_loop atex_mask_done: popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_atex8() */ /* void _poly_scanline_atex_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %ebx ; \ sarl $8, %eax ; \ sarl $8, %ebx ; \ jge atex_lit_round ; \ incl %ebx ; \ atex_lit_round: \ subl %ebx, %eax ; \ movl %ebx, DC ; \ movl %eax, C INIT_ATEX(INIT_CODE) #undef INIT_CODE movl %eax, TMP addl DVL, %ebx movl C, %eax adcl DVH, %edx addl DC, %eax movzbl (%esi), %esi /* read texel */ movl %eax, C addl GLOBL(color_map), %esi andl $0x0000ff00, %eax movb (%eax, %esi), %ch /* lookup in lighting table */ movl TMP, %eax movb %ch, FSEG(%edi) decl W jz atex_lit_done _align_ atex_lit_loop: andl VMASK, %edx movl %eax, %esi incl %edi shrdl %cl, %edx, %esi addl DU, %eax addl TEXTURE, %esi movl %eax, TMP addl DVL, %ebx movl C, %eax adcl DVH, %edx addl DC, %eax movzbl (%esi), %esi /* read texel */ movl %eax, C addl GLOBL(color_map), %esi andl $0x0000ff00, %eax movb (%eax, %esi), %ch /* lookup in lighting table */ movl TMP, %eax movb %ch, FSEG(%edi) decl W jg atex_lit_loop atex_lit_done: popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_atex_lit8() */ /* void _poly_scanline_atex_mask_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %ebx ; \ sarl $8, %eax ; \ sarl $8, %ebx ; \ jge atex_mask_lit_round ; \ incl %ebx ; \ atex_mask_lit_round: \ subl %ebx, %eax ; \ movl %ebx, DC ; \ movl %eax, C INIT_ATEX(INIT_CODE) #undef INIT_CODE movl %eax, TMP addl DVL, %ebx movl C, %eax adcl DVH, %edx addl DC, %eax movzbl (%esi), %esi /* read texel */ testl $0xffffffff, %esi jz atex_mask_lit_skip movl %eax, C addl GLOBL(color_map), %esi andl $0x0000ff00, %eax movb (%eax, %esi), %ch /* lookup in lighting table */ movl TMP, %eax movb %ch, FSEG(%edi) decl W jz atex_mask_lit_done _align_ atex_mask_lit_loop: andl VMASK, %edx movl %eax, %esi incl %edi shrdl %cl, %edx, %esi addl DU, %eax addl TEXTURE, %esi movl %eax, TMP addl DVL, %ebx movl C, %eax adcl DVH, %edx addl DC, %eax movzbl (%esi), %esi /* read texel */ testl $0xffffffff, %esi jz atex_mask_lit_skip movl %eax, C addl GLOBL(color_map), %esi andl $0x0000ff00, %eax movb (%eax, %esi), %ch /* lookup in lighting table */ movl TMP, %eax movb %ch, FSEG(%edi) decl W jg atex_mask_lit_loop jmp atex_mask_lit_done atex_mask_lit_skip: movl TMP, %eax decl W jg atex_mask_lit_loop atex_mask_lit_done: popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_atex_mask_lit8() */ #undef DU #undef DVL #undef DVH #undef TEXTURE #undef VMASK #undef INIT_ATEX #undef C #undef DC #undef TMP #endif /* COLOR8 */ #define TMP -4(%ebp) #define UMASK -8(%ebp) #define VMASK -12(%ebp) #define VSHIFT -16(%ebp) #define DU1 -20(%ebp) #define DV1 -24(%ebp) #define DZ1 -28(%ebp) #define DU4 -32(%ebp) #define DV4 -36(%ebp) #define DZ4 -40(%ebp) #define UDIFF -44(%ebp) #define VDIFF -48(%ebp) #define PREVU -52(%ebp) #define PREVV -56(%ebp) #define COUNT -60(%ebp) #define C -64(%ebp) #define DC -68(%ebp) #define TEXTURE -72(%ebp) /* helper for starting an fpu 1/z division */ #define START_FP_DIV() \ fld1 ; \ fdiv %st(3), %st(0) /* helper for ending an fpu division, returning corrected u and v values */ #define END_FP_DIV(ureg, vreg) \ fld %st(0) /* duplicate the 1/z value */ ; \ ; \ fmul %st(3), %st(0) /* divide u by z */ ; \ fxch %st(1) ; \ ; \ fmul %st(2), %st(0) /* divide v by z */ ; \ ; \ fistpl TMP /* store v */ ; \ movl TMP, vreg ; \ ; \ fistpl TMP /* store u */ ; \ movl TMP, ureg /* helper for updating the u, v, and z values */ #define UPDATE_FP_POS(n) \ fadds DV##n /* update v coord */ ; \ fxch %st(1) /* swap vuz stack to uvz */ ; \ ; \ fadds DU##n /* update u coord */ ; \ fxch %st(2) /* swap uvz stack to zvu */ ; \ ; \ fadds DZ##n /* update z value */ ; \ fxch %st(2) /* swap zvu stack to uvz */ ; \ fxch %st(1) /* swap uvz stack back to vuz */ /* main body of the perspective-correct texture mapping routine */ #define DO_PTEX(name) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $72, %esp /* eighteen local variables */ ; \ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ ; \ flds POLYSEG_Z(%esi) /* z at bottom of fpu stack */ ; \ flds POLYSEG_FU(%esi) /* followed by u */ ; \ flds POLYSEG_FV(%esi) /* followed by v */ ; \ ; \ flds POLYSEG_DFU(%esi) /* multiply diffs by four */ ; \ flds POLYSEG_DFV(%esi) ; \ flds POLYSEG_DZ(%esi) ; \ fxch %st(2) /* u v z */ ; \ fadd %st(0), %st(0) /* 2u v z */ ; \ fxch %st(1) /* v 2u z */ ; \ fadd %st(0), %st(0) /* 2v 2u z */ ; \ fxch %st(2) /* z 2u 2v */ ; \ fadd %st(0), %st(0) /* 2z 2u 2v */ ; \ fxch %st(1) /* 2u 2z 2v */ ; \ fadd %st(0), %st(0) /* 4u 2z 2v */ ; \ fxch %st(2) /* 2v 2z 4u */ ; \ fadd %st(0), %st(0) /* 4v 2z 4u */ ; \ fxch %st(1) /* 2z 4v 4u */ ; \ fadd %st(0), %st(0) /* 4z 4v 4u */ ; \ fxch %st(2) /* 4u 4v 4z */ ; \ fstps DU4 ; \ fstps DV4 ; \ fstps DZ4 ; \ ; \ START_FP_DIV() /* prime the 1/z calculation */ ; \ ; \ movl POLYSEG_DFU(%esi), %eax /* copy diff values onto the stack */ ; \ movl POLYSEG_DFV(%esi), %ebx ; \ movl POLYSEG_DZ(%esi), %ecx ; \ movl %eax, DU1 ; \ movl %ebx, DV1 ; \ movl %ecx, DZ1 ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %edx ; \ movl POLYSEG_UMASK(%esi), %eax ; \ ; \ shll %cl, %edx /* adjust v mask and shift value */ ; \ negl %ecx ; \ movl %eax, UMASK ; \ addl $16, %ecx ; \ movl %edx, VMASK ; \ movl %ecx, VSHIFT ; \ ; \ INIT() ; \ ; \ movl ADDR, %edi ; \ ; \ _align_ ; \ name##_odd_byte_loop: ; \ testl $3, %edi /* deal with any odd pixels */ ; \ jz name##_no_odd_bytes ; \ ; \ END_FP_DIV(%ebx, %edx) /* get corrected u/v position */ ; \ UPDATE_FP_POS(1) /* update u/v/z values */ ; \ START_FP_DIV() /* start up the next divide */ ; \ ; \ movb VSHIFT, %cl /* shift and mask v coordinate */ ; \ sarl %cl, %edx ; \ andl VMASK, %edx ; \ ; \ sarl $16, %ebx /* shift and mask u coordinate */ ; \ andl UMASK, %ebx ; \ addl %ebx, %edx ; \ ; \ SINGLE_PIXEL(1) /* process the pixel */ ; \ ; \ decl W ; \ jg name##_odd_byte_loop ; \ ; \ _align_ ; \ name##_no_odd_bytes: ; \ movl W, %ecx /* inner loop expanded 4 times */ ; \ movl %ecx, COUNT ; \ shrl $2, %ecx ; \ jg name##_prime_x4 ; \ ; \ END_FP_DIV(%ebx, %edx) /* get corrected u/v position */ ; \ UPDATE_FP_POS(1) /* update u/v/z values */ ; \ START_FP_DIV() /* start up the next divide */ ; \ ; \ movl %ebx, PREVU /* store initial u/v pos */ ; \ movl %edx, PREVV ; \ ; \ jmp name##_cleanup_leftovers ; \ ; \ _align_ ; \ name##_prime_x4: ; \ movl %ecx, W ; \ ; \ END_FP_DIV(%ebx, %edx) /* get corrected u/v position */ ; \ UPDATE_FP_POS(4) /* update u/v/z values */ ; \ START_FP_DIV() /* start up the next divide */ ; \ ; \ movl %ebx, PREVU /* store initial u/v pos */ ; \ movl %edx, PREVV ; \ ; \ jmp name##_start_loop ; \ ; \ _align_ ; \ name##_last_time: ; \ END_FP_DIV(%eax, %ecx) /* get corrected u/v position */ ; \ UPDATE_FP_POS(1) /* update u/v/z values */ ; \ jmp name##_loop_contents ; \ ; \ _align_ ; \ name##_loop: ; \ END_FP_DIV(%eax, %ecx) /* get corrected u/v position */ ; \ UPDATE_FP_POS(4) /* update u/v/z values */ ; \ ; \ name##_loop_contents: ; \ START_FP_DIV() /* start up the next divide */ ; \ ; \ movl PREVU, %ebx /* read the previous u/v pos */ ; \ movl PREVV, %edx ; \ ; \ movl %eax, PREVU /* store u/v for the next cycle */ ; \ movl %ecx, PREVV ; \ ; \ subl %ebx, %eax /* get u/v diffs for the four pixels */ ; \ subl %edx, %ecx ; \ sarl $2, %eax ; \ sarl $2, %ecx ; \ movl %eax, UDIFF ; \ movl %ecx, VDIFF ; \ ; \ PREPARE_FOUR_PIXELS() ; \ ; \ /* pixel 1 */ ; \ movl %edx, %eax /* shift and mask v coordinate */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* shift and mask u coordinate */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ FOUR_PIXELS(0) /* process pixel 1 */ ; \ ; \ addl UDIFF, %ebx ; \ addl VDIFF, %edx ; \ ; \ /* pixel 2 */ ; \ movl %edx, %eax /* shift and mask v coordinate */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* shift and mask u coordinate */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ FOUR_PIXELS(1) /* process pixel 2 */ ; \ ; \ addl UDIFF, %ebx ; \ addl VDIFF, %edx ; \ ; \ /* pixel 3 */ ; \ movl %edx, %eax /* shift and mask v coordinate */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* shift and mask u coordinate */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ FOUR_PIXELS(2) /* process pixel 3 */ ; \ ; \ addl UDIFF, %ebx ; \ addl VDIFF, %edx ; \ ; \ /* pixel 4 */ ; \ movl %edx, %eax /* shift and mask v coordinate */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* shift and mask u coordinate */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ FOUR_PIXELS(3) /* process pixel 4 */ ; \ ; \ WRITE_FOUR_PIXELS() /* write four pixels at a time */ ; \ ; \ name##_start_loop: ; \ decl W ; \ jg name##_loop ; \ jz name##_last_time ; \ ; \ name##_cleanup_leftovers: ; \ movl COUNT, %ecx /* deal with any leftover pixels */ ; \ andl $3, %ecx ; \ jz name##_done ; \ ; \ movl %ecx, COUNT ; \ movl PREVU, %ebx ; \ movl PREVV, %edx ; \ ; \ _align_ ; \ name##_cleanup_loop: ; \ movb VSHIFT, %cl /* shift and mask v coordinate */ ; \ sarl %cl, %edx ; \ andl VMASK, %edx ; \ ; \ sarl $16, %ebx /* shift and mask u coordinate */ ; \ andl UMASK, %ebx ; \ addl %ebx, %edx ; \ ; \ SINGLE_PIXEL(2) /* process the pixel */ ; \ ; \ decl COUNT ; \ jz name##_done ; \ ; \ END_FP_DIV(%ebx, %edx) /* get corrected u/v position */ ; \ UPDATE_FP_POS(1) /* update u/v/z values */ ; \ START_FP_DIV() /* start up the next divide */ ; \ jmp name##_cleanup_loop ; \ ; \ name##_done: ; \ fstp %st(0) /* pop fpu stack */ ; \ fstp %st(0) ; \ fstp %st(0) ; \ fstp %st(0) ; \ ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR8 /* void _poly_scanline_ptex8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex8) #define INIT() \ movl POLYSEG_TEXTURE(%esi), %esi #define SINGLE_PIXEL(n) \ movb (%esi, %edx), %al /* read texel */ ; \ movb %al, FSEG(%edi) /* write the pixel */ ; \ incl %edi #define PREPARE_FOUR_PIXELS() \ /* noop */ #define FOUR_PIXELS(n) \ movb (%esi, %eax), %al /* read texel */ ; \ movb %al, n+TMP /* store the pixel */ #define WRITE_FOUR_PIXELS() \ movl TMP, %eax /* write four pixels at a time */ ; \ movl %eax, FSEG(%edi) ; \ addl $4, %edi DO_PTEX(ptex) #undef INIT #undef SINGLE_PIXEL #undef PREPARE_FOUR_PIXELS #undef FOUR_PIXELS #undef WRITE_FOUR_PIXELS ret /* end of _poly_scanline_ptex8() */ /* void _poly_scanline_ptex_mask8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask8) #define INIT() \ movl POLYSEG_TEXTURE(%esi), %esi #define SINGLE_PIXEL(n) \ movb (%esi, %edx), %al /* read texel */ ; \ orb %al, %al ; \ jz ptex_mask_skip_left_##n ; \ movb %al, FSEG(%edi) /* write the pixel */ ; \ ptex_mask_skip_left_##n: ; \ incl %edi #define PREPARE_FOUR_PIXELS() \ /* noop */ #define FOUR_PIXELS(n) \ movb (%esi, %eax), %al /* read texel */ ; \ orb %al, %al ; \ jz ptex_mask_skip_##n ; \ movb %al, FSEG(%edi) /* write the pixel */ ; \ ptex_mask_skip_##n: ; \ incl %edi #define WRITE_FOUR_PIXELS() \ /* noop */ DO_PTEX(ptex_mask) #undef INIT #undef SINGLE_PIXEL #undef PREPARE_FOUR_PIXELS #undef FOUR_PIXELS #undef WRITE_FOUR_PIXELS ret /* end of _poly_scanline_ptex_mask8() */ /* void _poly_scanline_ptex_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_lit8) #define INIT() \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %ebx ; \ movl POLYSEG_TEXTURE(%esi), %ecx ; \ sarl $8, %eax ; \ sarl $8, %ebx ; \ movl %eax, C ; \ movl %ebx, DC ; \ movl %ecx, TEXTURE #define SINGLE_PIXEL(n) \ movl TEXTURE, %esi /* read texel */ ; \ movzbl (%esi, %edx), %eax ; \ ; \ movb 1+C, %ah /* lookup in lighting table */ ; \ movl GLOBL(color_map), %esi ; \ movl DC, %ecx ; \ movb (%eax, %esi), %al ; \ addl %ecx, C ; \ ; \ movb %al, FSEG(%edi) /* write the pixel */ ; \ incl %edi #define PREPARE_FOUR_PIXELS() \ movl TEXTURE, %esi #define FOUR_PIXELS(n) \ movl TEXTURE, %esi ; \ movb (%esi, %eax), %al /* read texel */ ; \ movb %al, n+TMP /* store the pixel */ #define WRITE_FOUR_PIXELS() \ movl GLOBL(color_map), %esi /* light four pixels */ ; \ xorl %ecx, %ecx ; \ movl DC, %ebx ; \ movl C, %edx ; \ ; \ movb %dh, %ch /* light pixel 1 */ ; \ movb TMP, %cl ; \ addl %ebx, %edx ; \ movb (%ecx, %esi), %al ; \ ; \ movb %dh, %ch /* light pixel 2 */ ; \ movb 1+TMP, %cl ; \ addl %ebx, %edx ; \ movb (%ecx, %esi), %ah ; \ ; \ roll $16, %eax ; \ ; \ movb %dh, %ch /* light pixel 3 */ ; \ movb 2+TMP, %cl ; \ addl %ebx, %edx ; \ movb (%ecx, %esi), %al ; \ ; \ movb %dh, %ch /* light pixel 4 */ ; \ movb 3+TMP, %cl ; \ addl %ebx, %edx ; \ movb (%ecx, %esi), %ah ; \ ; \ movl %edx, C ; \ roll $16, %eax ; \ movl %eax, FSEG(%edi) /* write four pixels at a time */ ; \ addl $4, %edi DO_PTEX(ptex_lit) #undef INIT #undef SINGLE_PIXEL #undef PREPARE_FOUR_PIXELS #undef FOUR_PIXELS #undef WRITE_FOUR_PIXELS ret /* end of _poly_scanline_ptex_lit8() */ #endif /* COLOR8 */ #undef TMP #undef UMASK #undef VMASK #undef VSHIFT #undef DU1 #undef DV1 #undef DZ1 #undef DU4 #undef DV4 #undef DZ4 #undef UDIFF #undef VDIFF #undef PREVU #undef PREVV #undef COUNT #undef C #undef DC #undef TEXTURE #undef START_FP_DIV #undef END_FP_DIV #undef UPDATE_FP_POS #undef DO_PTEX #define DB -4(%ebp) #define DG -8(%ebp) #define DR -12(%ebp) #define TMP4 -4(%ebp) #define TMP -8(%ebp) #define SB -16(%ebp) #define SG -24(%ebp) #define SR -32(%ebp) /* first part of a grgb routine */ #define INIT_GRGB(depth, r_sft, g_sft, b_sft) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $12, %esp ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ grgb_entry_##depth: ; \ movl INFO, %esi /* load registers */ ; \ ; \ movl POLYSEG_DR(%esi), %ebx /* move delta's on stack */ ; \ movl POLYSEG_DG(%esi), %edi ; \ movl POLYSEG_DB(%esi), %edx ; \ movl %ebx, DR ; \ movl %edi, DG ; \ movl %edx, DB ; \ ; \ movl POLYSEG_R(%esi), %ebx ; \ movl POLYSEG_G(%esi), %edi ; \ movl POLYSEG_B(%esi), %edx ; \ ; \ _align_ ; \ grgb_loop_##depth: ; \ movl %ebx, %eax /* red */ ; \ movb GLOBL(_rgb_r_shift_##depth), %cl ; \ shrl $r_sft, %eax ; \ addl DR, %ebx ; \ shll %cl, %eax ; \ movl %edi, %esi /* green */ ; \ movb GLOBL(_rgb_g_shift_##depth), %cl ; \ shrl $g_sft, %esi ; \ addl DG, %edi ; \ shll %cl, %esi ; \ orl %esi, %eax ; \ movl %edx, %esi /* blue */ ; \ movb GLOBL(_rgb_b_shift_##depth), %cl ; \ shrl $b_sft, %esi ; \ addl DB, %edx ; \ shll %cl, %esi ; \ orl %esi, %eax ; \ movl ADDR, %esi /* end of grgb routine */ #define END_GRGB(depth) \ movl %esi, ADDR ; \ decl W ; \ jg grgb_loop_##depth ; \ ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_grgb15(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_scanline_grgb15) INIT_GRGB(15, 19, 19, 19) movw %ax, FSEG(%esi) /* write the pixel */ addl $2, %esi END_GRGB(15) ret /* end of _poly_scanline_grgb15() */ /* void _poly_scanline_grgb16(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_scanline_grgb16) INIT_GRGB(16, 19, 18, 19) movw %ax, FSEG(%esi) /* write the pixel */ addl $2, %esi END_GRGB(16) ret /* end of _poly_scanline_grgb16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_grgb32(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_scanline_grgb32) INIT_GRGB(32, 16, 16, 16) movl %eax, FSEG(%esi) /* write the pixel */ addl $4, %esi END_GRGB(32) ret /* end of _poly_scanline_grgb32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_grgb24(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_scanline_grgb24) INIT_GRGB(24, 16, 16, 16) movw %ax, FSEG(%esi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%esi) addl $3, %esi END_GRGB(24) ret /* end of _poly_scanline_grgb24() */ #endif /* COLOR24 */ #undef DR #undef DG #undef DB #undef TMP #undef TMP2 #undef TMP4 #undef TMP6 #undef SR #undef SG #undef SB #define VMASK -8(%ebp) #define VSHIFT -16(%ebp) #define DV -20(%ebp) #define DU -24(%ebp) #define ALPHA4 -28(%ebp) #define ALPHA2 -30(%ebp) #define ALPHA -32(%ebp) #define DALPHA4 -36(%ebp) #define DALPHA -40(%ebp) #define UMASK -44(%ebp) #define READ_ADDR -48(%ebp) /* first part of an affine texture mapping operation */ #define INIT_ATEX(extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $48, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ extra ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %eax ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ addl $16, %ecx ; \ movl %ecx, VSHIFT ; \ movl %eax, VMASK ; \ ; \ movl POLYSEG_UMASK(%esi), %eax ; \ movl POLYSEG_DU(%esi), %ebx ; \ movl POLYSEG_DV(%esi), %edx ; \ movl %eax, UMASK ; \ movl %ebx, DU ; \ movl %edx, DV ; \ ; \ movl POLYSEG_U(%esi), %ebx ; \ movl POLYSEG_V(%esi), %edx ; \ movl ADDR, %edi ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ ; \ _align_ ; \ 1: ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax /* end of atex routine */ #define END_ATEX() ; \ addl DU, %ebx ; \ addl DV, %edx ; \ decl W ; \ jg 1b ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_atex16(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex16) INIT_ATEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ addl $2, %edi END_ATEX() ret /* end of _poly_scanline_atex16() */ /* void _poly_scanline_atex_mask15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask15) INIT_ATEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 7f movw %ax, FSEG(%edi) /* write solid pixels */ 7: addl $2, %edi END_ATEX() ret /* end of _poly_scanline_atex_mask15() */ /* void _poly_scanline_atex_mask16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask16) INIT_ATEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 7f movw %ax, FSEG(%edi) /* write solid pixels */ 7: addl $2, %edi END_ATEX() ret /* end of _poly_scanline_atex_mask16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_atex32(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex32) INIT_ATEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ movl %eax, FSEG(%edi) /* write the pixel */ addl $4, %edi END_ATEX() ret /* end of _poly_scanline_atex32() */ /* void _poly_scanline_atex_mask32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask32) INIT_ATEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 7f movl %eax, FSEG(%edi) /* write solid pixels */ 7: addl $4, %edi END_ATEX() ret /* end of _poly_scanline_atex_mask32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_atex24(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex24) INIT_ATEX(/**/) leal (%eax, %eax, 2), %ecx movw (%esi, %ecx), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ movb 2(%esi, %ecx), %al /* read texel */ movb %al, FSEG 2(%edi) /* write the pixel */ addl $3, %edi END_ATEX() ret /* end of _poly_scanline_atex24() */ /* void _poly_scanline_atex_mask24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask24) INIT_ATEX(/**/) leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f movw %ax, FSEG(%edi) /* write solid pixels */ shrl $16, %eax movb %al, FSEG 2(%edi) 7: addl $3, %edi END_ATEX() ret /* end of _poly_scanline_atex_mask24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_atex_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA popl %edx END_ATEX() ret /* end of _poly_scanline_atex_lit15() */ /* void _poly_scanline_atex_mask_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA END_ATEX() ret /* end of _poly_scanline_atex_mask_lit15() */ /* void _poly_scanline_atex_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA popl %edx END_ATEX() ret /* end of _poly_scanline_atex_lit16() */ /* void _poly_scanline_atex_mask_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA END_ATEX() ret /* end of _poly_scanline_atex_mask_lit16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_atex_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movl (%esi, %eax, 4), %eax /* read texel */ pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ movl DALPHA, %eax addl $4, %edi addl %eax, ALPHA popl %edx END_ATEX() ret /* end of _poly_scanline_atex_lit32() */ /* void _poly_scanline_atex_mask_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx 7: movl DALPHA, %eax addl $4, %edi addl %eax, ALPHA END_ATEX() ret /* end of _poly_scanline_atex_mask_lit32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_atex_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx leal (%eax, %eax, 2), %ecx movb 2(%esi, %ecx), %al /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) movl DALPHA, %eax addl $3, %edi addl %eax, ALPHA popl %edx END_ATEX() ret /* end of _poly_scanline_atex_lit24() */ /* void _poly_scanline_atex_mask_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx 7: movl DALPHA, %eax addl $3, %edi addl %eax, ALPHA END_ATEX() ret /* end of _poly_scanline_atex_mask_lit24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_scanline_atex_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edi movzbl (%esi, %eax), %eax /* read texel */ movl READ_ADDR, %edi shll $8, %eax movb FSEG (%edi), %al /* read pixel */ movl GLOBL(color_map), %ecx popl %edi movb (%ecx, %eax), %al movb %al, FSEG(%edi) incl READ_ADDR incl %edi END_ATEX() ret /* end of _poly_scanline_atex_trans8() */ /* void _poly_scanline_atex_mask_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 7f shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) 7: incl READ_ADDR incl %edi END_ATEX() ret /* end of _poly_scanline_atex_mask_trans8() */ #endif /* COLOR8 */ #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_atex_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ addl $2, READ_ADDR addl $2, %edi popl %edx END_ATEX() ret /* end of _poly_scanline_atex_trans15() */ /* void _poly_scanline_atex_mask_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 7f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: addl $2, %edi addl $2, READ_ADDR END_ATEX() ret /* end of _poly_scanline_atex_mask_trans15() */ /* void _poly_scanline_atex_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ addl $2, READ_ADDR addl $2, %edi popl %edx END_ATEX() ret /* end of _poly_scanline_atex_trans16() */ /* void _poly_scanline_atex_mask_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 7f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: addl $2, %edi addl $2, READ_ADDR END_ATEX() ret /* end of _poly_scanline_atex_mask_trans16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_atex_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) movl %edi, ALPHA movl READ_ADDR, %edi pushl FSEG (%edi) movl ALPHA, %edi pushl (%esi, %eax, 4) call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ addl $4, READ_ADDR addl $4, %edi popl %edx END_ATEX() ret /* end of _poly_scanline_atex_trans32() */ /* void _poly_scanline_atex_mask_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 7f pushl %edx pushl GLOBL(_blender_alpha) movl %edi, ALPHA movl READ_ADDR, %edi pushl FSEG (%edi) movl ALPHA, %edi pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx 7: addl $4, %edi addl $4, READ_ADDR END_ATEX() ret /* end of _poly_scanline_atex_mask_trans32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_atex_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) leal (%eax, %eax, 2), %ecx pushl %edi movl READ_ADDR, %edi movb FSEG 2(%edi), %dl movb 2(%esi, %ecx), %al /* read texel */ shll $16, %edx shll $16, %eax movw FSEG (%edi), %dx popl %edi movw (%esi, %ecx), %ax pushl %edx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) addl $3, READ_ADDR addl $3, %edi popl %edx END_ATEX() ret /* end of _poly_scanline_atex_trans24() */ /* void _poly_scanline_atex_mask_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_scanline_atex_mask_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f pushl %edi movl READ_ADDR, %edi movb FSEG 2(%edi), %cl shll $16, %ecx movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx 7: addl $3, %edi addl $3, READ_ADDR END_ATEX() ret /* end of _poly_scanline_atex_mask_trans24() */ #endif /* COLOR24 */ #undef VMASK #undef VSHIFT #undef UMASK #undef DU #undef DV #undef ALPHA #undef ALPHA2 #undef ALPHA4 #undef DALPHA #undef DALPHA4 #undef READ_ADDR #define VMASK -4(%ebp) #define VSHIFT -8(%ebp) #define ALPHA4 -12(%ebp) #define ALPHA -16(%ebp) #define DALPHA4 -20(%ebp) #define DALPHA -24(%ebp) #define TMP4 -28(%ebp) #define TMP2 -30(%ebp) #define TMP -32(%ebp) #define BLEND4 -36(%ebp) #define BLEND2 -38(%ebp) #define BLEND -40(%ebp) #define U1 -44(%ebp) #define V1 -48(%ebp) #define DU -52(%ebp) #define DV -56(%ebp) #define DU4 -60(%ebp) #define DV4 -64(%ebp) #define DZ4 -68(%ebp) #define UMASK -72(%ebp) #define COUNT -76(%ebp) #define SM -80(%ebp) #define SV -84(%ebp) #define SU -88(%ebp) #define SZ -92(%ebp) #define READ_ADDR -96(%ebp) /* helper for starting an fpu 1/z division */ #define START_FP_DIV() \ fld1 ; \ fdiv %st(3), %st(0) /* helper for ending an fpu division, returning corrected u and v values */ #define END_FP_DIV() \ fld %st(0) /* duplicate the 1/z value */ ; \ fmul %st(3), %st(0) /* divide u by z */ ; \ fxch %st(1) ; \ fmul %st(2), %st(0) /* divide v by z */ #define UPDATE_FP_POS_4() \ fadds DV4 /* update v coord */ ; \ fxch %st(1) /* swap vuz stack to uvz */ ; \ fadds DU4 /* update u coord */ ; \ fxch %st(2) /* swap uvz stack to zvu */ ; \ fadds DZ4 /* update z value */ ; \ fxch %st(2) /* swap zvu stack to uvz */ ; \ fxch %st(1) /* swap uvz stack back to vuz */ /* main body of the perspective-correct texture mapping routine */ #define INIT_PTEX(extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $100, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ ; \ flds POLYSEG_Z(%esi) /* z at bottom of fpu stack */ ; \ flds POLYSEG_FU(%esi) /* followed by u */ ; \ flds POLYSEG_FV(%esi) /* followed by v */ ; \ ; \ flds POLYSEG_DFU(%esi) /* multiply diffs by four */ ; \ flds POLYSEG_DFV(%esi) ; \ flds POLYSEG_DZ(%esi) ; \ fxch %st(2) /* u v z */ ; \ fadd %st(0), %st(0) /* 2u v z */ ; \ fxch %st(1) /* v 2u z */ ; \ fadd %st(0), %st(0) /* 2v 2u z */ ; \ fxch %st(2) /* z 2u 2v */ ; \ fadd %st(0), %st(0) /* 2z 2u 2v */ ; \ fxch %st(1) /* 2u 2z 2v */ ; \ fadd %st(0), %st(0) /* 4u 2z 2v */ ; \ fxch %st(2) /* 2v 2z 4u */ ; \ fadd %st(0), %st(0) /* 4v 2z 4u */ ; \ fxch %st(1) /* 2z 4v 4u */ ; \ fadd %st(0), %st(0) /* 4z 4v 4u */ ; \ fxch %st(2) /* 4u 4v 4z */ ; \ fstps DU4 ; \ fstps DV4 ; \ fstps DZ4 ; \ ; \ START_FP_DIV() ; \ ; \ extra ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %eax ; \ movl POLYSEG_UMASK(%esi), %edx ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ addl $16, %ecx ; \ movl %ecx, VSHIFT ; \ movl %eax, VMASK ; \ movl %edx, UMASK ; \ ; \ END_FP_DIV() ; \ fistpl V1 /* store v */ ; \ fistpl U1 /* store u */ ; \ UPDATE_FP_POS_4() ; \ START_FP_DIV() ; \ ; \ movl ADDR, %edi ; \ movl V1, %edx ; \ movl U1, %ebx ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ movl $0, COUNT /* COUNT ranges from 3 to -1 */ ; \ jmp 3f ; \ ; \ _align_ ; \ 1: /* step 2: compute DU, DV for next 4 steps */ ; \ movl $3, COUNT ; \ ; \ END_FP_DIV() /* finish the divide */ ; \ fistpl V1 ; \ fistpl U1 ; \ UPDATE_FP_POS_4() /* 4 pixels away */ ; \ START_FP_DIV() ; \ ; \ movl V1, %eax ; \ movl U1, %ecx ; \ subl %edx, %eax ; \ subl %ebx, %ecx ; \ sarl $2, %eax ; \ sarl $2, %ecx ; \ movl %eax, DV ; \ movl %ecx, DU ; \ 2: /* step 3 & 4: next U, V */ ; \ addl DV, %edx ; \ addl DU, %ebx ; \ 3: /* step 1: just use U and V */ ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax #define END_PTEX() \ decl W ; \ jle 6f ; \ decl COUNT ; \ jg 2b ; \ nop ; \ jl 1b ; \ movl V1, %edx ; \ movl U1, %ebx ; \ jmp 3b ; \ _align_ ; \ 6: ; \ fstp %st(0) /* pop fpu stack */ ; \ fstp %st(0) ; \ fstp %st(0) ; \ fstp %st(0) ; \ ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_ptex16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex16) INIT_PTEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ addl $2, %edi END_PTEX() ret /* end of _poly_scanline_ptex16() */ /* void _poly_scanline_ptex_mask15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask15) INIT_PTEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 7f movw %ax, FSEG(%edi) /* write solid pixels */ 7: addl $2, %edi END_PTEX() ret /* end of _poly_scanline_ptex_mask15() */ /* void _poly_scanline_ptex_mask16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask16) INIT_PTEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 7f movw %ax, FSEG(%edi) /* write solid pixels */ 7: addl $2, %edi END_PTEX() ret /* end of _poly_scanline_ptex_mask16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_ptex32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex32) INIT_PTEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ movl %eax, FSEG(%edi) /* write the pixel */ addl $4, %edi END_PTEX() ret /* end of _poly_scanline_ptex32() */ /* void _poly_scanline_ptex_mask32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask32) INIT_PTEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 7f movl %eax, FSEG(%edi) /* write solid pixels */ 7: addl $4, %edi END_PTEX() ret /* end of _poly_scanline_ptex_mask32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_ptex24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex24) INIT_PTEX(/**/) leal (%eax, %eax, 2), %ecx movw (%esi, %ecx), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ movb 2(%esi, %ecx), %al /* read texel */ movb %al, FSEG 2(%edi) /* write the pixel */ addl $3, %edi END_PTEX() ret /* end of _poly_scanline_ptex24() */ /* void _poly_scanline_ptex_mask24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask24) INIT_PTEX(/**/) leal (%eax, %eax, 2), %ecx xorl %eax, %eax movb 2(%esi, %ecx), %al /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f movw %ax, FSEG(%edi) /* write solid pixels */ shrl $16, %eax movb %al, FSEG 2(%edi) 7: addl $3, %edi END_PTEX() ret /* end of _poly_scanline_ptex_mask24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_scanline_ptex_mask_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 7f movb 2+ALPHA, %ah movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) 7: movl DALPHA, %eax incl %edi addl %eax, ALPHA END_PTEX() ret /* end of _poly_scanline_ptex_mask_lit8() */ #endif /* COLOR8 */ #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_ptex_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_lit15() */ /* void _poly_scanline_ptex_mask_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA END_PTEX() ret /* end of _poly_scanline_ptex_mask_lit15() */ /* void _poly_scanline_ptex_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_lit16() */ /* void _poly_scanline_ptex_mask_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: movl DALPHA, %eax addl $2, %edi addl %eax, ALPHA END_PTEX() ret /* end of _poly_scanline_ptex_mask_lit16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_ptex_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movl (%esi, %eax, 4), %eax /* read texel */ pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ movl DALPHA, %eax addl $4, %edi addl %eax, ALPHA popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_lit32() */ /* void _poly_scanline_ptex_mask_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx 7: movl DALPHA, %eax addl $4, %edi addl %eax, ALPHA END_PTEX() ret /* end of _poly_scanline_ptex_mask_lit32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_ptex_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx leal (%eax, %eax, 2), %ecx movb 2(%esi, %ecx), %al /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) movl DALPHA, %eax addl $3, %edi addl %eax, ALPHA popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_lit24() */ /* void _poly_scanline_ptex_mask_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx 7: movl DALPHA, %eax addl $3, %edi addl %eax, ALPHA END_PTEX() ret /* end of _poly_scanline_ptex_mask_lit24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_scanline_ptex_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) incl READ_ADDR incl %edi END_PTEX() ret /* end of _poly_scanline_ptex_trans8() */ /* void _poly_scanline_ptex_mask_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 7f shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) 7: incl READ_ADDR incl %edi END_PTEX() ret /* end of _poly_scanline_ptex_mask_trans8() */ #endif /* COLOR8 */ #ifdef ALLEGRO_COLOR16 /* void _poly_scanline_ptex_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ addl $2, READ_ADDR addl $2, %edi popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_trans15() */ /* void _poly_scanline_ptex_mask_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 7f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: addl $2, %edi addl $2, READ_ADDR END_PTEX() ret /* end of _poly_scanline_ptex_mask_trans15() */ /* void _poly_scanline_ptex_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ addl $2, READ_ADDR addl $2, %edi popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_trans16() */ /* void _poly_scanline_ptex_mask_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 7f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx 7: addl $2, %edi addl $2, READ_ADDR END_PTEX() ret /* end of _poly_scanline_ptex_mask_trans16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_scanline_ptex_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) movl %edi, TMP movl READ_ADDR, %edi pushl FSEG (%edi) movl TMP, %edi pushl (%esi, %eax, 4) call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ addl $4, READ_ADDR addl $4, %edi popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_trans32() */ /* void _poly_scanline_ptex_mask_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 7f pushl %edx pushl GLOBL(_blender_alpha) movl %edi, TMP movl READ_ADDR, %edi pushl FSEG (%edi) movl TMP, %edi pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx 7: addl $4, %edi addl $4, READ_ADDR END_PTEX() ret /* end of _poly_scanline_ptex_mask_trans32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_scanline_ptex_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) leal (%eax, %eax, 2), %ecx pushl %edi movl READ_ADDR, %edi movb FSEG 2(%edi), %dl movb 2(%esi, %ecx), %al /* read texel */ shll $16, %edx shll $16, %eax movw FSEG (%edi), %dx popl %edi movw (%esi, %ecx), %ax pushl %edx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) addl $3, READ_ADDR addl $3, %edi popl %edx END_PTEX() ret /* end of _poly_scanline_ptex_trans24() */ /* void _poly_scanline_ptex_mask_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_scanline_ptex_mask_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi) ,%eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f movl %edi, TMP movl READ_ADDR, %edi movb FSEG 2(%edi), %cl pushl %edx pushl GLOBL(_blender_alpha) shll $16, %ecx movw FSEG (%edi), %cx movl TMP, %edi pushl %ecx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx 7: addl $3, %edi addl $3, READ_ADDR END_PTEX() ret /* end of _poly_scanline_ptex_mask_trans24() */ #endif /* COLOR24 */ allegro-4.4.3.1/src/i386/ispr24.s0000664000175000017500000007403513437077643015100 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit sprite drawing (written for speed, not readability :-) * * By Michal Mertl. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "sprite.inc" #ifdef ALLEGRO_COLOR24 .text /* void _linear_draw_sprite24(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite onto a linear bitmap at the specified x, y position, * using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_sprite24) START_SPRITE_DRAW(sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %ebx leal (%ebx, %ebx, 2), %ebx /* X *= 3 */ movl %ebx, S_X movl S_LGAP, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(draw_sprite) movl (%esi), %ebx /* read a pixel */ andl $0xFFFFFF,%ebx cmpl $MASK_COLOR_24, %ebx /* test */ jz draw_sprite_skip movw %bx, %es:(%eax) /* write */ shrl $16, %ebx movb %bl, %es:2(%eax) _align_ draw_sprite_skip: addl $3, %esi addl $3, %eax SPRITE_END_X(draw_sprite) SPRITE_END_Y(draw_sprite) _align_ sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite24() */ FUNC(_linear_draw_sprite24_end) ret /* void _linear_draw_256_sprite24(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a 256 color sprite onto a linear bitmap at the specified x, y * position, using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_256_sprite24) START_SPRITE_DRAW(sprite256) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X,%ebx leal (%ebx, %ebx, 2), %ebx movl %ebx,S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ pushl %edx /* get color expansion lookup table */ pushl $24 call *GLOBL(_palette_expansion_table) addl $4, %esp popl %edx movl %eax, %edi _align_ SPRITE_LOOP(draw_sprite256) movzbl (%esi), %ebx /* read a pixel */ orb %bl, %bl /* test */ jz draw_256_sprite_skip movl (%edi, %ebx, 4), %ebx /* lookup in palette table */ movw %bx, %es:(%eax) /* write */ shrl $16, %ebx movb %bl, %es:2(%eax) _align_ draw_256_sprite_skip: incl %esi addl $3, %eax SPRITE_END_X(draw_sprite256) SPRITE_END_Y(draw_sprite256) _align_ sprite256_done: END_SPRITE_DRAW() ret /* end of _linear_draw_256_sprite24() */ /* void _linear_draw_sprite_v_flip24(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping vertically. */ FUNC(_linear_draw_sprite_v_flip24) START_SPRITE_DRAW(sprite_v_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ addl S_W, %eax addl S_W, %eax addl S_W, %eax /* + w */ negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_X movl S_LGAP, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx,S_LGAP negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(v_flip) movl (%esi), %ebx /* read pixel */ andl $0xFFFFFF, %ebx cmpl $MASK_COLOR_24, %ebx /* test */ je sprite_v_flip_skip movw %bx, %es:(%eax) /* write */ shrl $16, %ebx movb %bl, %es:2(%eax) _align_ sprite_v_flip_skip: addl $3, %esi addl $3, %eax SPRITE_END_X(v_flip) SPRITE_END_Y(v_flip) sprite_v_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_v_flip24() */ /* void _linear_draw_sprite_h_flip24(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping horizontally. */ FUNC(_linear_draw_sprite_h_flip24) START_SPRITE_DRAW(sprite_h_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ addl S_W, %eax addl S_W, %eax addl S_W, %eax /* + w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_X movl S_LGAP, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_LGAP movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi leal (%ecx, %ecx, 2), %ecx leal (%esi, %ecx), %esi subl S_LGAP, %esi subl $3, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(h_flip) movl (%esi), %ebx /* read pixel */ andl $0xFFFFFF, %ebx cmpl $MASK_COLOR_24, %ebx /* test */ je sprite_h_flip_skip movw %bx,%es:(%eax) shrl $16, %ebx movb %bl, %es:2(%eax) /* write */ sprite_h_flip_skip: subl $3, %esi addl $3, %eax SPRITE_END_X(h_flip) SPRITE_END_Y(h_flip) sprite_h_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_h_flip24() */ /* void _linear_draw_sprite_vh_flip24(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping both vertically and horizontally. */ FUNC(_linear_draw_sprite_vh_flip24) START_SPRITE_DRAW(sprite_vh_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax subl S_W, %eax /* - w */ negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_X movl S_LGAP, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_LGAP negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi leal (%ecx, %ecx, 2), %ecx leal (%esi, %ecx), %esi subl S_LGAP, %esi subl $3, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(vh_flip) movl (%esi), %ebx /* read pixel */ andl $0xFFFFFF, %ebx cmpl $MASK_COLOR_24, %ebx /* test */ je sprite_vh_flip_skip movw %bx, %es:(%eax) shrl $16, %ebx movb %bl, %es:2(%eax) /* write */ sprite_vh_flip_skip: subl $3, %esi addl $3, %eax SPRITE_END_X(vh_flip) SPRITE_END_Y(vh_flip) sprite_vh_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_vh_flip24() */ /* void _linear_draw_trans_sprite24(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a translucent sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_sprite24) START_SPRITE_DRAW(trans_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %edi leal (%edi, %edi, 2), %edi movl %edi, S_X movl S_LGAP, %edi leal (%edi, %edi, 2), %edi movl %edi, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans, %edi) movl (%esi), %eax /* read source pixel */ andl $0xFFFFFF, %eax cmpl $MASK_COLOR_24, %eax jz trans_sprite_skip pushl GLOBL(_blender_alpha) pushl %es:(%ebx, %edi) /* read memory pixel */ pushl %eax call *GLOBL(_blender_func24) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ shrl $16, %eax movb %al, %es:2(%ebx) trans_sprite_skip: addl $3, %ebx addl $3, %esi T_SPRITE_END_X(trans) /* no cleanup at end of line */ SPRITE_END_Y(trans) trans_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_trans_sprite24() */ /* void _linear_draw_trans_rgba_sprite24(BITMAP *bmp, sprite, int x, y); * Draws a translucent 32 bit sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_sprite24) START_SPRITE_DRAW(trans_rgba_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %edi leal (%edi, %edi, 2), %edi movl %edi, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans_rgba, %edi) movl (%esi), %eax /* read source pixel */ cmpl $MASK_COLOR_32, %eax jz trans_rgba_sprite_skip pushl GLOBL(_blender_alpha) pushl %es:(%ebx, %edi) /* read memory pixel */ pushl %eax call *GLOBL(_blender_func24x) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ shrl $16, %eax movb %al, %es:2(%ebx) trans_rgba_sprite_skip: addl $3, %ebx addl $4, %esi T_SPRITE_END_X(trans_rgba) /* no cleanup at end of line */ SPRITE_END_Y(trans_rgba) trans_rgba_sprite_done: END_SPRITE_DRAW() ret /* end _linear_draw_trans_rgba_sprite24() */ /* void _linear_draw_lit_sprite24(BITMAP *bmp, BITMAP *sprite, int x, y, color); * Draws a lit sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_sprite24) #define ALPHA ARG5 START_SPRITE_DRAW(lit_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %edi leal (%edi, %edi, 2), %edi movl %edi, S_X movl S_LGAP, %edi leal (%edi, %edi, 2), %edi movl %edi, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl ALPHA, %edi _align_ LT_SPRITE_LOOP(lit_sprite) movl (%esi), %eax /* read pixel */ andl $0xFFFFFF, %eax cmpl $MASK_COLOR_24, %eax jz lit_sprite_skip pushl %edi pushl %eax pushl GLOBL(_blender_col_24) call *GLOBL(_blender_func24) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write pixel */ shrl $16, %eax movb %al, %es:2(%ebx) lit_sprite_skip: addl $3, %esi addl $3, %ebx T_SPRITE_END_X(lit_sprite) SPRITE_END_Y(lit_sprite) lit_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_lit_sprite24() */ /* void _linear_draw_character24(BITMAP *bmp, BITMAP *sprite, int x, y, color, bg); * For proportional font output onto a linear bitmap: uses the sprite as * a mask, replacing all set pixels with the specified color. */ FUNC(_linear_draw_character24) #define COLOR ARG5 #define BG ARG6 /* sets up the inner sprite drawing loop, loads registers, etc */ #define SPRITE_LOOP24(name) \ sprite_y_loop_##name: ; \ movl S_Y, %eax /* load line */ ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ WRITE_BANK() /* select bank */ ; \ addl S_X, %eax /* add x offset */ ; \ movl S_W, %ecx /* x loop counter */ ; \ movl S_MASK, %edx /* color value */ ; \ _align_ ; \ sprite_x_loop_##name: START_SPRITE_DRAW(draw_char) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl S_X, %ebx leal (%ebx, %ebx, 2), %ebx movl %ebx, S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl COLOR, %ebx /* bx = text color */ movl BG, %edi /* di = background color */ movb 2+COLOR, %dl /* dl = text color high byte */ movb 2+BG, %dh /* dh = background color high byte */ movl %edx, S_MASK /* store */ cmpl $0, %edi jl draw_masked_char /* opaque (bg >= 0) character output */ _align_ SPRITE_LOOP24(draw_opaque_char) cmpb $0, (%esi) /* test pixel */ jz draw_opaque_background movw %bx, %es:(%eax) /* write pixel */ movb %dl, %es:2(%eax) jmp draw_opaque_done draw_opaque_background: movw %di, %es:(%eax) /* write background */ movb %dh, %es:2(%eax) draw_opaque_done: incl %esi addl $3, %eax SPRITE_END_X(draw_opaque_char) SPRITE_END_Y(draw_opaque_char) jmp draw_char_done /* masked (bg -1) character output */ _align_ draw_masked_char: SPRITE_LOOP24(draw_masked_char) cmpb $0, (%esi) /* test pixel */ jz draw_masked_skip movw %bx, %es:(%eax) /* write pixel */ movb %dl, %es:2(%eax) draw_masked_skip: incl %esi addl $3, %eax SPRITE_END_X(draw_masked_char) SPRITE_END_Y(draw_masked_char) draw_char_done: END_SPRITE_DRAW() ret /* end of _linear_draw_character24() */ /* void _linear_draw_rle_sprite24(BITMAP *bmp, RLE_SPRITE *sprite, int x, y) * Draws an RLE sprite onto a linear bitmap at the specified position. */ FUNC(_linear_draw_rle_sprite24) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%edi, %edi, 2), %edi ; \ addl %eax, %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ rle24_loop_##n: ; \ lodsl ; \ movw %ax, %es:(%edi) ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $3, %edi ; \ decl %ecx ; \ jg rle24_loop_##n /* no special initialisation required */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ SLOW_RLE_RUN(fast) /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpl $MASK_COLOR_24, %eax ; \ je done ; \ testl %eax, %eax ; \ js skip /* adds the offset in %eax onto the destination address */ #define ADD_EAX_EDI() \ leal (%edi, %eax, 2), %edi ; \ addl %eax, %edi /* no zero extend required */ #define RLE_ZEX_EAX() /* this can be a simple copy... */ #define RLE_ZEX_ECX() \ movl %eax, %ecx /* no sign extend required */ #define RLE_SEX_EAX() /* do it! */ DO_RLE(rle, 4, l, %eax, $MASK_COLOR_24) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_trans_rle_sprite24(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rle_sprite24) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%edi, %edi, 2), %edi ; \ addl %eax, %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func24) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $4, %esi ; \ addl $3, %edi ; \ decl R_TMP2 ; \ jg trans_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func24) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $4, %esi ; \ addl $3, %edi ; \ decl R_TMP2 ; \ jg trans_rle_run_loop /* do it! */ DO_RLE(rle_trans, 4, l, %eax, $MASK_COLOR_24) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_lit_rle_sprite24(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y, int color) * Draws a tinted RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_rle_sprite24) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%edi, %edi, 2), %edi ; \ addl %eax, %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl R_COLOR, %ebx ; \ movl %ecx, R_TMP ; \ ; \ lit_rle_clipped_run_loop##n: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_24) ; \ call *GLOBL(_blender_func24) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $4, %esi ; \ addl $3, %edi ; \ decl R_TMP ; \ jg lit_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ movl R_COLOR, %ebx /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP ; \ ; \ lit_rle_run_loop: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_24) ; \ call *GLOBL(_blender_func24) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $4, %esi ; \ addl $3, %edi ; \ decl R_TMP ; \ jg lit_rle_run_loop /* do it! */ DO_RLE(rle_lit, 4, l, %eax, $MASK_COLOR_24) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #undef TEST_RLE_COMMAND #undef RLE_ZEX_EAX #undef RLE_ZEX_ECX #undef RLE_SEX_EAX /* void _linear_draw_trans_rgba_rle_sprite24(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent 32 bit RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_rle_sprite24) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%edi, %edi, 2), %edi ; \ addl %eax, %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func24x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $4, %esi ; \ addl $3, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func24x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ shrl $16, %eax ; \ movb %al, %es:2(%edi) ; \ addl $4, %esi ; \ addl $3, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_run_loop /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpl $MASK_COLOR_32, %eax ; \ je done ; \ testl %eax, %eax ; \ js skip /* no zero or sign extend required */ #define RLE_ZEX_EAX() #define RLE_SEX_EAX() /* this can be a simple copy... */ #define RLE_ZEX_ECX() \ movl %eax, %ecx /* do it! */ DO_RLE(rle_trans_rgba, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #endif /* ifdef ALLEGRO_COLOR24 */ allegro-4.4.3.1/src/i386/igfx32.s0000664000175000017500000002701013437077643015046 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit linear graphics functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #ifdef ALLEGRO_COLOR32 .text /* void _linear_putpixel32(BITMAP *bmp, int x, int y, int color); * Draws a pixel onto a linear bitmap. */ FUNC(_linear_putpixel32) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ je putpix_noclip cmpl %ecx, BMP_CL(%edx) /* test cl */ jg putpix_done cmpl %ecx, BMP_CR(%edx) /* test cr */ jle putpix_done cmpl %eax, BMP_CT(%edx) /* test ct */ jg putpix_done cmpl %eax, BMP_CB(%edx) /* test cb */ jle putpix_done putpix_noclip: movw BMP_SEG(%edx), %es /* segment selector */ movl ARG4, %ebx /* bx = color */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je putpix_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) je putpix_xor_mode /* XOR? */ cmpl $DRAW_TRANS, GLOBL(_drawing_mode) je putpix_trans_mode /* translucent? */ LOOKUP_PATTERN_POS(%ecx, %eax, %edx) movl (%eax, %ecx, 4), %ebx /* read pixel from pattern bitmap */ movl ARG1, %edx /* reload clobbered registers */ movl ARG2, %ecx movl ARG3, %eax cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je putpix_solid_mode /* draw the pattern pixel? */ cmpl $MASK_COLOR_32, %ebx /* test the pattern pixel */ je putpix_zero_pattern movl ARG4, %ebx /* if set, draw color */ jmp putpix_solid_mode _align_ putpix_zero_pattern: cmpl $DRAW_MASKED_PATTERN, GLOBL(_drawing_mode) je putpix_done /* skip zero pixels in masked mode */ xorl %ebx, %ebx jmp putpix_solid_mode /* draw zero pixels in solid mode */ _align_ putpix_xor_mode: READ_BANK() /* read pixel from screen, and XOR it */ xorl %es:(%eax, %ecx, 4), %ebx movl ARG3, %eax /* re-read Y position */ jmp putpix_solid_mode _align_ putpix_trans_mode: READ_BANK() pushl %ecx pushl %edx pushl GLOBL(_blender_alpha) pushl %es:(%eax, %ecx, 4) /* read pixel from screen */ pushl %ebx /* and the drawing color */ call *GLOBL(_blender_func32) /* blend */ addl $12, %esp popl %edx popl %ecx movl %eax, %ebx movl ARG3, %eax /* re-read Y position */ _align_ putpix_solid_mode: WRITE_BANK() /* write the pixel */ movl %ebx, %es:(%eax, %ecx, 4) putpix_done: popw %es UNWRITE_BANK() popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_putpixel32() */ /* int _linear_getpixel32(BITMAP *bmp, int x, int y); * Reads a pixel from a linear bitmap. */ FUNC(_linear_getpixel32) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ testl %ecx, %ecx /* test that we are on the bitmap */ jl getpix_skip cmpl %ecx, BMP_W(%edx) jle getpix_skip testl %eax, %eax jl getpix_skip cmpl %eax, BMP_H(%edx) jg getpix_ok _align_ getpix_skip: /* return -1 if we are off the edge */ movl $-1, %ebx jmp getpix_done _align_ getpix_ok: READ_BANK() /* select the bank */ movw BMP_SEG(%edx), %es /* segment selector */ movl %es:(%eax, %ecx, 4), %ebx getpix_done: popw %es UNWRITE_BANK() movl %ebx, %eax popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_getpixel32() */ /* void _linear_hline32(BITMAP *bmp, int x1, int y, int x2, int color); * Draws a horizontal line onto a linear bitmap. */ FUNC(_linear_hline32) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ebx /* ebx = x1 */ movl ARG3, %eax /* eax = y */ movl ARG4, %ecx /* ecx = x2 */ cmpl %ebx, %ecx jge hline_no_xswap xchgl %ecx, %ebx hline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je hline_noclip cmpl BMP_CT(%edx), %eax /* test bmp->ct */ jl hline_done cmpl BMP_CB(%edx), %eax /* test bmp->cb */ jge hline_done cmpl BMP_CL(%edx), %ebx /* test x1, bmp->cl */ jge hline_x1_ok cmpl BMP_CL(%edx), %ecx /* test x2, bmp->cl */ jl hline_done movl BMP_CL(%edx), %ebx /* clip x1 */ hline_x1_ok: cmpl BMP_CR(%edx), %ecx /* test x2, bmp->cr */ jl hline_noclip cmpl BMP_CR(%edx), %ebx /* test x1, bmp->cr */ jge hline_done movl BMP_CR(%edx), %ecx /* clip x2 */ decl %ecx hline_noclip: subl %ebx, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* segment selector */ WRITE_BANK() /* select write bank */ leal (%eax, %ebx, 4), %edi /* dest address in edi */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je hline_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) jne hline_not_xor /* XOR? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%eax, %ebx, 4), %esi /* source address in esi */ movl ARG5, %ebx /* read the color */ _align_ hline_xor_loop: movl %es:(%esi), %eax /* read a pixel */ xorl %ebx, %eax /* xor */ movl %eax, %es:(%edi) /* and write it */ addl $4, %esi addl $4, %edi decl %ecx jg hline_xor_loop jmp hline_done _align_ hline_not_xor: cmpl $DRAW_TRANS, GLOBL(_drawing_mode) jne hline_not_trans /* translucent? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%eax, %ebx, 4), %esi /* source address in esi */ movl %ecx, ARG4 /* loop counter on the stack */ _align_ hline_trans_loop: pushl GLOBL(_blender_alpha) pushl %es:(%esi) /* read pixel from screen */ pushl ARG5 /* and the drawing color */ call *GLOBL(_blender_func32) /* blend */ addl $12, %esp movl %eax, %es:(%edi) /* and write it */ addl $4, %esi addl $4, %edi decl ARG4 jg hline_trans_loop jmp hline_done _align_ hline_not_trans: movl ARG3, %eax /* get position in pattern bitmap */ LOOKUP_PATTERN_POS(%ebx, %eax, %edx) movl %eax, %esi movl GLOBL(_drawing_x_mask), %edx cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je hline_copy_pattern_loop cmpl $DRAW_SOLID_PATTERN, GLOBL(_drawing_mode) je hline_solid_pattern_loop _align_ hline_masked_pattern_loop: movl (%esi, %ebx, 4), %eax /* read a pixel */ cmpl $MASK_COLOR_32, %eax /* test it */ je hline_masked_skip movl ARG5, %eax movl %eax, %es:(%edi) /* write a colored pixel */ hline_masked_skip: incl %ebx andl %edx, %ebx addl $4, %edi decl %ecx jg hline_masked_pattern_loop jmp hline_done _align_ hline_copy_pattern_loop: movl (%esi, %ebx, 4), %eax /* read a pixel */ movl %eax, %es:(%edi) /* and write it */ incl %ebx andl %edx, %ebx addl $4, %edi decl %ecx jg hline_copy_pattern_loop jmp hline_done _align_ hline_solid_pattern_loop: movl (%esi, %ebx, 4), %eax /* read a pixel */ cmpl $MASK_COLOR_32, %eax /* test it */ je hline_solid_zero movl ARG5, %eax movl %eax, %es:(%edi) /* write a colored pixel */ incl %ebx andl %edx, %ebx addl $4, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_zero: movl $0, %es:(%edi) /* write a zero pixel */ incl %ebx andl %edx, %ebx addl $4, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_mode: /* regular hline drawer */ movl ARG5, %eax cld rep ; stosl /* draw the line */ hline_done: popw %es movl ARG1, %edx UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_hline32 */ /* void _linear_vline32(BITMAP *bmp, int x, int y1, int y2, int color); * Draws a vertical line onto a linear bitmap. */ FUNC(_linear_vline32) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %edi /* edi = x */ movl ARG3, %esi /* esi = y1 */ movl ARG4, %ecx /* ecx = y2 */ cmpl %esi, %ecx jge vline_no_xswap xchgl %ecx, %esi vline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je vline_noclip cmpl BMP_CL(%edx), %edi /* test bmp->cl */ jl vline_done cmpl BMP_CR(%edx), %edi /* test bmp->cr */ jge vline_done cmpl BMP_CT(%edx), %esi /* test y1, bmp->ct */ jge vline_y1_ok cmpl BMP_CT(%edx), %ecx /* test y2, bmp->ct */ jl vline_done movl BMP_CT(%edx), %esi /* clip y1 */ vline_y1_ok: cmpl BMP_CB(%edx), %ecx /* test y2, bmp->cb */ jl vline_noclip cmpl BMP_CB(%edx), %esi /* test y1, bmp->cb */ jge vline_done movl BMP_CB(%edx), %ecx /* clip y2 */ decl %ecx vline_noclip: subl %esi, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* load segment */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je vline_solid_mode /* solid draw? */ movl BMP_CLIP(%edx), %eax /* store destination clipping flag */ pushl %eax movl $0, BMP_CLIP(%edx) /* turn clipping off (we already did it) */ movl ARG5, %eax pushl %eax /* push color */ pushl %esi /* push y */ pushl %edi /* push x */ pushl %edx /* push bitmap */ movl %ecx, %ebx /* ebx = loop counter */ _align_ vline_special_mode_loop: /* vline drawer for funny modes */ call GLOBL(_linear_putpixel32)/* draw the pixel */ incl 8(%esp) /* next y */ decl %ebx jg vline_special_mode_loop /* loop */ popl %edx /* clean up stack */ addl $12, %esp popl %eax movl %eax, BMP_CLIP(%edx) /* restore bitmap clipping flag */ jmp vline_done _align_ vline_solid_mode: /* normal vline drawer */ movl ARG5, %ebx /* get color */ _align_ vline_loop: movl %esi, %eax WRITE_BANK() /* select bank */ movl %ebx, %es:(%eax, %edi, 4) incl %esi decl %ecx jg vline_loop /* loop */ vline_done: popw %es UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_vline32() */ #endif /* ifdef ALLEGRO_COLOR32 */ allegro-4.4.3.1/src/i386/igfx24.s0000664000175000017500000003463313437077643015060 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit linear graphics functions. * * By Michal Mertl. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #ifdef ALLEGRO_COLOR24 .text /* void _linear_putpixel24(BITMAP *bmp, int x, int y, int color); * Draws a pixel onto a linear bitmap. */ FUNC(_linear_putpixel24) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ je putpix_noclip cmpl %ecx, BMP_CL(%edx) /* test cl */ jg putpix_done cmpl %ecx, BMP_CR(%edx) /* test cr */ jle putpix_done cmpl %eax, BMP_CT(%edx) /* test ct */ jg putpix_done cmpl %eax, BMP_CB(%edx) /* test cb */ jle putpix_done putpix_noclip: movw BMP_SEG(%edx), %es /* segment selector */ movl ARG4, %ebx /* bx = color */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je putpix_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) je putpix_xor_mode /* XOR? */ cmpl $DRAW_TRANS, GLOBL(_drawing_mode) je putpix_trans_mode /* translucent? */ LOOKUP_PATTERN_POS(%ecx, %eax, %edx) leal (%ecx, %ecx, 2), %ecx movl (%eax, %ecx), %ebx /* read pixel from pattern bitmap */ andl $0xFFFFFF, %ebx movl ARG1, %edx /* reload clobbered registers */ movl ARG2, %ecx movl ARG3, %eax cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je putpix_solid_mode /* draw the pattern pixel? */ cmpl $MASK_COLOR_24, %ebx /* test the pattern pixel */ je putpix_zero_pattern movl ARG4, %ebx /* if set, draw color */ jmp putpix_solid_mode _align_ putpix_zero_pattern: cmpl $DRAW_MASKED_PATTERN, GLOBL(_drawing_mode) je putpix_done /* skip zero pixels in masked mode */ xorl %ebx, %ebx jmp putpix_solid_mode /* draw zero pixels in solid mode */ _align_ putpix_xor_mode: READ_BANK() /* read pixel from screen, and XOR it */ leal (%ecx, %ecx, 2), %ecx /* ecx *= 3 */ movl %es:(%eax, %ecx), %eax xorl %eax, %ebx movl ARG3, %eax /* re-read Y position */ WRITE_BANK() movw %bx, %es:(%eax, %ecx) shrl $16, %ebx movb %bl, %es:2(%eax, %ecx) jmp putpix_done _align_ putpix_trans_mode: READ_BANK() leal (%ecx, %ecx, 2), %ecx /* ecx *= 3 */ pushl %ecx pushl %edx pushl GLOBL(_blender_alpha) pushl %es:(%eax, %ecx) /* read pixel from screen */ pushl %ebx /* and the drawing color */ call *GLOBL(_blender_func24) /* blend */ addl $12, %esp popl %edx popl %ecx movl %eax, %ebx movl ARG3, %eax /* re-read Y position */ WRITE_BANK() movw %bx, %es:(%eax, %ecx) shrl $16, %ebx movb %bl, %es:2(%eax, %ecx) jmp putpix_done _align_ putpix_solid_mode: WRITE_BANK() /* write the pixel */ leal (%ecx, %ecx, 2), %ecx movw %bx, %es:(%eax, %ecx) shrl $16, %ebx movb %bl, %es:2(%eax, %ecx) putpix_done: popw %es UNWRITE_BANK() popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_putpixel24() */ /* int _linear_getpixel24(BITMAP *bmp, int x, int y); * Reads a pixel from a linear bitmap. */ FUNC(_linear_getpixel24) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es xorl %eax, %eax xorl %edx, %edx movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ testl %ecx, %ecx /* test that we are on the bitmap */ jl getpix_skip cmpl %ecx, BMP_W(%edx) jle getpix_skip testl %eax, %eax jl getpix_skip cmpl %eax, BMP_H(%edx) jg getpix_ok _align_ getpix_skip: /* return -1 if we are off the edge */ movl $-1, %ebx jmp getpix_done _align_ getpix_ok: READ_BANK() /* select the bank */ movw BMP_SEG(%edx), %es /* segment selector */ leal (%ecx, %ecx, 2), %ecx movl %es:(%eax, %ecx), %ebx andl $0xFFFFFF, %ebx getpix_done: popw %es UNWRITE_BANK() movl %ebx, %eax popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_getpixel24() */ /* void _linear_hline24(BITMAP *bmp, int x1, int y, int x2, int color); * Draws a horizontal line onto a linear bitmap. */ FUNC(_linear_hline24) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ebx /* ebx = x1 */ movl ARG3, %eax /* eax = y */ movl ARG4, %ecx /* ecx = x2 */ cmpl %ebx, %ecx jge hline_no_xswap xchgl %ecx, %ebx hline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je hline_noclip cmpl BMP_CT(%edx), %eax /* test bmp->ct */ jl hline_done cmpl BMP_CB(%edx), %eax /* test bmp->cb */ jge hline_done cmpl BMP_CL(%edx), %ebx /* test x1, bmp->cl */ jge hline_x1_ok cmpl BMP_CL(%edx), %ecx /* test x2, bmp->cl */ jl hline_done movl BMP_CL(%edx), %ebx /* clip x1 */ hline_x1_ok: cmpl BMP_CR(%edx), %ecx /* test x2, bmp->cr */ jl hline_noclip cmpl BMP_CR(%edx), %ebx /* test x1, bmp->cr */ jge hline_done movl BMP_CR(%edx), %ecx /* clip x2 */ decl %ecx hline_noclip: subl %ebx, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* segment selector */ WRITE_BANK() /* select write bank */ pushl %ebx leal (%ebx, %ebx, 2), %ebx /* ebx *= 3 */ leal (%eax, %ebx), %edi /* dest address in edi=eax+ebx */ popl %ebx cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je hline_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) jne hline_not_xor /* XOR? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%ebx, %ebx, 2), %ebx leal (%eax, %ebx), %esi /* source address in esi */ movl ARG5, %eax /* pixel color */ movl %eax, %ebx movl %eax, ARG2 /* ARG2 == 12(%ebp) */ movl %eax, 15(%ebp) /* overwrite ARG2, ARG3, ARG4 */ movl %eax, 18(%ebp) movw %ax, 21(%ebp) shrl $16, %eax movb %al, 23(%ebp) cmpl $4, %ecx jb hline_xor_short subl $4, %ecx _align_ hline_xor_loop: movl %es:(%esi), %eax /* read 1st 4 bytes */ xorl ARG2, %eax /* xor it */ movl %eax, %es:(%edi) /* write it back */ movl %es:4(%esi), %eax /* 2nd 4 bytes */ xorl ARG3, %eax movl %eax, %es:4(%edi) movl %es:8(%esi), %eax /* 3rd 4 bytes */ xorl ARG4, %eax movl %eax, %es:8(%edi) addl $12, %esi addl $12, %edi subl $4, %ecx jns hline_xor_loop addl $4, %ecx jz hline_done _align_ hline_xor_short: movl %es:(%esi), %eax xorl ARG5, %eax /* xor */ movw %ax, %es:(%edi) shrl $16, %eax movb %al, %es:2(%edi) addl $3, %esi addl $3, %edi decl %ecx jg hline_xor_short jmp hline_done _align_ hline_not_xor: cmpl $DRAW_TRANS, GLOBL(_drawing_mode) jne hline_not_trans /* translucent? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%ebx, %ebx, 2), %ebx leal (%eax, %ebx), %esi /* source address in esi */ movl %ecx, ARG4 /* loop counter on the stack */ _align_ hline_trans_loop: pushl GLOBL(_blender_alpha) pushl %es:(%esi) /* read pixel from screen */ pushl ARG5 /* and the drawing color */ call *GLOBL(_blender_func24) /* blend */ addl $12, %esp movw %ax, %es:(%edi) /* and write it */ shrl $16, %eax movb %al, %es:2(%edi) addl $3, %esi addl $3, %edi decl ARG4 jg hline_trans_loop jmp hline_done _align_ hline_not_trans: movl ARG3, %eax /* get position in pattern bitmap */ movl ARG2, %ebx LOOKUP_PATTERN_POS(%ebx, %eax, %edx) movl %eax, %esi movl GLOBL(_drawing_x_mask), %edx cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je hline_copy_pattern cmpl $DRAW_SOLID_PATTERN, GLOBL(_drawing_mode) je hline_solid_pattern_loop _align_ hline_masked_pattern_loop: leal (%ebx, %ebx, 2), %eax movl (%esi, %eax), %eax /* read a pixel */ andl $0xFFFFFF, %eax cmpl $MASK_COLOR_24, %eax /* test it */ je hline_masked_skip movl ARG5, %eax movw %ax, %es:(%edi) shrl $16, %eax movb %al, %es:2(%edi) _align_ hline_masked_skip: incl %ebx andl %edx, %ebx addl $3, %edi decl %ecx jg hline_masked_pattern_loop jmp hline_done hline_copy_pattern: decl %ecx jz short_copy_pattern _align_ hline_copy_pattern_loop: leal (%ebx, %ebx, 2), %eax movl (%esi, %eax), %eax /* read a pixel */ movl %eax, %es:(%edi) incl %ebx andl %edx, %ebx addl $3, %edi decl %ecx jg hline_copy_pattern_loop short_copy_pattern: leal (%ebx, %ebx, 2), %eax movl (%esi, %eax), %eax /* read a pixel */ movw %ax, %es:(%edi) shrl $16, %eax movb %al, %es:2(%edi) jmp hline_done _align_ hline_solid_pattern_loop: leal (%ebx, %ebx, 2), %eax movl (%esi, %eax), %eax /* read a pixel */ andl $0xFFFFFF, %eax cmpl $MASK_COLOR_24, %eax /* test it */ je hline_solid_zero movl ARG5, %eax movw %ax, %es:(%edi) shrl $16, %eax movb %al, %es:2(%edi) /* write a colored pixel */ incl %ebx andl %edx, %ebx addl $3, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_zero: movw $0, %es:(%edi) /* write a zero pixel */ movb $0, %es:2(%edi) incl %ebx andl %edx, %ebx addl $3, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_mode: /* regular hline drawer */ movl ARG5, %eax /* ARG2 = 12(%ebp) pixel color */ movl %eax, ARG2 /* overwrite ARG2, ARG3 */ movl %eax, 15(%ebp) movl ARG2, %eax movl 13(%ebp), %ebx movl 14(%ebp), %edx /* al,ah,high al,ah,bl,bh ,high bl,bh,dl,dh,high dl,dh */ /* 1st pixel ,2nd pixel,3rd pixel ,4th pixel */ /* ------eax-------,------ebx--------,------edx------- */ cmpl $4, %ecx jb short_line subl $4, %ecx /* test for sign flag */ cld _align_ hline_solid_loop: /* plots 4 pixels an once */ movl %eax, %es:(%edi) movl %ebx, %es:4(%edi) movl %edx, %es:8(%edi) addl $12, %edi subl $4, %ecx jns hline_solid_loop addl $4, %ecx /* add the helper back */ jz hline_done _align_ short_line: movw %ax, %es:(%edi) /* plots remaining pixels (max 3) */ movb %dl, %es:2(%edi) addl $3, %edi decl %ecx jg short_line hline_done: popw %es movl ARG1, %edx UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_hline24 */ /* void _linear_vline24(BITMAP *bmp, int x, int y1, int y2, int color); * Draws a vertical line onto a linear bitmap. */ FUNC(_linear_vline24) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %edi /* edi = x */ movl ARG3, %esi /* esi = y1 */ movl ARG4, %ecx /* ecx = y2 */ cmpl %esi, %ecx jge vline_no_xswap xchgl %ecx, %esi vline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je vline_noclip cmpl BMP_CL(%edx), %edi /* test bmp->cl */ jl vline_done cmpl BMP_CR(%edx), %edi /* test bmp->cr */ jge vline_done cmpl BMP_CT(%edx), %esi /* test y1, bmp->ct */ jge vline_y1_ok cmpl BMP_CT(%edx), %ecx /* test y2, bmp->ct */ jl vline_done movl BMP_CT(%edx), %esi /* clip y1 */ vline_y1_ok: cmpl BMP_CB(%edx), %ecx /* test y2, bmp->cb */ jl vline_noclip cmpl BMP_CB(%edx), %esi /* test y1, bmp->cb */ jge vline_done movl BMP_CB(%edx), %ecx /* clip y2 */ decl %ecx vline_noclip: subl %esi, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* load segment */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je vline_solid_mode /* solid draw? */ movl BMP_CLIP(%edx), %eax /* store destination clipping flag */ pushl %eax movl $0, BMP_CLIP(%edx) /* turn clipping off (we already did it) */ movl ARG5, %eax pushl %eax /* push color */ pushl %esi /* push y */ pushl %edi /* push x */ pushl %edx /* push bitmap */ movl %ecx, %ebx /* ebx = loop counter */ _align_ vline_special_mode_loop: /* vline drawer for funny modes */ call GLOBL(_linear_putpixel24)/* draw the pixel */ incl 8(%esp) /* next y */ decl %ebx jg vline_special_mode_loop /* loop */ popl %edx /* clean up stack */ addl $12, %esp popl %eax movl %eax, BMP_CLIP(%edx) /* restore bitmap clipping flag */ jmp vline_done _align_ vline_solid_mode: /* normal vline drawer */ movl ARG5, %ebx /* get color */ leal (%edi, %edi, 2), %edi /* xadd on each line */ movl %ebx, %eax shrl $16, %eax movl %eax, ARG4 _align_ vline_loop: movl %esi, %eax WRITE_BANK() /* select bank */ movl ARG5, %ebx movw %bx, %es:(%eax, %edi) movl ARG4, %ebx movb %bl, %es:2(%eax, %edi) incl %esi decl %ecx jg vline_loop /* loop */ vline_done: popw %es UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_vline24() */ #endif /* ifdef ALLEGRO_COLOR24 */ allegro-4.4.3.1/src/i386/asmdefs.inc0000664000175000017500000000546113437077643015703 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * A few macros to make my asm code (slightly :-) more readable. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_ASMDEFS_INC #define ALLEGRO_ASMDEFS_INC #ifndef SCAN_DEPEND #include "allegro/platform/alplatf.h" #endif #include "gen_asmdefs.inc" /* helper macro in case we ever need to change this */ #define _align_ .balign 4, 0x90 /* readable way to access arguments passed from C code */ #define ARG1 8(%ebp) #define ARG2 12(%ebp) #define ARG3 16(%ebp) #define ARG4 20(%ebp) #define ARG5 24(%ebp) #define ARG6 28(%ebp) #define ARG7 32(%ebp) #define ARG8 36(%ebp) #define ARG9 40(%ebp) #define ARG10 44(%ebp) /* Bank switching macros. These should be called with a pointer to the * bitmap structure in %edx, and the line number you want to access in * %eax. Registers will be unchanged, except %eax will return a pointer * to the start of the selected scanline. */ #define WRITE_BANK() call *BMP_WBANK(%edx) #define READ_BANK() call *BMP_RBANK(%edx) #define UNWRITE_BANK() movl BMP_VTABLE(%edx), %eax ; call *VTABLE_UNBANK(%eax) #define UNREAD_BANK() movl BMP_VTABLE(%edx), %eax ; call *VTABLE_UNBANK(%eax) /* Helper macro for looking up a position in the pattern bitmap. Passed * registers containing the x and y coordinates of the point, it returns * a 'start of pattern line' pointer in y, and an offset into this line * in x. It clobbers the tmp register. */ #define LOOKUP_PATTERN_POS(x, y, tmp) ; \ subl GLOBL(_drawing_x_anchor), x /* adjust x */ ; \ andl GLOBL(_drawing_x_mask), x /* limit range of x */ ; \ ; \ subl GLOBL(_drawing_y_anchor), y /* adjust y */ ; \ andl GLOBL(_drawing_y_mask), y /* limit range of y */ ; \ ; \ movl GLOBL(_drawing_pattern), tmp /* get position in pattern */ ; \ movl BMP_LINE(tmp, y, 4), y /* How many stacks to allocate for the irq wrappers. This can't be in the * main headers, because it is used by both C and asm code. You could * probably get away with fewer of these, if you want to save memory and * you are feeling brave... */ #define IRQ_STACKS 8 #endif /* ifndef ALLEGRO_ASMDEFS_INC */ allegro-4.4.3.1/src/i386/icsprite.c0000664000175000017500000002012613437077643015547 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Compiled sprite routines for the i386. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "opcodes.h" #ifdef ALLEGRO_UNIX #include "allegro/platform/aintunix.h" /* for _unix_get_page_size */ #endif #ifdef ALLEGRO_WINDOWS #include "winalleg.h" /* For VirtualProtect */ #endif /* ifdef ALLEGRO_WINDOWS */ #ifdef ALLEGRO_HAVE_MPROTECT #include #include #endif /* ifdef ALLEGRO_HAVE_MPROTECT */ /* compile_sprite: * Helper function for making compiled sprites. */ static void *compile_sprite(BITMAP *b, int l, int planar, int *len) { int x, y; int offset; int run; int run_pos; int compiler_pos = 0; int xc = planar ? 4 : 1; unsigned long *addr; #ifdef ALLEGRO_COLOR16 unsigned short *p16; #endif #if defined ALLEGRO_COLOR24 || defined ALLEGRO_COLOR32 unsigned long *p32; #endif #ifdef ALLEGRO_USE_MMAP_GEN_CODE_BUF /* make sure we get a new map */ _map_size = 0; #endif for (y=0; yh; y++) { /* for linear bitmaps, time for some bank switching... */ if (!planar) { COMPILER_MOV_EDI_EAX(); COMPILER_CALL_ESI(); COMPILER_ADD_ECX_EAX(); } offset = 0; x = l; /* compile a line of the sprite */ while (x < b->w) { switch (bitmap_color_depth(b)) { #ifdef ALLEGRO_COLOR8 case 8: /* 8 bit version */ if (b->line[y][x]) { run = 0; run_pos = x; while ((run_posw) && (b->line[y][run_pos])) { run++; run_pos += xc; } while (run >= 4) { COMPILER_MOVL_IMMED(offset, ((int)b->line[y][x]) | ((int)b->line[y][x+xc] << 8) | ((int)b->line[y][x+xc*2] << 16) | ((int)b->line[y][x+xc*3] << 24)); x += xc*4; offset += 4; run -= 4; } if (run >= 2) { COMPILER_MOVW_IMMED(offset, ((int)b->line[y][x]) | ((int)b->line[y][x+xc] << 8)); x += xc*2; offset += 2; run -= 2; } if (run > 0) { COMPILER_MOVB_IMMED(offset, b->line[y][x]); x += xc; offset++; } } else { x += xc; offset++; } break; #endif #ifdef ALLEGRO_COLOR16 case 15: case 16: /* 16 bit version */ p16 = (unsigned short *)b->line[y]; if (p16[x] != b->vtable->mask_color) { run = 0; run_pos = x; while ((run_posw) && (p16[run_pos] != b->vtable->mask_color)) { run++; run_pos++; } while (run >= 2) { COMPILER_MOVL_IMMED(offset, ((int)p16[x]) | ((int)p16[x+1] << 16)); x += 2; offset += 4; run -= 2; } if (run > 0) { COMPILER_MOVW_IMMED(offset, p16[x]); x++; offset += 2; run--; } } else { x++; offset += 2; } break; #endif #ifdef ALLEGRO_COLOR24 case 24: /* 24 bit version */ p32 = (unsigned long *)b->line[y]; if (((*((unsigned long *)(((unsigned char *)p32)+x*3)))&0xFFFFFF) != (unsigned)b->vtable->mask_color) { run = 0; run_pos = x; while ((run_posw) && (((*((unsigned long *)(((unsigned char *)p32)+run_pos*3)))&0xFFFFFF) != (unsigned)b->vtable->mask_color)) { run++; run_pos++; } while (run >= 4) { addr = ((unsigned long *)(((unsigned char *)p32)+x*3)); COMPILER_MOVL_IMMED(offset, addr[0]); offset += 4; COMPILER_MOVL_IMMED(offset, addr[1]); offset += 4; COMPILER_MOVL_IMMED(offset, addr[2]); offset += 4; x += 4; run -= 4; } switch (run) { case 3: addr = ((unsigned long *)(((unsigned char *)p32)+x*3)); COMPILER_MOVL_IMMED(offset, addr[0]); offset += 4; COMPILER_MOVL_IMMED(offset, addr[1]); offset += 4; COMPILER_MOVB_IMMED(offset, *(((unsigned short *)addr)+4)); offset++; x += 3; run -= 3; break; case 2: addr = ((unsigned long *)(((unsigned char *)p32)+x*3)); COMPILER_MOVL_IMMED(offset, addr[0]); offset += 4; COMPILER_MOVW_IMMED(offset, *(((unsigned short *)addr)+2)); offset += 2; x += 2; run -= 2; break; case 1: addr = ((unsigned long *)((unsigned char *)p32+x*3)); COMPILER_MOVW_IMMED(offset, (unsigned short )addr[0]); offset += 2; COMPILER_MOVB_IMMED(offset, *((unsigned char *)(((unsigned short *)addr)+1))); offset++; x++; run--; break; default: break; } } else { x++; offset += 3; } break; #endif #ifdef ALLEGRO_COLOR32 case 32: /* 32 bit version */ p32 = (unsigned long *)b->line[y]; if (p32[x] != (unsigned)b->vtable->mask_color) { run = 0; run_pos = x; while ((run_posw) && (p32[run_pos] != (unsigned)b->vtable->mask_color)) { run++; run_pos++; } while (run > 0) { COMPILER_MOVL_IMMED(offset, p32[x]); x++; offset += 4; run--; } } else { x++; offset += 4; } break; #endif } } /* move on to the next line */ if (y+1 < b->h) { if (planar) { COMPILER_ADD_ECX_EAX(); } else { COMPILER_INC_EDI(); } } } COMPILER_RET(); #ifdef ALLEGRO_USE_MMAP_GEN_CODE_BUF /* Lie about the size, return the size mapped which >= size used / * compiler_pos, because we need the size mapped for munmap. */ *len = _map_size; /* we don't need _rw_map or _map_fd anymore */ munmap(_rw_map, _map_size); close(_map_fd); return _exec_map; #else { void *p = _AL_MALLOC(compiler_pos); if (p) { memcpy(p, _scratch_mem, compiler_pos); *len = compiler_pos; #ifdef ALLEGRO_WINDOWS { DWORD old_protect; /* Play nice with Windows executable memory protection */ VirtualProtect(p, compiler_pos, PAGE_EXECUTE_READWRITE, &old_protect); } #elif defined(ALLEGRO_HAVE_MPROTECT) { long page_size = _unix_get_page_size(); char *aligned_p = (char *)((unsigned long)p & ~(page_size-1ul)); if (mprotect(aligned_p, compiler_pos + ((char *)p - aligned_p), PROT_EXEC|PROT_READ|PROT_WRITE)) { perror("allegro-error: mprotect failed during compile sprite!"); _AL_FREE(p); return NULL; } } #endif } return p; } #endif } /* get_compiled_sprite: * Creates a compiled sprite based on the specified bitmap. */ COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar) { COMPILED_SPRITE *s; int plane; s = _AL_MALLOC(sizeof(COMPILED_SPRITE)); if (!s) return NULL; s->planar = planar; s->color_depth = bitmap_color_depth(bitmap); s->w = bitmap->w; s->h = bitmap->h; for (plane=0; plane<4; plane++) { s->proc[plane].draw = NULL; s->proc[plane].len = 0; } for (plane=0; plane < (planar ? 4 : 1); plane++) { s->proc[plane].draw = compile_sprite(bitmap, plane, planar, &s->proc[plane].len); if (!s->proc[plane].draw) { destroy_compiled_sprite(s); return NULL; } } return s; } /* destroy_compiled_sprite: * Destroys a compiled sprite structure returned by get_compiled_sprite(). */ void destroy_compiled_sprite(COMPILED_SPRITE *sprite) { int plane; if (sprite) { for (plane=0; plane<4; plane++) { if (sprite->proc[plane].draw) { #ifdef ALLEGRO_USE_MMAP_GEN_CODE_BUF munmap(sprite->proc[plane].draw, sprite->proc[plane].len); #else _AL_FREE(sprite->proc[plane].draw); #endif } } _AL_FREE(sprite); } } allegro-4.4.3.1/src/i386/igfx8.s0000664000175000017500000003304013437077643014771 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color linear graphics functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #ifdef ALLEGRO_COLOR8 .text /* void _linear_putpixel8(BITMAP *bmp, int x, int y, int color); * Draws a pixel onto a linear bitmap. */ FUNC(_linear_putpixel8) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ je putpix_noclip cmpl %ecx, BMP_CL(%edx) /* test cl */ jg putpix_done cmpl %ecx, BMP_CR(%edx) /* test cr */ jle putpix_done cmpl %eax, BMP_CT(%edx) /* test ct */ jg putpix_done cmpl %eax, BMP_CB(%edx) /* test cb */ jle putpix_done putpix_noclip: movw BMP_SEG(%edx), %es /* segment selector */ movl ARG4, %ebx /* bx = color */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je putpix_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) je putpix_xor_mode /* XOR? */ cmpl $DRAW_TRANS, GLOBL(_drawing_mode) je putpix_trans_mode /* translucent? */ LOOKUP_PATTERN_POS(%ecx, %eax, %edx) movb (%eax, %ecx), %bl /* read pixel from pattern bitmap */ movl ARG1, %edx /* reload clobbered registers */ movl ARG2, %ecx movl ARG3, %eax cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je putpix_solid_mode /* draw the pattern pixel? */ testb %bl, %bl /* test the pattern pixel */ jz putpix_zero_pattern movl ARG4, %ebx /* if set, draw color */ jmp putpix_solid_mode _align_ putpix_zero_pattern: cmpl $DRAW_MASKED_PATTERN, GLOBL(_drawing_mode) je putpix_done /* skip zero pixels in masked mode */ jmp putpix_solid_mode /* draw zero pixels in solid mode */ _align_ putpix_xor_mode: READ_BANK() /* read pixel from screen */ xorb %es:(%eax, %ecx), %bl /* XOR */ movl ARG3, %eax /* re-read Y position */ jmp putpix_solid_mode _align_ putpix_trans_mode: shll $8, %ebx /* shift color into high byte */ READ_BANK() /* read from screen */ movb %es:(%eax, %ecx), %bl /* screen pixel into low byte */ movl GLOBL(color_map), %eax /* color map in eax */ andl $0xFFFF, %ebx /* mask high bits of ebx */ movb (%eax, %ebx), %bl /* lookup color in the table */ movl ARG3, %eax /* re-read Y position */ _align_ putpix_solid_mode: WRITE_BANK() /* select bank */ movb %bl, %es:(%eax, %ecx) /* store the pixel */ putpix_done: popw %es UNWRITE_BANK() popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_putpixel8() */ /* int _linear_getpixel8(BITMAP *bmp, int x, int y); * Reads a pixel from a linear bitmap. */ FUNC(_linear_getpixel8) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ testl %ecx, %ecx /* test that we are on the bitmap */ jl getpix_skip cmpl %ecx, BMP_W(%edx) jle getpix_skip testl %eax, %eax jl getpix_skip cmpl %eax, BMP_H(%edx) jg getpix_ok _align_ getpix_skip: /* return -1 if we are off the edge */ movl $-1, %ebx jmp getpix_done _align_ getpix_ok: READ_BANK() /* select the bank */ movw BMP_SEG(%edx), %es /* segment selector */ movl %eax, %ebx movzbl %es:(%ebx, %ecx), %ebx /* get the pixel */ getpix_done: popw %es UNWRITE_BANK() movl %ebx, %eax popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_getpixel8() */ /* void _linear_hline8(BITMAP *bmp, int x1, int y, int x2, int color); * Draws a horizontal line onto a linear bitmap. */ FUNC(_linear_hline8) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ebx /* ebx = x1 */ movl ARG3, %eax /* eax = y */ movl ARG4, %ecx /* ecx = x2 */ cmpl %ebx, %ecx jge hline_no_xswap xchgl %ecx, %ebx hline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je hline_noclip cmpl BMP_CT(%edx), %eax /* test bmp->ct */ jl hline_done cmpl BMP_CB(%edx), %eax /* test bmp->cb */ jge hline_done cmpl BMP_CL(%edx), %ebx /* test x1, bmp->cl */ jge hline_x1_ok cmpl BMP_CL(%edx), %ecx /* test x2, bmp->cl */ jl hline_done movl BMP_CL(%edx), %ebx /* clip x1 */ hline_x1_ok: cmpl BMP_CR(%edx), %ecx /* test x2, bmp->cr */ jl hline_noclip cmpl BMP_CR(%edx), %ebx /* test x1, bmp->cr */ jge hline_done movl BMP_CR(%edx), %ecx /* clip x2 */ decl %ecx hline_noclip: subl %ebx, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* segment selector */ WRITE_BANK() /* select write bank */ movl %eax, %edi addl %ebx, %edi /* dest address in edi */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je hline_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) jne hline_not_xor /* XOR? */ movl ARG3, %eax /* select read bank */ READ_BANK() movl %eax, %esi addl %ebx, %esi /* source address in esi */ movb ARG5, %bl /* read the color */ _align_ hline_xor_loop: movb %es:(%esi), %al /* read a pixel */ xorb %bl, %al /* xor */ movb %al, %es:(%edi) /* and write it */ incl %esi incl %edi decl %ecx jg hline_xor_loop jmp hline_done _align_ hline_not_xor: cmpl $DRAW_TRANS, GLOBL(_drawing_mode) jne hline_not_trans /* translucent? */ movl ARG3, %eax /* select read bank */ READ_BANK() movl %eax, %esi addl %ebx, %esi /* source address in esi */ xorl %ebx, %ebx movb ARG5, %bh /* read color into high byte */ movl GLOBL(color_map), %edx /* color mapping table in edx */ shrl $1, %ecx /* adjust counter for 16 bit copies */ jnc hline_no_trans_byte movb %es:(%esi), %bl /* write odd pixel */ movb (%edx, %ebx), %al /* table lookup */ movb %al, %es:(%edi) incl %esi incl %edi hline_no_trans_byte: shrl $1, %ecx /* adjust counter for 32 bit copies */ jnc hline_no_trans_word movw %es:(%esi), %ax /* write two odd pixels */ movb %al, %bl movb (%edx, %ebx), %al /* table lookup 1 */ movb %ah, %bl movb (%edx, %ebx), %ah /* table lookup 2 */ movw %ax, %es:(%edi) addl $2, %esi addl $2, %edi hline_no_trans_word: orl %ecx, %ecx /* anything left to copy? */ jz hline_done _align_ hline_trans_loop: movl %es:(%esi), %eax /* read four pixels at a time */ movb %al, %bl movb (%edx, %ebx), %al /* table lookup 1 */ movb %ah, %bl movb (%edx, %ebx), %ah /* table lookup 2 */ roll $16, %eax movb %al, %bl movb (%edx, %ebx), %al /* table lookup 3 */ movb %ah, %bl movb (%edx, %ebx), %ah /* table lookup 4 */ roll $16, %eax movl %eax, %es:(%edi) /* write four pixels */ addl $4, %esi addl $4, %edi decl %ecx jg hline_trans_loop jmp hline_done _align_ hline_not_trans: movl ARG3, %eax /* get position in pattern bitmap */ LOOKUP_PATTERN_POS(%ebx, %eax, %edx) movl %eax, %esi movl GLOBL(_drawing_x_mask), %edx cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je hline_copy_pattern_loop movb ARG5, %ah /* color in ah */ cmpl $DRAW_SOLID_PATTERN, GLOBL(_drawing_mode) je hline_solid_pattern_loop _align_ hline_masked_pattern_loop: movb (%esi, %ebx), %al /* read a pixel */ testb %al, %al /* test it */ jz hline_masked_skip movb %ah, %es:(%edi) /* write a colored pixel */ hline_masked_skip: incl %ebx andl %edx, %ebx incl %edi decl %ecx jg hline_masked_pattern_loop jmp hline_done _align_ hline_copy_pattern_loop: movb (%esi, %ebx), %al /* read a pixel */ movb %al, %es:(%edi) /* and write it */ incl %ebx andl %edx, %ebx incl %edi decl %ecx jg hline_copy_pattern_loop jmp hline_done _align_ hline_solid_pattern_loop: movb (%esi, %ebx), %al /* read a pixel */ testb %al, %al /* test it */ jz hline_solid_zero movb %ah, %es:(%edi) /* write a colored pixel */ incl %ebx andl %edx, %ebx incl %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_zero: movb $0, %es:(%edi) /* write a zero pixel */ incl %ebx andl %edx, %ebx incl %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_mode: /* regular hline drawer */ movb ARG5, %dl /* get color */ movb %dl, %dh shrdl $16, %edx, %eax movw %dx, %ax /* get four copies of the color */ cld testl $1, %edi /* are we word aligned? */ jz hline_w_aligned stosb /* if not, copy a pixel */ decl %ecx hline_w_aligned: testl $2, %edi /* are we long aligned? */ jz hline_l_aligned subl $2, %ecx jl hline_oops stosw /* if not, copy a word */ hline_l_aligned: movw %cx, %dx /* store low bits */ shrl $2, %ecx /* for long copy */ jz hline_no_long rep ; stosl /* do some 32 bit copies */ hline_no_long: testw $2, %dx jz hline_no_word stosw /* do we need a 16 bit copy? */ hline_no_word: testw $1, %dx jz hline_done stosb /* do we need a byte copy? */ hline_done: popw %es movl ARG1, %edx UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret hline_oops: /* fix up ecx for short line? */ addl $2, %ecx jmp hline_l_aligned /* void _linear_vline8(BITMAP *bmp, int x, int y1, int y2, int color); * Draws a vertical line onto a linear bitmap. */ FUNC(_linear_vline8) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %edi /* edi = x */ movl ARG3, %esi /* esi = y1 */ movl ARG4, %ecx /* ecx = y2 */ cmpl %esi, %ecx jge vline_no_xswap xchgl %ecx, %esi vline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je vline_noclip cmpl BMP_CL(%edx), %edi /* test bmp->cl */ jl vline_done cmpl BMP_CR(%edx), %edi /* test bmp->cr */ jge vline_done cmpl BMP_CT(%edx), %esi /* test y1, bmp->ct */ jge vline_y1_ok cmpl BMP_CT(%edx), %ecx /* test y2, bmp->ct */ jl vline_done movl BMP_CT(%edx), %esi /* clip y1 */ vline_y1_ok: cmpl BMP_CB(%edx), %ecx /* test y2, bmp->cb */ jl vline_noclip cmpl BMP_CB(%edx), %esi /* test y1, bmp->cb */ jge vline_done movl BMP_CB(%edx), %ecx /* clip y2 */ decl %ecx vline_noclip: subl %esi, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* load segment */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je vline_solid_mode /* solid draw? */ movl BMP_CLIP(%edx), %eax /* store destination clipping flag */ pushl %eax movl $0, BMP_CLIP(%edx) /* turn clipping off (we already did it) */ movl ARG5, %eax pushl %eax /* push color */ pushl %esi /* push y */ pushl %edi /* push x */ pushl %edx /* push bitmap */ movl %ecx, %ebx /* ebx = loop counter */ _align_ vline_special_mode_loop: /* vline drawer for funny modes */ call GLOBL(_linear_putpixel8) /* draw the pixel */ incl 8(%esp) /* next y */ decl %ebx jg vline_special_mode_loop /* loop */ popl %edx /* clean up stack */ addl $12, %esp popl %eax movl %eax, BMP_CLIP(%edx) /* restore bitmap clipping flag */ jmp vline_done _align_ vline_solid_mode: /* normal vline drawer */ movl ARG5, %ebx /* get color */ _align_ vline_loop: movl %esi, %eax WRITE_BANK() /* select bank */ movb %bl, %es:(%eax, %edi) /* write pixel */ incl %esi decl %ecx jg vline_loop /* loop */ vline_done: popw %es UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_vline8() */ #endif /* ifdef ALLEGRO_COLOR8 */ allegro-4.4.3.1/src/i386/iblit32.s0000664000175000017500000003057013437077643015221 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit bitmap blitting (written for speed, not readability :-) * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "blit.inc" #ifdef ALLEGRO_COLOR32 .text /* void _linear_clear_to_color32(BITMAP *bitmap, int color); * Fills a linear bitmap with the specified color. */ FUNC(_linear_clear_to_color32) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl ARG1, %edx /* edx = bmp */ movl BMP_CT(%edx), %ebx /* line to start at */ movl BMP_SEG(%edx), %eax /* select segment */ movl %eax, %es movl BMP_CR(%edx), %esi /* width to clear */ subl BMP_CL(%edx), %esi cld _align_ clear_loop: movl %ebx, %eax movl BMP_CL(%edx), %edi WRITE_BANK() /* select bank */ leal (%eax, %edi, 4), %edi /* get line address */ movl ARG2, %eax movl %esi, %ecx rep ; stosl /* clear the line */ incl %ebx cmpl %ebx, BMP_CB(%edx) jg clear_loop /* and loop */ popl %es UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_clear_to_color() */ /* void _linear_blit32(BITMAP *source, BITMAP *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Normal forwards blitting routine for linear bitmaps. */ FUNC(_linear_blit32) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es cld /* for forward copy */ _align_ BLIT_LOOP(blitter, 4, /* copy the data */ rep ; movsl ) popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit32() */ /* void _linear_blit_backward32(BITMAP *source, BITMAP *dest, int source_x, * int source_y, int dest_x, dest_y, int width, height); * Reverse blitting routine, for overlapping linear bitmaps. */ FUNC(_linear_blit_backward32) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_HEIGHT, %eax /* y values go from high to low */ decl %eax addl %eax, B_SOURCE_Y addl %eax, B_DEST_Y movl B_WIDTH, %eax /* x values go from high to low */ decl %eax addl %eax, B_SOURCE_X addl %eax, B_DEST_X movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %edx /* load destination segment */ movl %edx, %es _align_ blit_backwards_loop: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ leal (%eax, %edi, 4), %edi movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ leal (%eax, %esi, 4), %esi movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds std /* backwards */ rep ; movsl /* copy the line */ movl %ebx, %ds /* restore data segment */ decl B_SOURCE_Y decl B_DEST_Y decl B_HEIGHT jg blit_backwards_loop /* and loop */ cld /* finished */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit_backward32() */ FUNC(_linear_blit32_end) ret /* void _linear_masked_blit32(BITMAP *source, *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Masked (skipping pink pixels) blitting routine for linear bitmaps. */ FUNC(_linear_masked_blit32) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx movl BMP_SEG(%edx), %eax movl %eax, %es cld #ifdef ALLEGRO_SSE /* Use SSE if the compiler supports it */ /* Speed improvement on the Pentium 3 only, so we need to check for MMX+ and no 3DNow! */ movl GLOBL(cpu_capabilities), %ecx /* if MMX+ is enabled (or not disabled :) */ andl $CPU_MMXPLUS | $CPU_3DNOW, %ecx cmpl $CPU_MMXPLUS, %ecx jne masked32_no_mmx movl B_WIDTH, %ecx shrl $2, %ecx /* Are there more than 4 pixels? Otherwise, use non-MMX code */ jz masked32_no_mmx movl $MASK_COLOR_32, %eax movd %eax, %mm0 /* Create mask (%mm0) */ movd %eax, %mm1 psllq $32, %mm0 por %mm1, %mm0 pcmpeqd %mm4, %mm4 /* Create inverter mask */ /* ??? maskmovq is an SSE instruction! */ #define BLIT_CODE \ movd %ecx, %mm2; /* Save line length (%mm2) */ \ shrl $2, %ecx; \ \ pushl %es; /* Swap ES and DS */ \ pushl %ds; \ popl %es; \ popl %ds; \ \ _align_; \ masked32_mmx_x_loop: \ \ movq %es:(%esi), %mm1; /* Read 4 pixels */ \ movq %mm0, %mm3; \ movq %es:8(%esi), %mm5; /* Read 4 more pixels */ \ movq %mm0, %mm6; \ \ pcmpeqd %mm1, %mm3; /* Compare with mask (%mm3/%mm6) */ \ pcmpeqd %mm5, %mm6; \ pxor %mm4, %mm3; /* Turn 1->0 and 0->1 */ \ pxor %mm4, %mm6; \ addl $16, %esi; /* Update src */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ addl $8, %edi; \ maskmovq %mm6, %mm5; \ \ addl $8, %edi; /* Update dest */ \ \ decl %ecx; /* Any pixel packs left for this line? */ \ jnz masked32_mmx_x_loop; \ \ movd %mm2, %ecx; /* Restore pixel count */ \ movd %mm0, %edx; \ andl $3, %ecx; \ jz masked32_mmx_loop_end; /* Nothing else to do? */ \ shrl $1, %ecx; /* 1 pixels left */ \ jnc masked32_mmx_qword; \ \ movl %es:(%esi), %eax; /* Read 1 pixel */ \ addl $4, %esi; \ addl $4, %edi; \ cmpl %eax, %edx; /* Compare with mask */ \ je masked32_mmx_qword; \ movl %eax, -4(%edi); /* Write the pixel */ \ \ _align_; \ masked32_mmx_qword: \ \ shrl $1, %ecx; /* 2 pixels left */ \ jnc masked32_mmx_loop_end; \ \ movq %es:(%esi), %mm1; /* Read 2 more pixels */ \ movq %mm0, %mm3; \ \ pcmpeqd %mm1, %mm3; /* Compare with mask (%mm3, %mm6) */ \ pxor %mm4, %mm3; /* Turn 1->0 and 0->1 */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ \ _align_; \ masked32_mmx_loop_end: \ \ pushl %ds; /* Swap back ES and DS */ \ popl %es; BLIT_LOOP(masked32_mmx_loop, 4, BLIT_CODE) #undef BLIT_CODE emms jmp masked32_end; #endif _align_ masked32_no_mmx: _align_ #define BLIT_CODE \ _align_ ; \ masked_blit_x_loop: \ movl (%esi), %eax ; /* read a byte */ \ addl $4, %esi ; \ \ cmpl $MASK_COLOR_32, %eax ;/* test it */ \ je masked_blit_skip ; \ \ movl %eax, %es:(%edi) ; /* write the pixel */ \ addl $4, %edi ; \ decl %ecx ; \ jg masked_blit_x_loop ; \ jmp masked_blit_x_loop_done ; \ \ _align_ ; \ masked_blit_skip: \ addl $4, %edi ; /* skip zero pixels */ \ decl %ecx ; \ jg masked_blit_x_loop ; \ \ masked_blit_x_loop_done: BLIT_LOOP(masked, 4, BLIT_CODE) #undef BLIT_CODE masked32_end: popl %es /* the source must be a memory bitmap, no need for * movl B_SOURCE, %edx * UNREAD_BANK() */ movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_masked_blit32() */ #endif /* ifdef ALLEGRO_COLOR32 */ allegro-4.4.3.1/src/i386/opcodes.h0000664000175000017500000005555613437077643015405 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * i386 opcodes for the bitmap stretcher and mode-X sprite compilers. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_I386_OPCODES_H #define ALLEGRO_I386_OPCODES_H /* * SELinux is the only target for which ALLEGRO_USE_MMAP_GEN_CODE_BUF has to be * defined. So it's okay, for now, if code conditional to * ALLEGRO_USE_MMAP_GEN_CODE_BUF uses a Linux-specific feature. */ #ifdef __linux__ #define ALLEGRO_USE_MMAP_GEN_CODE_BUF #define __USE_GNU /* for mremap */ #include /* for mkstemp */ #include /* for unlink */ #include /* for mmap */ static void *_exec_map; static void *_rw_map; static int _map_size; static int _map_fd; #define GROW_GEN_CODE_BUF(size) \ do { \ size_t page_size = _unix_get_page_size(); \ if (!_map_size) { \ /* Create backing file. FIXME: error-checking, but how? */ \ char tempfile_name[] = "/tmp/allegroXXXXXX"; \ _map_fd = mkstemp(tempfile_name); \ unlink(tempfile_name); \ /* Grow backing file to multiple of page size */ \ _map_size = (size + (page_size-1)) & ~(page_size-1); \ ftruncate(_map_fd, _map_size); \ /* And create the 2 mappings */ \ _exec_map = mmap(0, _map_size, PROT_EXEC | PROT_READ, MAP_SHARED, \ _map_fd, 0); \ _rw_map = mmap(0, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, \ _map_fd, 0); \ } \ else if (size > _map_size) { \ int old_size = _map_size; \ /* Grow backing file to multiple of page size */ \ _map_size = (size + (page_size-1)) & ~(page_size-1); \ ftruncate(_map_fd, _map_size); \ /* And remap the 2 mappings */ \ _exec_map = mremap(_exec_map, old_size, _map_size, MREMAP_MAYMOVE); \ _rw_map = mremap(_rw_map, old_size, _map_size, MREMAP_MAYMOVE); \ } \ } while (0) #define GEN_CODE_BUF _rw_map #else #define GROW_GEN_CODE_BUF(size) _grow_scratch_mem(size) #define GEN_CODE_BUF _scratch_mem #endif #ifdef ALLEGRO_ASM_USE_FS #define FS_PREFIX() COMPILER_BYTE(0x64) #define FS_SIZE 1 #else #define FS_PREFIX() #define FS_SIZE 0 #endif #define COMPILER_BYTE(val) { \ *(((unsigned char *)GEN_CODE_BUF)+compiler_pos) = val; \ compiler_pos++; \ } #define COMPILER_WORD(val) { \ *((unsigned short *)(((char *)GEN_CODE_BUF)+compiler_pos)) = val; \ compiler_pos += 2; \ } #define COMPILER_LONG(val) { \ *((unsigned long *)(((char *)GEN_CODE_BUF)+compiler_pos)) = val; \ compiler_pos += 4; \ } #define COMPILER_INC_ESI() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x46); /* incl %esi */ \ } #define COMPILER_INC_EDI() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x47); /* incl %edi */ \ } #define COMPILER_ADD_ESI(val) { \ GROW_GEN_CODE_BUF(compiler_pos+6); \ COMPILER_BYTE(0x81); /* addl $val, %esi */ \ COMPILER_BYTE(0xC6); \ COMPILER_LONG(val); \ } #define COMPILER_ADD_ECX_EAX() { \ GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0x01); /* addl %ecx, %eax */ \ COMPILER_BYTE(0xC8); \ } #define COMPILER_MOV_EAX(val) { \ GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0xB8); /* movl $val, %eax */ \ COMPILER_LONG(val); \ } #define COMPILER_MOV_ECX(val) { \ GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0xB9); /* movl $val, %ecx */ \ COMPILER_LONG(val); \ } #define COMPILER_MOV_EDX(val) { \ GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0xBA); /* movl $val, %edx */ \ COMPILER_LONG(val); \ } #define COMPILER_MOV_EDI_EAX() { \ GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0x89); /* movl %edi, %eax */ \ COMPILER_BYTE(0xF8); \ } #define COMPILER_CALL_ESI() { \ GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0xFF); /* call *%esi */ \ COMPILER_BYTE(0xD6); \ } #define COMPILER_OUTW() { \ GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0x66); /* outw %ax, %dx */ \ COMPILER_BYTE(0xEF); \ } #define COMPILER_PUSH_ESI() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x56); /* pushl %esi */ \ } #define COMPILER_PUSH_EDI() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x57); /* pushl %edi */ \ } #define COMPILER_POP_ESI() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x5E); /* popl %esi */ \ } #define COMPILER_POP_EDI() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x5F); /* popl %edi */ \ } #define COMPILER_REP_MOVSB() { \ GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0xF2); /* rep */ \ COMPILER_BYTE(0xA4); /* movsb */ \ } #define COMPILER_REP_MOVSW() { \ GROW_GEN_CODE_BUF(compiler_pos+3); \ COMPILER_BYTE(0xF3); /* rep */ \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0xA5); /* movsw */ \ } #define COMPILER_REP_MOVSL() { \ GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0xF3); /* rep */ \ COMPILER_BYTE(0xA5); /* movsl */ \ } #define COMPILER_REP_MOVSL2() { \ GROW_GEN_CODE_BUF(compiler_pos+17); \ COMPILER_BYTE(0x8D); /* leal (%ecx, %ecx, 2), %ecx */ \ COMPILER_BYTE(0x0C); \ COMPILER_BYTE(0x49); \ COMPILER_BYTE(0x8B); /* movl %ecx, %edx */ \ COMPILER_BYTE(0xD1); \ COMPILER_BYTE(0x83); \ COMPILER_BYTE(0xE2); /* andl $3, %edx */ \ COMPILER_BYTE(0x03); \ COMPILER_BYTE(0xC1); \ COMPILER_BYTE(0xE9); /* shrl $2, %ecx */ \ COMPILER_BYTE(0x02); \ COMPILER_BYTE(0xF3); /* rep */ \ COMPILER_BYTE(0xA5); /* movsl */ \ COMPILER_BYTE(0x8B); /* movl %edx, %ecx */ \ COMPILER_BYTE(0xCA); \ COMPILER_BYTE(0xF3); /* rep */ \ COMPILER_BYTE(0xA4); /* movsb */ \ } #define COMPILER_LODSB() { \ GROW_GEN_CODE_BUF(compiler_pos+3); \ COMPILER_BYTE(0x8A); /* movb (%esi), %al */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x46); /* incl %esi */ \ } #define COMPILER_LODSW() { \ GROW_GEN_CODE_BUF(compiler_pos+6); \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x8B); /* movw (%esi), %ax */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x83); /* addl $2, %esi */ \ COMPILER_BYTE(0xC6); \ COMPILER_BYTE(0x02); \ } #define COMPILER_LODSL() { \ GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0x8B); /* movl (%esi), %eax */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x83); /* addl $4, %esi */ \ COMPILER_BYTE(0xC6); \ COMPILER_BYTE(0x04); \ } #define COMPILER_LODSL2() { \ GROW_GEN_CODE_BUF(compiler_pos+15); \ COMPILER_BYTE(0x8B); /* movl (%esi), %eax */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x25); /* andl $0xFFFFFF, %eax */ \ COMPILER_LONG(0xFFFFFF); \ COMPILER_BYTE(0x8B); /* movl %eax, %ebx */ \ COMPILER_BYTE(0xD8); \ COMPILER_BYTE(0xC1); /* shrl $16, %ebx */ \ COMPILER_BYTE(0xEB); \ COMPILER_BYTE(0x10); \ COMPILER_BYTE(0x83); /* addl $3, %esi */ \ COMPILER_BYTE(0xC6); \ COMPILER_BYTE(0x03); \ } #define COMPILER_STOSB() { \ GROW_GEN_CODE_BUF(compiler_pos+4); \ COMPILER_BYTE(0x26); /* movb %al, %es:(%edi) */ \ COMPILER_BYTE(0x88); \ COMPILER_BYTE(0x07); \ COMPILER_BYTE(0x47); /* incl %edi */ \ } #define COMPILER_STOSW() { \ GROW_GEN_CODE_BUF(compiler_pos+7); \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x89); /* movw %ax, %es:(%edi) */ \ COMPILER_BYTE(0x07); \ COMPILER_BYTE(0x83); /* addl $2, %edi */ \ COMPILER_BYTE(0xC7); \ COMPILER_BYTE(0x02); \ } #define COMPILER_STOSL() { \ GROW_GEN_CODE_BUF(compiler_pos+6); \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movl %eax, %es:(%edi) */ \ COMPILER_BYTE(0x07); \ COMPILER_BYTE(0x83); /* addl $4, %edi */ \ COMPILER_BYTE(0xC7); \ COMPILER_BYTE(0x04); \ } #define COMPILER_STOSL2() { \ GROW_GEN_CODE_BUF(compiler_pos+11); \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movw %ax, %es:(%edi) */ \ COMPILER_BYTE(0x07); \ COMPILER_BYTE(0x26); /* movb %bl, %es:2(%edi) */ \ COMPILER_BYTE(0x88); \ COMPILER_BYTE(0x5F); \ COMPILER_BYTE(0x02); \ COMPILER_BYTE(0x83); /* addl $3, %edi */ \ COMPILER_BYTE(0xC7); \ COMPILER_BYTE(0x03); \ } #define COMPILER_MASKED_STOSB(mask_color) { \ GROW_GEN_CODE_BUF(compiler_pos+8); \ COMPILER_BYTE(0x08); /* orb %al, %al */ \ COMPILER_BYTE(0xC0); \ COMPILER_BYTE(0x74); /* jz skip */ \ COMPILER_BYTE(0x03); \ COMPILER_BYTE(0x26); /* movb %al, %es:(%edi) */ \ COMPILER_BYTE(0x88); \ COMPILER_BYTE(0x07); \ COMPILER_BYTE(0x47); /* skip: incl %edi */ \ } #define COMPILER_MASKED_STOSW(mask_color) { \ GROW_GEN_CODE_BUF(compiler_pos+13); \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x3D); /* cmpw mask_color, %ax */ \ COMPILER_WORD(mask_color); \ COMPILER_BYTE(0x74); /* jz skip */ \ COMPILER_BYTE(0x04); /* how much bytes to jump */ \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movw */ \ COMPILER_BYTE(0x07); /* %ax, %es:(%edi) */ \ COMPILER_BYTE(0x83); /* skip: addl $2, %edi */ \ COMPILER_BYTE(0xC7); \ COMPILER_BYTE(0x02); \ } #define COMPILER_MASKED_STOSL(mask_color) { \ GROW_GEN_CODE_BUF(compiler_pos+13); \ COMPILER_BYTE(0x3D); /* cmpl mask_color, %eax */ \ COMPILER_LONG(mask_color); \ COMPILER_BYTE(0x74); /* jz skip */ \ COMPILER_BYTE(0x03); /* how much bytes to jump */ \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movl */ \ COMPILER_BYTE(0x07); /* %eax, %es:(%edi) */ \ COMPILER_BYTE(0x83); /* skip: addl $4, %edi */ \ COMPILER_BYTE(0xC7); \ COMPILER_BYTE(0x04); \ } #define COMPILER_MASKED_STOSL2(mask_color) { \ GROW_GEN_CODE_BUF(compiler_pos+18); \ COMPILER_BYTE(0x3D); /* cmpl mask_color, %eax */ \ COMPILER_LONG(mask_color); \ COMPILER_BYTE(0x74); /* jz skip */ \ COMPILER_BYTE(0x08); /* how much bytes to jump */ \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movw */ \ COMPILER_BYTE(0x07); /* %ax, %es:(%edi) */ \ COMPILER_BYTE(0x26); /* movb %bl, %es:2(%edi) */ \ COMPILER_BYTE(0x88); \ COMPILER_BYTE(0x5F); \ COMPILER_BYTE(0x02); \ COMPILER_BYTE(0x83); /* skip: addl $3, %edi */ \ COMPILER_BYTE(0xC7); \ COMPILER_BYTE(0x03); \ } #define MOV_IMMED_SIZE(x, offset) \ (compiler_pos + x + ((offset < 128) ? 2 : 5)) #define MOV_IMMED(offset) { \ if (offset < 128) { \ COMPILER_BYTE(0x40); /* byte address offset */ \ COMPILER_BYTE(offset); \ } \ else { \ COMPILER_BYTE(0x80); /* long address offset */ \ COMPILER_LONG(offset); \ } \ } #define COMPILER_MOVB_IMMED(offset, val) { \ GROW_GEN_CODE_BUF(MOV_IMMED_SIZE(2+FS_SIZE, offset)); \ FS_PREFIX(); /* fs: */ \ COMPILER_BYTE(0xC6); /* movb $val, offset(%eax) */ \ MOV_IMMED(offset); \ COMPILER_BYTE(val); \ } #define COMPILER_MOVW_IMMED(offset, val) { \ GROW_GEN_CODE_BUF(MOV_IMMED_SIZE(4+FS_SIZE, offset)); \ COMPILER_BYTE(0x66); /* word prefix */ \ FS_PREFIX(); /* fs: */ \ COMPILER_BYTE(0xC7); /* movw $val, offset(%eax) */ \ MOV_IMMED(offset); \ COMPILER_WORD(val); \ } #define COMPILER_MOVL_IMMED(offset, val) { \ GROW_GEN_CODE_BUF(MOV_IMMED_SIZE(5+FS_SIZE, offset)); \ FS_PREFIX(); /* fs: */ \ COMPILER_BYTE(0xC7); /* movl $val, offset(%eax) */ \ MOV_IMMED(offset); \ COMPILER_LONG(val); \ } #define COMPILER_RET() { \ GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0xC3); /* ret */ \ } #endif /* ifndef ALLEGRO_I386_OPCODES_H */ allegro-4.4.3.1/src/i386/blit.inc0000664000175000017500000000537613437077643015220 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper macros for constructing the asm bitmap blitting routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_I386_BLIT_INC #define ALLEGRO_I386_BLIT_INC /* generic framework for constructing blitting routines, shared * between the 8, 16, 24, and 32 bit versions of the code. */ #define B_SOURCE ARG1 #define B_DEST ARG2 #define B_SOURCE_X ARG3 #define B_SOURCE_Y ARG4 #define B_DEST_X ARG5 #define B_DEST_Y ARG6 #define B_WIDTH ARG7 #define B_HEIGHT ARG8 #define BLIT_LOOP(name, bpp, code) \ blit_loop_##name: ; \ movl B_DEST, %edx /* destination bitmap */ ; \ movl B_DEST_Y, %eax /* line number */ ; \ movl B_DEST_X, %edi /* x offset */ ; \ WRITE_BANK() /* select bank */ ; \ leal (%eax, %edi, bpp), %edi ; \ ; \ movl B_SOURCE, %edx /* source bitmap */ ; \ movl B_SOURCE_Y, %eax /* line number */ ; \ movl B_SOURCE_X, %esi /* x offset */ ; \ READ_BANK() /* select bank */ ; \ leal (%eax, %esi, bpp), %esi ; \ ; \ movl B_WIDTH, %ecx /* x loop counter */ ; \ movl BMP_SEG(%edx), %eax /* load data segment */ ; \ movl %eax, %ds ; \ code /* do the transfer */ ; \ ; \ movl %ebx, %ds /* restore data segment */ ; \ incl B_SOURCE_Y ; \ incl B_DEST_Y ; \ decl B_HEIGHT ; \ jg blit_loop_##name /* and loop */ #endif /* ifndef ALLEGRO_I386_BLIT_INC */ allegro-4.4.3.1/src/i386/sprite.inc0000664000175000017500000006071213437077643015567 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper macros for constructing the asm sprite drawing routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_I386_SPRITE_INC #define ALLEGRO_I386_SPRITE_INC /* generic framework for constructing sprite drawing routines, shared * between the 8, 16, 24, and 32 bit versions of the code... */ #define S_BMP ARG1 #define S_SPRITE ARG2 #define S_X ARG3 #define S_Y ARG4 #define S_TGAP -4(%ebp) #define S_LGAP -8(%ebp) #define S_SGAP -12(%ebp) #define S_W -16(%ebp) #define S_H -20(%ebp) #define S_C -24(%ebp) #define S_MASK -28(%ebp) /* sets up a sprite draw operation and handles the clipping */ #define START_SPRITE_DRAW(name) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $28, %esp /* seven local variables */ ; \ ; \ pushl %edi ; \ pushl %esi ; \ pushl %ebx ; \ pushw %es ; \ ; \ movl S_BMP, %edx /* edx = bitmap pointer */ ; \ movl S_SPRITE, %esi /* esi = sprite pointer */ ; \ ; \ movw BMP_SEG(%edx), %es /* segment selector */ ; \ ; \ cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ ; \ jz name##_no_clip ; \ ; \ movl BMP_CT(%edx), %eax /* bmp->ct */ ; \ subl S_Y, %eax /* eax -= y */ ; \ jge name##_tgap_ok ; \ xorl %eax, %eax ; \ name##_tgap_ok: ; \ movl %eax, S_TGAP /* set tgap */ ; \ ; \ movl BMP_H(%esi), %ebx /* sprite->h */ ; \ movl BMP_CB(%edx), %ecx /* bmp->cb */ ; \ subl S_Y, %ecx /* ecx -= y */ ; \ cmpl %ebx, %ecx /* check bottom clipping */ ; \ jg name##_height_ok ; \ movl %ecx, %ebx ; \ name##_height_ok: ; \ subl %eax, %ebx /* height -= tgap */ ; \ jle name##_done ; \ movl %ebx, S_H /* set h */ ; \ ; \ movl BMP_CL(%edx), %eax /* bmp->cl */ ; \ subl S_X, %eax /* eax -= x */ ; \ jge name##_lgap_ok ; \ xorl %eax, %eax ; \ name##_lgap_ok: ; \ movl %eax, S_LGAP /* set lgap */ ; \ ; \ movl BMP_W(%esi), %ebx /* sprite->w */ ; \ movl BMP_CR(%edx), %ecx /* bmp->cr */ ; \ subl S_X, %ecx /* ecx -= x */ ; \ cmpl %ebx, %ecx /* check left clipping */ ; \ jg name##_width_ok ; \ movl %ecx, %ebx ; \ name##_width_ok: ; \ subl %eax, %ebx /* width -= lgap */ ; \ jle name##_done ; \ movl %ebx, S_W /* set w */ ; \ ; \ jmp name##_clip_done ; \ ; \ _align_ ; \ name##_no_clip: ; \ movl $0, S_TGAP ; \ movl $0, S_LGAP ; \ movl BMP_W(%esi), %eax ; \ movl %eax, S_W /* w = sprite->w */ ; \ movl BMP_H(%esi), %eax ; \ movl %eax, S_H /* h = sprite->h */ ; \ ; \ _align_ ; \ name##_clip_done: /* cleans up the stack after a sprite draw operation */ #define END_SPRITE_DRAW() \ popw %es ; \ ; \ movl S_BMP, %edx ; \ UNWRITE_BANK() ; \ ; \ popl %ebx ; \ popl %esi ; \ popl %edi ; \ movl %ebp, %esp ; \ popl %ebp /* sets up the inner sprite drawing loop, loads registers, etc */ #define SPRITE_LOOP(name) \ sprite_y_loop_##name: ; \ movl S_Y, %eax /* load line */ ; \ WRITE_BANK() /* select bank */ ; \ addl S_X, %eax /* add x offset */ ; \ movl S_W, %ecx /* x loop counter */ ; \ ; \ _align_ ; \ sprite_x_loop_##name: /* ends the inner (x) part of a sprite drawing loop */ #define SPRITE_END_X(name) \ decl %ecx ; \ jg sprite_x_loop_##name /* ends the outer (y) part of a sprite drawing loop */ #define SPRITE_END_Y(name) \ addl S_SGAP, %esi /* skip sprite bytes */ ; \ incl S_Y /* next line */ ; \ decl S_H /* loop counter */ ; \ jg sprite_y_loop_##name /* sets up the inner translucent sprite drawing loop, loads registers, etc */ #define T_SPRITE_LOOP(name) \ sprite_y_loop_##name: ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ movl S_Y, %eax /* load line */ ; \ READ_BANK() /* select read bank */ ; \ movl %eax, %ecx /* read address in ecx */ ; \ movl S_Y, %eax /* reload line */ ; \ WRITE_BANK() /* select write bank */ ; \ subl %eax, %ecx /* convert ecx to offset */ ; \ addl S_X, %eax /* add x offset */ ; \ movl S_W, %edx /* x loop counter */ ; \ movl %edx, S_C /* store */ ; \ ; \ _align_ ; \ sprite_x_loop_##name: /* sets up the inner truecolor translucent sprite drawing loop */ #define TT_SPRITE_LOOP(name, readreg) \ sprite_y_loop_##name: ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ movl S_Y, %eax /* load line */ ; \ READ_BANK() /* select read bank */ ; \ movl %eax, readreg /* read address in readreg */ ; \ movl S_Y, %eax /* reload line */ ; \ WRITE_BANK() /* select write bank */ ; \ subl %eax, readreg /* convert readreg to offset */ ; \ movl S_W, %edx /* x loop counter */ ; \ addl S_X, %eax /* add x offset */ ; \ movl %edx, S_C /* store */ ; \ movl %eax, %ebx /* move dest address */ ; \ ; \ _align_ ; \ sprite_x_loop_##name: /* sets up the inner truecolor lit sprite drawing loop */ #define LT_SPRITE_LOOP(name) \ sprite_y_loop_##name: ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ movl S_Y, %eax /* load line */ ; \ WRITE_BANK() /* select write bank */ ; \ movl S_W, %edx /* x loop counter */ ; \ addl S_X, %eax /* add x offset */ ; \ movl %edx, S_C /* store */ ; \ movl %eax, %ebx /* move dest address */ ; \ ; \ _align_ ; \ sprite_x_loop_##name: /* ends the inner (x) part of a translucent sprite drawing loop */ #define T_SPRITE_END_X(name) \ decl S_C ; \ jg sprite_x_loop_##name /* generic framework for constructing RLE sprite drawing routines, shared * between the 8, 16, 24, and 32 bit versions of the code... */ #define R_BMP ARG1 #define R_SPRITE ARG2 #define R_X ARG3 #define R_Y ARG4 #define R_COLOR ARG5 #define R_LGAP -4(%ebp) #define R_W -8(%ebp) #define R_H -12(%ebp) #define R_TMP -16(%ebp) #define R_TMP2 -20(%ebp) /* helper macro for drawing RLE sprites */ #define DO_RLE(name, bpp, suf, areg, eolmarker) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $20, %esp ; \ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ pushw %es ; \ ; \ movl $0, R_LGAP /* normally zero gap on left */ ; \ movl R_SPRITE, %esi /* esi = sprite pointer */ ; \ movl RLE_W(%esi), %eax /* read sprite width */ ; \ movl %eax, R_W ; \ movl RLE_H(%esi), %eax /* read sprite height */ ; \ movl %eax, R_H ; \ addl $RLE_DAT, %esi /* points to start of RLE data */ ; \ ; \ movl R_BMP, %edx /* edx = bitmap pointer */ ; \ movw BMP_SEG(%edx), %es /* select segment */ ; \ cld ; \ ; \ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ ; \ je name##_noclip ; \ ; \ movl R_Y, %ecx /* ecx = Y */ ; \ ; \ name##_clip_top: ; \ cmpl %ecx, BMP_CT(%edx) /* test top clipping */ ; \ jle name##_top_ok ; \ ; \ incl %ecx /* increment Y */ ; \ decl R_H /* decrement height */ ; \ jle name##_done ; \ ; \ _align_ ; \ name##_clip_top_loop: ; \ lods##suf /* find zero EOL marker in RLE data */ ; \ cmp##suf eolmarker, areg ; \ jne name##_clip_top_loop ; \ ; \ jmp name##_clip_top ; \ ; \ _align_ ; \ name##_top_ok: ; \ movl %ecx, R_Y /* store clipped Y */ ; \ ; \ addl R_H, %ecx /* ecx = Y + height */ ; \ subl BMP_CB(%edx), %ecx /* test bottom clipping */ ; \ jl name##_bottom_ok ; \ ; \ subl %ecx, R_H /* clip on the bottom */ ; \ jle name##_done ; \ ; \ _align_ ; \ name##_bottom_ok: ; \ movl BMP_CL(%edx), %eax /* check left clipping */ ; \ subl R_X, %eax ; \ jle name##_left_ok ; \ ; \ movl %eax, R_LGAP /* clip on the left */ ; \ addl %eax, R_X ; \ subl %eax, R_W ; \ jle name##_done ; \ ; \ _align_ ; \ name##_left_ok: ; \ movl R_X, %eax /* check right clipping */ ; \ addl R_W, %eax ; \ subl BMP_CR(%edx), %eax ; \ jle name##_no_right_clip ; \ ; \ subl %eax, R_W ; \ jl name##_done ; \ jmp name##_clip_y_loop ; \ ; \ _align_ ; \ name##_no_right_clip: ; \ cmpl $0, R_LGAP /* can we use the fast noclip drawer? */ ; \ je name##_noclip ; \ ; \ ; \ /* slower version of the drawer for sprites that need clipping */ ; \ _align_ ; \ name##_clip_y_loop: ; \ INIT_RLE_LINE() ; \ ; \ movl R_W, %ebx ; \ movl R_LGAP, %ecx ; \ ; \ name##_clip_lgap_loop: ; \ lods##suf /* read a command byte */ ; \ test##suf areg, areg /* and test it */ ; \ js name##_clip_lgap_zeros ; \ ; \ RLE_ZEX_EAX() /* skip a solid run */ ; \ leal (%esi, %eax, bpp), %esi ; \ subl %eax, %ecx ; \ jge name##_clip_lgap_loop ; \ ; \ leal (%esi, %ecx, bpp), %esi /* oops, we overshot */ ; \ negl %ecx ; \ movl %ecx, %eax ; \ jmp name##_clip_x_loop ; \ ; \ _align_ ; \ name##_clip_lgap_zeros: ; \ RLE_SEX_EAX() /* skip a run of zeros */ ; \ addl %eax, %ecx ; \ jge name##_clip_lgap_loop ; \ ; \ movl %ecx, %eax /* oops, we overshot */ ; \ ; \ _align_ ; \ name##_clip_x_loop: ; \ TEST_RLE_COMMAND(name##_clip_x_done, name##_clip_skip_zeros) ; \ ; \ RLE_ZEX_ECX() /* write a string of pixels */ ; \ subl %ecx, %ebx ; \ jle name##_clip_string ; \ ; \ SLOW_RLE_RUN(0) ; \ lods##suf /* read next command byte */ ; \ jmp name##_clip_x_loop ; \ ; \ _align_ ; \ name##_clip_string: ; \ addl %ebx, %ecx /* only write part of the string */ ; \ jle name##_clip_altogether ; \ SLOW_RLE_RUN(1) ; \ name##_clip_altogether: ; \ negl %ebx ; \ leal (%esi, %ebx, bpp), %esi ; \ jmp name##_clip_skip_rgap ; \ ; \ _align_ ; \ name##_clip_skip_zeros: ; \ RLE_SEX_EAX() /* skip over a string of zeros */ ; \ negl %eax ; \ ADD_EAX_EDI() ; \ subl %eax, %ebx ; \ jle name##_clip_skip_rgap ; \ ; \ lods##suf /* read next command byte */ ; \ jmp name##_clip_x_loop ; \ ; \ _align_ ; \ name##_clip_skip_rgap: ; \ lods##suf /* skip forward to zero EOL marker */ ; \ cmp##suf eolmarker, areg ; \ jne name##_clip_skip_rgap ; \ ; \ name##_clip_x_done: ; \ incl R_Y ; \ decl R_H ; \ jg name##_clip_y_loop ; \ jmp name##_done ; \ ; \ ; \ /* fast drawer for sprites that don't need clipping */ ; \ _align_ ; \ name##_noclip: ; \ INIT_FAST_RLE_LOOP() ; \ ; \ _align_ ; \ name##_noclip_y_loop: ; \ INIT_RLE_LINE() ; \ ; \ _align_ ; \ name##_noclip_x_loop: ; \ lods##suf /* read a command byte */ ; \ TEST_RLE_COMMAND(name##_noclip_x_done, name##_noclip_skip_zeros) ; \ ; \ RLE_ZEX_ECX() /* write a string of pixels */ ; \ FAST_RLE_RUN() ; \ jmp name##_noclip_x_loop ; \ ; \ _align_ ; \ name##_noclip_skip_zeros: ; \ neg##suf areg /* skip over a string of zeros */ ; \ RLE_ZEX_EAX() ; \ ADD_EAX_EDI() ; \ jmp name##_noclip_x_loop ; \ ; \ _align_ ; \ name##_noclip_x_done: ; \ incl R_Y ; \ decl R_H ; \ jg name##_noclip_y_loop ; \ ; \ ; \ name##_done: ; \ popw %es ; \ ; \ movl R_BMP, %edx ; \ UNWRITE_BANK() ; \ ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp /* finished drawing an RLE sprite */ #endif /* ifndef ALLEGRO_I386_SPRITE_INC */ allegro-4.4.3.1/src/i386/ispr16.s0000664000175000017500000007577713437077643015117 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit sprite drawing (written for speed, not readability :-) * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "sprite.inc" #ifdef ALLEGRO_COLOR16 .text /* helper for reading the transparency mask value for a bitmap */ #define STORE_MASK_COLOR(bmp, tmp) \ movl BMP_VTABLE(bmp), tmp ; \ movl VTABLE_MASK_COLOR(tmp), tmp ; \ movl tmp, S_MASK /* void _linear_draw_sprite16(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite onto a linear bitmap at the specified x, y position, * using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_sprite16) /* inner loop that copies just the one word */ #define LOOP_ONLY_ONE_WORD \ SPRITE_LOOP(only_one_word) ; \ movw (%esi), %bx /* read a pixel */ ; \ cmpw S_MASK, %bx /* test */ ; \ je only_one_word_skip ; \ movw %bx, %es:(%eax) /* write */ ; \ only_one_word_skip: ; \ addl $2, %esi ; \ addl $2, %eax ; \ /* no x loop */ ; \ SPRITE_END_Y(only_one_word) /* inner loop that copies a long at a time */ #define LOOP_LONGS_ONLY \ SPRITE_LOOP(longs_only) ; \ movl (%esi), %ebx /* read two pixels */ ; \ cmpw S_MASK, %bx /* test */ ; \ jz longs_only_skip_1 ; \ movw %bx, %es:(%eax) /* write */ ; \ longs_only_skip_1: ; \ shrl $16, %ebx /* access next pixel */ ; \ cmpw S_MASK, %bx /* test */ ; \ jz longs_only_skip_2 ; \ movw %bx, %es:2(%eax) /* write */ ; \ longs_only_skip_2: ; \ addl $4, %esi ; \ addl $4, %eax ; \ SPRITE_END_X(longs_only) ; \ /* no cleanup at end of line */ ; \ SPRITE_END_Y(longs_only) /* inner loop that copies a long at a time, plus a leftover word */ #define LOOP_LONGS_AND_WORD \ SPRITE_LOOP(longs_and_word) ; \ movl (%esi), %ebx /* read two pixels */ ; \ cmpw S_MASK, %bx /* test */ ; \ jz longs_and_word_skip_1 ; \ movw %bx, %es:(%eax) /* write */ ; \ longs_and_word_skip_1: ; \ shrl $16, %ebx /* access next pixel */ ; \ cmpw S_MASK, %bx /* test */ ; \ jz longs_and_word_skip_2 ; \ movw %bx, %es:2(%eax) /* write */ ; \ longs_and_word_skip_2: ; \ addl $4, %esi ; \ addl $4, %eax ; \ SPRITE_END_X(longs_and_word) /* end of x loop */ ; \ movw (%esi), %bx /* read pixel */ ; \ cmpw S_MASK, %bx /* test */ ; \ jz longs_and_word_end_skip ; \ movw %bx, %es:(%eax) /* write */ ; \ longs_and_word_end_skip: ; \ addl $2, %esi ; \ addl $2, %eax ; \ SPRITE_END_Y(longs_and_word) /* the actual sprite drawing routine... */ START_SPRITE_DRAW(sprite) STORE_MASK_COLOR(%esi, %eax); movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ shrl $1, S_W /* halve counter for long copies */ jz sprite_only_one_word jnc sprite_even_words _align_ LOOP_LONGS_AND_WORD /* long at a time, plus leftover word */ jmp sprite_done _align_ sprite_even_words: LOOP_LONGS_ONLY /* copy a long at a time */ jmp sprite_done _align_ sprite_only_one_word: LOOP_ONLY_ONE_WORD /* copy just the one word */ _align_ sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite16() */ FUNC(_linear_draw_sprite16_end) ret /* void _linear_draw_256_sprite16(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a 256 color sprite onto a linear bitmap at the specified x, y * position, using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_256_sprite16) START_SPRITE_DRAW(sprite256) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ pushl %edx /* get color expansion lookup table */ movl BMP_VTABLE(%edx), %edx pushl VTABLE_COLOR_DEPTH(%edx) call *GLOBL(_palette_expansion_table) addl $4, %esp popl %edx movl %eax, %edi _align_ SPRITE_LOOP(draw_sprite256) movzbl (%esi), %ebx /* read a pixel */ orb %bl, %bl /* test */ jz draw_256_sprite_skip movl (%edi, %ebx, 4), %ebx /* lookup in palette table */ movw %bx, %es:(%eax) /* write */ draw_256_sprite_skip: incl %esi addl $2, %eax SPRITE_END_X(draw_sprite256) SPRITE_END_Y(draw_sprite256) _align_ sprite256_done: END_SPRITE_DRAW() ret /* end of _linear_draw_256_sprite16() */ /* void _linear_draw_sprite_v_flip16(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping vertically. */ FUNC(_linear_draw_sprite_v_flip16) START_SPRITE_DRAW(sprite_v_flip) STORE_MASK_COLOR(%esi, %eax); movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ addl S_W, %eax addl S_W, %eax /* + w */ negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(v_flip) movw (%esi), %bx /* read pixel */ cmpw S_MASK, %bx /* test */ je sprite_v_flip_skip movw %bx, %es:(%eax) /* write */ sprite_v_flip_skip: addl $2, %esi addl $2, %eax SPRITE_END_X(v_flip) SPRITE_END_Y(v_flip) sprite_v_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_v_flip16() */ /* void _linear_draw_sprite_h_flip16(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping horizontally. */ FUNC(_linear_draw_sprite_h_flip16) START_SPRITE_DRAW(sprite_h_flip) STORE_MASK_COLOR(%esi, %eax); movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ addl S_W, %eax addl S_W, %eax /* + w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi leal (%esi, %ecx, 2), %esi subl S_LGAP, %esi subl $2, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(h_flip) movw (%esi), %bx /* read pixel */ cmpw S_MASK, %bx /* test */ je sprite_h_flip_skip movw %bx, %es:(%eax) /* write */ sprite_h_flip_skip: subl $2, %esi addl $2, %eax SPRITE_END_X(h_flip) SPRITE_END_Y(h_flip) sprite_h_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_h_flip16() */ /* void _linear_draw_sprite_vh_flip16(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping both vertically and horizontally. */ FUNC(_linear_draw_sprite_vh_flip16) START_SPRITE_DRAW(sprite_vh_flip) STORE_MASK_COLOR(%esi, %eax); movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi leal (%esi, %ecx, 2), %esi subl S_LGAP, %esi subl $2, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(vh_flip) movw (%esi), %bx /* read pixel */ cmpw S_MASK, %bx /* test */ je sprite_vh_flip_skip movw %bx, %es:(%eax) /* write */ sprite_vh_flip_skip: subl $2, %esi addl $2, %eax SPRITE_END_X(vh_flip) SPRITE_END_Y(vh_flip) sprite_vh_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_vh_flip16() */ /* void _linear_draw_trans_sprite16(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a translucent sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_sprite16) START_SPRITE_DRAW(trans_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans, %edi) movw (%esi), %ax /* read source pixel */ cmpw $MASK_COLOR_16, %ax jz trans_sprite_skip movw %es:(%ebx, %edi), %dx /* read memory pixel */ pushl GLOBL(_blender_alpha) pushl %edx pushl %eax call *GLOBL(_blender_func16) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ trans_sprite_skip: addl $2, %ebx addl $2, %esi T_SPRITE_END_X(trans) /* no cleanup at end of line */ SPRITE_END_Y(trans) trans_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_trans_sprite16() */ /* void _linear_draw_trans_rgba_sprite16(BITMAP *bmp, *sprite, int x, y); * Draws a translucent 32 bit sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_sprite16) START_SPRITE_DRAW(trans_rgba_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans_rgba, %edi) movl (%esi), %eax /* read source pixel */ cmpl $MASK_COLOR_32, %eax jz trans_rgba_sprite_skip movw %es:(%ebx, %edi), %dx /* read memory pixel */ pushl GLOBL(_blender_alpha) pushl %edx pushl %eax call *GLOBL(_blender_func16x) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ trans_rgba_sprite_skip: addl $2, %ebx addl $4, %esi T_SPRITE_END_X(trans_rgba) /* no cleanup at end of line */ SPRITE_END_Y(trans_rgba) trans_rgba_sprite_done: END_SPRITE_DRAW() ret /* end _linear_draw_trans_rgba_sprite16() */ /* void _linear_draw_lit_sprite16(BITMAP *bmp, BITMAP *sprite, int x, y, color); * Draws a lit sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_sprite16) #define ALPHA ARG5 START_SPRITE_DRAW(lit_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl ALPHA, %edi _align_ LT_SPRITE_LOOP(lit_sprite) movw (%esi), %ax /* read pixel */ cmpw $MASK_COLOR_16, %ax jz lit_sprite_skip pushl %edi pushl %eax pushl GLOBL(_blender_col_16) call *GLOBL(_blender_func16) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write pixel */ lit_sprite_skip: addl $2, %esi addl $2, %ebx T_SPRITE_END_X(lit_sprite) SPRITE_END_Y(lit_sprite) lit_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_lit_sprite16() */ /* void _linear_draw_character16(BITMAP *bmp, BITMAP *sprite, int x, y, color, bg); * For proportional font output onto a linear bitmap: uses the sprite as * a mask, replacing all set pixels with the specified color. */ FUNC(_linear_draw_character16) #define COLOR ARG5 #define BG ARG6 START_SPRITE_DRAW(draw_char) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl COLOR, %ebx /* bx = text color */ movl BG, %edi /* di = background color */ cmpl $0, %edi jl draw_masked_char /* opaque (bg >= 0) character output */ _align_ SPRITE_LOOP(draw_opaque_char) cmpb $0, (%esi) /* test pixel */ jz draw_opaque_background movw %bx, %es:(%eax) /* write pixel */ jmp draw_opaque_done draw_opaque_background: movw %di, %es:(%eax) /* write background */ draw_opaque_done: incl %esi addl $2, %eax SPRITE_END_X(draw_opaque_char) SPRITE_END_Y(draw_opaque_char) jmp draw_char_done /* masked (bg -1) character output */ _align_ draw_masked_char: SPRITE_LOOP(draw_masked_char) cmpb $0, (%esi) /* test pixel */ jz draw_masked_skip movw %bx, %es:(%eax) /* write pixel */ draw_masked_skip: incl %esi addl $2, %eax SPRITE_END_X(draw_masked_char) SPRITE_END_Y(draw_masked_char) draw_char_done: END_SPRITE_DRAW() ret /* end of _linear_draw_character16() */ /* void _linear_draw_rle_sprite16(BITMAP *bmp, RLE_SPRITE *sprite, int x, y) * Draws an RLE sprite onto a linear bitmap at the specified position. */ FUNC(_linear_draw_rle_sprite16) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ rep ; movsw /* no special initialisation required */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ shrl $1, %ecx ; \ jnc rle_noclip_no_word ; \ movsw /* copy odd word? */ ; \ rle_noclip_no_word: ; \ jz rle_noclip_x_loop ; \ rep ; movsl /* 32 bit string copy */ /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpw $MASK_COLOR_16, %ax ; \ je done ; \ testw %ax, %ax ; \ js skip /* adds the offset in %eax onto the destination address */ #define ADD_EAX_EDI() \ leal (%edi, %eax, 2), %edi /* zero extend %ax into %eax */ #define RLE_ZEX_EAX() \ movzwl %ax, %eax /* zero extend %ax into %ecx */ #define RLE_ZEX_ECX() \ movzwl %ax, %ecx /* sign extend %ax into %eax */ #define RLE_SEX_EAX() \ movswl %ax, %eax /* do it! */ DO_RLE(rle, 2, w, %ax, $MASK_COLOR_16) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_trans_rle_sprite16(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rle_sprite16) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func16) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func16) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rle_run_loop /* do it! */ DO_RLE(rle_trans, 2, w, %ax, $MASK_COLOR_16) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_lit_rle_sprite16(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y, int color) * Draws a tinted RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_rle_sprite16) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl R_COLOR, %ebx ; \ movl %ecx, R_TMP ; \ ; \ lit_rle_clipped_run_loop##n: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_16) ; \ call *GLOBL(_blender_func16) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP ; \ jg lit_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ movl R_COLOR, %ebx /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP ; \ ; \ lit_rle_run_loop: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_16) ; \ call *GLOBL(_blender_func16) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP ; \ jg lit_rle_run_loop /* do it! */ DO_RLE(rle_lit, 2, w, %ax, $MASK_COLOR_16) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #undef TEST_RLE_COMMAND #undef RLE_ZEX_EAX #undef RLE_ZEX_ECX #undef RLE_SEX_EAX /* void _linear_draw_trans_rgba_rle_sprite16(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent 32 bit RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_rle_sprite16) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func16x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func16x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_run_loop /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpl $MASK_COLOR_32, %eax ; \ je done ; \ testl %eax, %eax ; \ js skip /* no zero or sign extend required */ #define RLE_ZEX_EAX() #define RLE_SEX_EAX() /* this can be a simple copy... */ #define RLE_ZEX_ECX() \ movl %eax, %ecx /* do it! */ DO_RLE(rle_trans_rgba, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #endif /* ifdef ALLEGRO_COLOR16 */ allegro-4.4.3.1/src/i386/icpus.s0000664000175000017500000001056513437077643015076 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * i386 CPU detection routines, by Phil Frisbie. * * Theuzifan improved the support for Cyrix chips. * * Calin Andrian added 3DNow! detection code. * * See readme.txt for copyright information. */ #include "asmdefs.inc" .text /* int _i_is_486(); * Returns TRUE for 486+, and FALSE for 386. */ FUNC(_i_is_486) pushl %ebp movl %esp, %ebp pushf /* save EFLAGS */ popl %eax /* get EFLAGS */ movl %eax, %edx /* temp storage EFLAGS */ xorl $0x40000, %eax /* change AC bit in EFLAGS */ pushl %eax /* put new EFLAGS value on stack */ popf /* replace current EFLAGS value */ pushf /* get EFLAGS */ popl %eax /* save new EFLAGS in EAX */ cmpl %edx, %eax /* compare temp and new EFLAGS */ jz is406_not_found movl $1, %eax /* 80486 present */ jmp is486_done is406_not_found: movl $0, %eax /* 80486 not present */ is486_done: pushl %edx /* get original EFLAGS */ popf /* restore EFLAGS */ popl %ebp ret /* int _i_is_fpu(); * Returns TRUE is the CPU has floating point hardware. */ FUNC(_i_is_fpu) pushl %ebp movl %esp, %ebp fninit movl $0x5A5A, %eax fnstsw %ax cmpl $0, %eax jne is_fpu_not_found movl $1, %eax jmp is_fpu_done is_fpu_not_found: movl $0, %eax is_fpu_done: popl %ebp ret /* int _i_is_cyrix(); * Returns TRUE if this is a Cyrix processor. */ FUNC(_i_is_cyrix) pushl %ebp movl %esp, %ebp xorw %ax, %ax /* clear eax */ sahf /* bit 1 is always 1 in flags */ movw $5, %ax movw $2, %dx div %dl /* this does not change flags */ lahf /* get flags */ cmpb $2, %ah /* check for change in flags */ jne is_cyrix_not_found movl $1, %eax /* TRUE Cyrix CPU */ jmp is_cyrix_done is_cyrix_not_found: movl $0, %eax /* FALSE NON-Cyrix CPU */ is_cyrix_done: popl %ebp ret /* void _i_cx_w(int index, int value); * Writes to a Cyrix register. */ FUNC(_i_cx_w) pushl %ebp movl %esp, %ebp cli movb ARG1, %al outb %al, $0x22 movb ARG2, %al outb %al, $0x23 sti popl %ebp ret /* char _i_cx_r(int index); * Reads from a Cyrix register. */ FUNC(_i_cx_r) pushl %ebp movl %esp, %ebp cli movb ARG1, %al outb %al, $0x22 xorl %eax, %eax inb $0x23, %al sti popl %ebp ret /* int _i_is_cpuid_supported(); * Checks whether the cpuid instruction is available. */ FUNC(_i_is_cpuid_supported) pushl %ebp movl %esp, %ebp pushfl /* get extended flags */ popl %eax movl %eax, %edx /* save current flags */ xorl $0x200000, %eax /* toggle bit 21 */ pushl %eax /* put new flags on stack */ popfl /* flags updated now in flags */ pushfl /* get extended flags */ popl %eax xorl %edx, %eax /* if bit 21 r/w then supports cpuid */ jz cpuid_not_found movl $1, %eax jmp cpuid_done cpuid_not_found: movl $0, %eax cpuid_done: popl %ebp ret /* void _i_get_cpuid_info(uint32_t cpuid_levels, uint32_t *reg); * This is so easy! */ FUNC(_i_get_cpuid_info) pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edi movl ARG1, %eax /* eax = cpuid_levels */ .byte 0x0F, 0xA2 /* cpuid instruction */ movl ARG2, %edi /* edi = reg */ movl %eax, (%edi) /* store results */ movl %ebx, 4(%edi) movl %ecx, 8(%edi) movl %edx, 12(%edi) popl %edi popl %ecx popl %ebx popl %ebp ret allegro-4.4.3.1/src/i386/ispr15.s0000664000175000017500000004425513437077643015101 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit sprite drawing (written for speed, not readability :-) * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "sprite.inc" #ifdef ALLEGRO_COLOR16 .text /* void _linear_draw_trans_sprite15(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a translucent sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_sprite15) START_SPRITE_DRAW(trans_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans, %edi) movw (%esi), %ax /* read source pixel */ cmpw $MASK_COLOR_15, %ax jz trans_sprite_skip movw %es:(%ebx, %edi), %dx /* read memory pixel */ pushl GLOBL(_blender_alpha) pushl %edx pushl %eax call *GLOBL(_blender_func15) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ trans_sprite_skip: addl $2, %ebx addl $2, %esi T_SPRITE_END_X(trans) /* no cleanup at end of line */ SPRITE_END_Y(trans) trans_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_trans_sprite15() */ /* void _linear_draw_trans_rgba_sprite15(BITMAP *bmp, sprite, int x, y); * Draws a translucent 32 bit sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_sprite15) START_SPRITE_DRAW(trans_rgba_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans_rgba, %edi) movl (%esi), %eax /* read source pixel */ cmpl $MASK_COLOR_32, %eax jz trans_rgba_sprite_skip movw %es:(%ebx, %edi), %dx /* read memory pixel */ pushl GLOBL(_blender_alpha) pushl %edx pushl %eax call *GLOBL(_blender_func15x) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write the result */ trans_rgba_sprite_skip: addl $2, %ebx addl $4, %esi T_SPRITE_END_X(trans_rgba) /* no cleanup at end of line */ SPRITE_END_Y(trans_rgba) trans_rgba_sprite_done: END_SPRITE_DRAW() ret /* end _linear_draw_trans_rgba_sprite15() */ /* void _linear_draw_lit_sprite15(BITMAP *bmp, BITMAP *sprite, int x, y, color); * Draws a lit sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_sprite15) #define ALPHA ARG5 START_SPRITE_DRAW(lit_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $1, S_X shll $1, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl ALPHA, %edi _align_ LT_SPRITE_LOOP(lit_sprite) movw (%esi), %ax /* read pixel */ cmpw $MASK_COLOR_15, %ax jz lit_sprite_skip pushl %edi pushl %eax pushl GLOBL(_blender_col_15) call *GLOBL(_blender_func15) /* blend */ addl $12, %esp movw %ax, %es:(%ebx) /* write pixel */ lit_sprite_skip: addl $2, %esi addl $2, %ebx T_SPRITE_END_X(lit_sprite) SPRITE_END_Y(lit_sprite) lit_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_lit_sprite15() */ /* void _linear_draw_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, int x, y) * Draws an RLE sprite onto a linear bitmap at the specified position. */ FUNC(_linear_draw_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ rep ; movsw /* no special initialisation required */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ shrl $1, %ecx ; \ jnc rle_noclip_no_word ; \ movsw /* copy odd word? */ ; \ rle_noclip_no_word: ; \ jz rle_noclip_x_loop ; \ rep ; movsl /* 32 bit string copy */ /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpw $MASK_COLOR_15, %ax ; \ je done ; \ testw %ax, %ax ; \ js skip /* adds the offset in %eax onto the destination address */ #define ADD_EAX_EDI() \ leal (%edi, %eax, 2), %edi /* zero extend %ax into %eax */ #define RLE_ZEX_EAX() \ movzwl %ax, %eax /* zero extend %ax into %ecx */ #define RLE_ZEX_ECX() \ movzwl %ax, %ecx /* sign extend %ax into %eax */ #define RLE_SEX_EAX() \ movswl %ax, %eax /* do it! */ DO_RLE(rle, 2, w, %ax, $MASK_COLOR_15) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_trans_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rle_run_loop /* do it! */ DO_RLE(rle_trans, 2, w, %ax, $MASK_COLOR_15) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_lit_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y, int color) * Draws a tinted RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl R_COLOR, %ebx ; \ movl %ecx, R_TMP ; \ ; \ lit_rle_clipped_run_loop##n: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_15) ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP ; \ jg lit_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ movl R_COLOR, %ebx /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP ; \ ; \ lit_rle_run_loop: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_15) ; \ call *GLOBL(_blender_func15) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ decl R_TMP ; \ jg lit_rle_run_loop /* do it! */ DO_RLE(rle_lit, 2, w, %ax, $MASK_COLOR_15) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #undef TEST_RLE_COMMAND #undef RLE_ZEX_EAX #undef RLE_ZEX_ECX #undef RLE_SEX_EAX /* void _linear_draw_trans_rgba_rle_sprite15(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent 32 bit RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rgba_rle_sprite15) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 2), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rgba_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func15x) /* blend */ ; \ addl $12, %esp ; \ movw %ax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $2, %edi ; \ decl R_TMP2 ; \ jg trans_rgba_rle_run_loop /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpl $MASK_COLOR_32, %eax ; \ je done ; \ testl %eax, %eax ; \ js skip /* no zero or sign extend required */ #define RLE_ZEX_EAX() #define RLE_SEX_EAX() /* this can be a simple copy... */ #define RLE_ZEX_ECX() \ movl %eax, %ecx /* do it! */ DO_RLE(rle_trans_rgba, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #endif /* ifdef ALLEGRO_COLOR16 */ allegro-4.4.3.1/src/i386/iblit16.s0000664000175000017500000006073013437077643015224 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit bitmap blitting (written for speed, not readability :-) * * By Shawn Hargreaves. * * MMX clear code by Robert Ohannessian. * * Blitting and masked blitting optimised by Jose Antonio Luque. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "blit.inc" #ifdef ALLEGRO_COLOR16 .text /* void _linear_clear_to_color16(BITMAP *bitmap, int color); * Fills a linear bitmap with the specified color. */ FUNC(_linear_clear_to_color16) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl ARG1, %edx /* edx = bmp */ movl BMP_CT(%edx), %ebx /* line to start at */ movl BMP_SEG(%edx), %eax /* select segment */ movl %eax, %es movl BMP_CR(%edx), %esi /* width to clear */ subl BMP_CL(%edx), %esi #ifdef ALLEGRO_MMX /* only use MMX if compiler supports it */ movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz clear_no_mmx movl %esi, %eax /* If there are less than 16 pixels to clear, then we use the non-MMX version */ shrl $4, %eax orl %eax, %eax jz clear_no_mmx movl ARG2, %eax /* duplicate color twice */ movl %eax, %ecx shll $16, %eax andl $0xFFFF, %ecx orl %ecx, %eax pushl %eax movl %ds, %eax movl %es, %ecx cmpw %ax, %cx /* can we use nearptr ? */ jne clearMMXseg_loop /* if not, then we have to decode segments...*/ /* else, we save one cycle per 4 pixels on PMMX/K6 */ _align_ clearMMX_loop: movl %ebx, %eax movl BMP_CL(%edx), %edi WRITE_BANK() /* select bank */ leal (%eax, %edi, 2), %edi /* get line address */ popl %eax /* get eax back */ movl %esi, %ecx /* width to clear */ movd %eax, %mm0 /* restore mmx reg 0 in case it's been clobbered by WRITE_BANK() */ movd %eax, %mm1 psllq $32, %mm0 por %mm1, %mm0 pushl %eax /* save eax */ testl $7, %edi /* is destination aligned on 64-bit ? */ jz clearMMX_aligned clearMMX_do_alignment: movl %edi, %eax /* we want to adjust %ecx (pairing: see andl) */ movq %mm0, (%edi) /* we clear 4 pixels */ andl $7, %eax /* we calc how may pixels we actually wanted to clear (8 - %eax) (see subl) */ andl $0xFFFFFFF8, %edi /* instruction pairing (see inc %edi) */ shrl $1, %eax subl $4, %eax addl $8, %edi /* we set %edi to the next aligned memory address */ addl %eax, %ecx /* and adjust %ecx to reflect the change */ clearMMX_aligned: movl %ecx, %eax /* save for later */ shrl $4, %ecx /* divide by 16 for 4 * 8-byte memory move */ jz clearMMX_finish_line /* if there's less than 16 pixels to clear, no need for MMX */ clearMMX_continue_line: movq %mm0, (%edi) /* move 4x 8 bytes */ movq %mm0, 8(%edi) /* MMX instructions can't pair when both write to memory */ movq %mm0, 16(%edi) movq %mm0, 24(%edi) addl $32, %edi /* inserting those in the MMX copy block makes no diffrence */ decl %ecx jnz clearMMX_continue_line clearMMX_finish_line: movl %eax, %ecx /* get ecx back */ testl $15, %ecx /* check if there's any left */ jz clearMMX_no_long /* else, write trailing pixels */ testl $8, %ecx jz clearMMX_finish_line2 movq %mm0, (%edi) movq %mm0, 8(%edi) addl $16, %edi clearMMX_finish_line2: testl $4, %ecx jz clearMMX_finish_line3 movq %mm0, (%edi) addl $8, %edi clearMMX_finish_line3: andl $3, %ecx subl $4, %ecx shll $1, %ecx movq %mm0, (%edi, %ecx) clearMMX_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clearMMX_loop /* and loop */ popl %eax emms /* clear FPU tag word */ jmp clear_done clearMMXseg_loop: movl %ebx, %eax movl BMP_CL(%edx), %edi WRITE_BANK() /* select bank */ leal (%eax, %edi, 2), %edi /* get line address */ popl %eax /* get eax back */ movl %esi, %ecx /* width to clear */ movd %eax, %mm0 /* restore mmx reg 0 in case it's been clobbered by WRITE_BANK() */ movd %eax, %mm1 psllq $32, %mm0 por %mm1, %mm0 pushl %eax /* save eax */ testl $7, %edi /* is destination aligned on 64-bit ? */ jz clearMMXseg_aligned clearMMXseg_do_alignment: movl %edi, %eax /* we want to adjust %ecx (pairing: see andl) */ movq %mm0, %es:(%edi) /* we clear 4 pixels */ andl $7, %eax /* we calc how may pixels we actually wanted to clear (8 - %eax) (see subl) */ andl $0xFFFFFFF8, %edi /* instruction pairing (see inc %edi) */ shrl $1, %eax subl $4, %eax addl $8, %edi /* we set %edi to the next aligned memory address */ addl %eax, %ecx /* and adjust %ecx to reflect the change */ clearMMXseg_aligned: movl %ecx, %eax /* save for later */ shrl $4, %ecx /* divide by 16 for 4 * 8-byte memory move */ jz clearMMXseg_finish_line /* if there's less than 16 pixels to clear, no need for MMX */ clearMMXseg_continue_line: movq %mm0, %es:(%edi) movq %mm0, %es:8(%edi) movq %mm0, %es:16(%edi) movq %mm0, %es:24(%edi) addl $32, %edi decl %ecx jnz clearMMXseg_continue_line clearMMXseg_finish_line: movl %eax, %ecx testl $15, %ecx /* check if there's any left */ jz clearMMXseg_no_long /* else, write trailing pixels */ testl $8, %ecx jz clearMMXseg_finish_line2 movq %mm0, %es:(%edi) movq %mm0, %es:8(%edi) addl $16, %edi clearMMXseg_finish_line2: testl $4, %ecx jz clearMMXseg_finish_line3 movq %mm0, %es:(%edi) addl $8, %edi clearMMXseg_finish_line3: andl $3, %ecx subl $4, %ecx shll $1, %ecx movq %mm0, %es:(%edi, %ecx) clearMMXseg_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clearMMXseg_loop /* and loop */ popl %eax emms /* clear FPU tag word */ jmp clear_done #endif /* ALLEGRO_MMX */ clear_no_mmx: /* If no MMX is available, use the non-MMX version */ cld _align_ clear_loop: movl %ebx, %eax movl BMP_CL(%edx), %edi WRITE_BANK() /* select bank */ leal (%eax, %edi, 2), %edi /* get line address */ movw ARG2, %ax /* duplicate color twice */ shll $16, %eax movw ARG2, %ax movl %esi, %ecx /* width to clear */ shrl $1, %ecx /* halve for 32 bit clear */ jnc clear_no_word stosw /* clear an odd word */ clear_no_word: jz clear_no_long rep ; stosl /* clear the line */ clear_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clear_loop /* and loop */ clear_done: popl %es UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_clear_to_color16() */ /* void _linear_blit16(BITMAP *source, BITMAP *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Normal forwards blitting routine for linear bitmaps. */ FUNC(_linear_blit16) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es #ifdef ALLEGRO_MMX /* only use MMX if the compiler supports it */ movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz blit_no_mmx shrl $1, B_WIDTH /* divide for use longs */ jz blit_only_one_word /* blit only one word */ jnc blit_longsmmx shrl $1, B_WIDTH /* divide for use longs64 */ jz blit_long_word /* blit one long and word */ jnc blit_even_wmmxlongs /* blit longs64 and word */ jmp blit_mmxlong_word /* blit longs64 and long and word */ blit_longsmmx: shrl $1, B_WIDTH /* divide for use longs64 */ jz blit_only_one_long /* blit only one long */ jnc blit_even_mmxlongs /* blit longs64 */ _align_ blit_mmxlong_long: /* blit longs64 and long */ #define BLIT_CODE \ even_llmmx_loop: \ movq %ds:(%esi), %mm0 ; \ addl $8, %esi ; \ movq %mm0, %es:(%edi) ; \ addl $8, %edi ; \ decl %ecx ; \ jnz even_llmmx_loop ; \ movsl BLIT_LOOP(long_longsmmx, 2, BLIT_CODE) #undef BLIT_CODE emms jmp blit_done _align_ blit_mmxlong_word: #define BLIT_CODE \ even_wlmmx_loop: \ movq %ds:(%esi), %mm0 ; \ addl $8, %esi ; \ movq %mm0, %es:(%edi) ; \ addl $8, %edi ; \ decl %ecx ; \ jnz even_wlmmx_loop ; \ movsl ; \ movsw BLIT_LOOP(word_longsmmx, 2, BLIT_CODE) #undef BLIT_CODE emms jmp blit_done _align_ blit_even_wmmxlongs: #define BLIT_CODE \ even_wmmx_loop: \ movq %ds:(%esi), %mm0 ; \ addl $8, %esi ; \ movq %mm0, %es:(%edi) ; \ addl $8, %edi ; \ decl %ecx ; \ jnz even_wmmx_loop ; \ movsw BLIT_LOOP(word_wlongsmmx, 2, BLIT_CODE) #undef BLIT_CODE emms jmp blit_done _align_ blit_even_mmxlongs: #define BLIT_CODE \ even_lmmx_loop: \ movq %ds:(%esi), %mm0 ; \ addl $8, %esi ; \ movq %mm0, %es:(%edi) ; \ addl $8, %edi ; \ decl %ecx ; \ jnz even_lmmx_loop BLIT_LOOP(even_longsmmx, 2, BLIT_CODE) #undef BLIT_CODE emms jmp blit_done _align_ blit_long_word: #define BLIT_CODE \ movsl ; \ movsw BLIT_LOOP(long_word, 2, BLIT_CODE) #undef BLIT_CODE emms jmp blit_done _align_ blit_only_one_long: BLIT_LOOP(only_one_wordmmx, 2, movsl) emms jmp blit_done #endif /* ALLEGRO_MMX */ blit_no_mmx: cld /* for forward copy */ shrl $1, B_WIDTH /* halve counter for long copies */ jz blit_only_one_word jnc blit_even_words _align_ #define BLIT_CODE \ rep ; movsl ; \ movsw BLIT_LOOP(longs_and_word, 2, BLIT_CODE) /* long at a time, plus leftover word */ #undef BLIT_CODE jmp blit_done _align_ blit_even_words: #define BLIT_CODE \ rep ; movsl BLIT_LOOP(even_words, 2, BLIT_CODE) /* copy a long at a time */ #undef BLIT_CODE jmp blit_done _align_ blit_only_one_word: BLIT_LOOP(only_one_word, 2, movsw) /* copy just the one word */ _align_ blit_done: popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit16() */ /* void _linear_blit_backward16(BITMAP *source, BITMAP *dest, int source_x, * int source_y, int dest_x, dest_y, int width, height); * Reverse blitting routine, for overlapping linear bitmaps. */ FUNC(_linear_blit_backward16) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_HEIGHT, %eax /* y values go from high to low */ decl %eax addl %eax, B_SOURCE_Y addl %eax, B_DEST_Y movl B_WIDTH, %eax /* x values go from high to low */ decl %eax addl %eax, B_SOURCE_X addl %eax, B_DEST_X movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es _align_ blit_backwards_loop: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ leal (%eax, %edi, 2), %edi movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ leal (%eax, %esi, 2), %esi movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %edx /* load data segment */ movl %edx, %ds std /* backwards */ rep ; movsw /* copy the line */ movl %ebx, %ds /* restore data segment */ decl B_SOURCE_Y decl B_DEST_Y decl B_HEIGHT jg blit_backwards_loop /* and loop */ cld /* finished */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit_backward16() */ FUNC(_linear_blit16_end) ret /* void _linear_masked_blit16(BITMAP *source, *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Masked (skipping zero pixels) blitting routine for linear bitmaps. */ FUNC(_linear_masked_blit16) pushl %ebp movl %esp, %ebp subl $4, %esp /* one local variable */ pushl %edi pushl %esi pushl %ebx pushl %es #define V_MASK -4(%ebp) movl B_DEST, %edx movl %ds, %ebx movl BMP_SEG(%edx), %edx movl %edx, %es cld movl B_SOURCE, %edx movl BMP_VTABLE(%edx), %edx movl VTABLE_MASK_COLOR(%edx), %eax movl %eax, %ecx shll $16, %eax orw %cx, %ax movl %eax, V_MASK #ifdef ALLEGRO_SSE /* Use SSE if the compiler supports it */ /* Speed improvement on the Pentium 3 only, so we need to check for MMX+ and no 3DNow! */ movl GLOBL(cpu_capabilities), %ecx /* if MMX+ is enabled (or not disabled :) */ andl $CPU_MMXPLUS | $CPU_3DNOW, %ecx cmpl $CPU_MMXPLUS, %ecx jne masked16_no_mmx movl B_WIDTH, %ecx shrl $3, %ecx /* Are there more than 8 pixels? Otherwise, use non-MMX code */ jz masked16_no_mmx movd V_MASK, %mm0 /* Create mask (%mm0) */ movd V_MASK, %mm1 psllq $32, %mm0 por %mm1, %mm0 pcmpeqd %mm4, %mm4 /* Create inverter mask */ /* ??? maskmovq is an SSE instruction! */ #define BLIT_CODE \ movd %ecx, %mm2; /* Save line length (%mm2) */ \ shrl $3, %ecx; \ movl V_MASK, %edx; /* Save 32 bit mask */ \ \ pushl %es; /* Swap ES and DS */ \ pushl %ds; \ popl %es; \ popl %ds; \ \ _align_; \ masked16_mmx_x_loop: \ \ movq %es:(%esi), %mm1; /* Read 4 pixels */ \ movq %mm0, %mm3; \ movq %es:8(%esi), %mm5; /* Read 4 more pixels */ \ movq %mm0, %mm6; \ \ pcmpeqw %mm1, %mm3; /* Compare with mask (%mm3/%mm6) */ \ pcmpeqw %mm5, %mm6; \ pxor %mm4, %mm3; /* Turn 1->0 and 0->1 */ \ pxor %mm4, %mm6; \ addl $16, %esi; /* Update src */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ addl $8, %edi; \ maskmovq %mm6, %mm5; \ \ addl $8, %edi; /* Update dest */ \ \ decl %ecx; /* Any pixel packs left for this line? */ \ jnz masked16_mmx_x_loop; \ \ movd %mm2, %ecx; /* Restore pixel count */ \ andl $7, %ecx; \ jz masked16_mmx_loop_end; /* Nothing else to do? */ \ shrl $1, %ecx; /* 1 pixels left */ \ jnc masked16_mmx_long; \ \ movw %es:(%esi), %ax; /* Read 1 pixel */ \ addl $2, %esi; \ addl $2, %edi; \ cmpw %ax, %dx; /* Compare with mask */ \ je masked16_mmx_long; \ movw %ax, -2(%edi); /* Write the pixel */ \ \ masked16_mmx_long: \ \ shrl $1, %ecx; /* 2 pixels left */ \ jnc masked16_mmx_qword; \ \ movl %es:(%esi), %eax; /* Read 2 pixels */ \ addl $4, %esi; \ addl $4, %edi; \ cmpw %ax, %dx; /* Compare with mask */ \ je masked16_mmx_long_2; \ movw %ax, -4(%edi); /* Write pixel */ \ \ masked16_mmx_long_2: \ shrl $16, %eax; \ shrl $16, %edx; \ cmpl %eax, %edx; \ je masked16_mmx_qword; \ movw %ax, -2(%edi); \ \ _align_; \ masked16_mmx_qword: \ shrl $1, %ecx; /* 4 pixels left */ \ jnc masked16_mmx_loop_end; \ \ movq %es:(%esi), %mm1; /* Read 4 more pixels */ \ movq %mm0, %mm3; \ \ pcmpeqw %mm1, %mm3; /* Compare with mask (%mm3, %mm6) */ \ pxor %mm4, %mm3; /* Turn 1->0 and 0->1 */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ \ _align_; \ masked16_mmx_loop_end: \ \ pushl %ds; /* Swap back ES and DS */ \ popl %es; BLIT_LOOP(masked16_mmx_loop, 2, BLIT_CODE) #undef BLIT_CODE emms jmp masked16_end; #endif _align_ masked16_no_mmx: #define BLIT_CODE \ movl V_MASK, %edx ; \ \ test $1, %ecx ; /* 32 bit aligned->use new code */ \ jz masked32_blit_x_loop ; \ movw (%esi), %ax ; /* read a pixel */ \ cmpw %ax, %dx ; /* test it */ \ je masked16_blit_skip ; \ movw %ax, %es:(%edi) ; /* write the pixel */ \ masked16_blit_skip: \ decl %ecx ; \ jng masked32_blit_end ; \ addl $2, %esi ; \ addl $2, %edi ; \ \ _align_ ; \ masked32_blit_x_loop: \ movl (%esi), %eax ; /* read two pixels */ \ addl $4, %esi ; \ cmpl %eax, %edx ; /* test it */ \ je masked32_blit_skip2 ; \ cmpw %ax, %dx ; /* test it */ \ je masked32_blit_skip1 ; \ movw %ax, %es:(%edi) ; /* write the pixel */ \ masked32_blit_skip1: \ shrl $16, %eax ; \ cmpw %ax, %dx ; /* test it */ \ je masked32_blit_skip2 ; \ movw %ax, %es:2(%edi) ; /* write the pixel */ \ masked32_blit_skip2: \ addl $4, %edi ; \ subl $2, %ecx ; \ jg masked32_blit_x_loop ; \ masked32_blit_end: BLIT_LOOP(masked32, 2, BLIT_CODE) #undef BLIT_CODE masked16_end: popl %es /* the source must be a memory bitmap, no need for * movl B_SOURCE, %edx * UNREAD_BANK() */ movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_masked_blit16() */ #endif /* ifdef ALLEGRO_COLOR16 */ allegro-4.4.3.1/src/i386/izbuf.s0000664000175000017500000022420113437077643015064 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Z-buffered polygon scanline filler helpers (gouraud shading, tmapping, etc). * Uses MMX instructions when possible, but these will be #ifdef'ed * out if your assembler doesn't support them. * * By Calin Andrian. * * Updated to Allegro 3.9.34 by Bertrand Coconnier. * * See readme.txt for copyright information. */ #include "asmdefs.inc" .text /* all these functions share the same parameters */ #define ADDR ARG1 #define W ARG2 #define INFO ARG3 #define ZBUF -4(%ebp) /* first part of a flat routine */ #define INIT_FLAT(bpp, extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl ADDR, %edi ; \ movl W, %ecx ; \ movl INFO, %esi ; \ ; \ flds POLYSEG_DZ(%esi) ; \ flds POLYSEG_Z(%esi) ; \ movl POLYSEG_C(%esi), %edx ; \ movl POLYSEG_ZBADDR(%esi), %esi ; \ extra ; \ ; \ subl $bpp, %edi ; \ subl $4, %esi ; \ ; \ _align_ ; \ 1: ; \ fcoms 4(%esi) ; \ addl $bpp, %edi ; \ fnstsw %ax ; \ addl $4, %esi ; \ andb $0x41, %ah ; \ jnz 2f /* with the andb above, it means jbe */ /* end of flat routine */ #define END_FLAT() \ fsts (%esi) ; \ 2: ; \ fadd %st(1), %st(0) ; \ decl %ecx ; \ jg 1b ; \ fstp %st(0) ; \ fstp %st(0) ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_flat8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills a single-color flat polygon scanline. */ FUNC(_poly_zbuf_flat8) INIT_FLAT(1, /**/) movb %dl, FSEG(%edi) END_FLAT() ret /* end of _poly_zbuf_flat8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_flat16(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills a single-color flat polygon scanline. */ FUNC(_poly_zbuf_flat16) INIT_FLAT(2, /**/) movw %dx, FSEG(%edi) END_FLAT() ret /* end of _poly_zbuf_flat16() */ #endif #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_flat32(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills a single-color flat polygon scanline. */ FUNC(_poly_zbuf_flat32) INIT_FLAT(4, /**/) movl %edx, FSEG(%edi) END_FLAT() ret /* end of _poly_zbuf_flat32() */ #endif #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_flat24(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills a single-color flat polygon scanline. */ FUNC(_poly_zbuf_flat24) #define INIT_CODE \ movl %edx, %ebx ; \ shrl $16, %ebx INIT_FLAT(3, INIT_CODE) #undef INIT_CODE movw %dx, FSEG(%edi) movb %bl, FSEG 2(%edi) END_FLAT() ret /* end of _poly_zbuf_flat24() */ #endif #define DB -8(%ebp) #define DG -12(%ebp) #define DR -16(%ebp) #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_gcol8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills a single-color gouraud shaded polygon scanline. */ FUNC(_poly_zbuf_gcol8) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi movl ADDR, %edi movl INFO, %esi movl W, %ecx flds POLYSEG_DZ(%esi) flds POLYSEG_Z(%esi) movl POLYSEG_C(%esi), %edx movl POLYSEG_DC(%esi), %ebx movl POLYSEG_ZBADDR(%esi), %esi subl %ebx, %edx decl %edi subl $4, %esi _align_ 1: fcoms 4(%esi) addl %ebx, %edx addl $4, %esi fnstsw %ax incl %edi andb $0x41, %ah jnz 2f movl %edx, %eax shrl $16, %eax movb %al, FSEG(%edi) fsts (%esi) 2: fadd %st(1), %st(0) decl %ecx jg 1b fstp %st(0) fstp %st(0) popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_zbuf_gcol8() */ /* void _poly_zbuf_grgb8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_zbuf_grgb8) pushl %ebp movl %esp, %ebp subl $16, %esp pushl %ebx pushl %esi pushl %edi movl INFO, %esi flds POLYSEG_DZ(%esi) flds POLYSEG_Z(%esi) movl POLYSEG_ZBADDR(%esi), %ecx movl POLYSEG_DR(%esi), %eax movl %ecx, ZBUF movl POLYSEG_DG(%esi), %ebx movl POLYSEG_DB(%esi), %ecx movl %eax, DR movl %ebx, DG movl %ecx, DB movl POLYSEG_R(%esi), %ebx movl POLYSEG_G(%esi), %ecx movl POLYSEG_B(%esi), %edx movl ADDR, %edi subl DR, %ebx subl DG, %ecx subl DB, %edx decl %edi _align_ 1: movl ZBUF, %esi addl DR, %ebx fcoms (%esi) addl DG, %ecx addl DB, %edx fnstsw %ax incl %edi andb $0x41, %ah jnz 2f movl %ecx, %eax /* green */ movl %ebx, %esi /* red */ shrl $19, %eax /* green */ shrl $19, %esi /* red */ shll $5, %eax /* green */ shll $10, %esi /* red */ orl %eax, %esi /* green */ movl %edx, %eax /* blue */ shrl $19, %eax /* blue */ orl %eax, %esi /* blue */ movl GLOBL(rgb_map), %eax /* table lookup */ movb (%eax, %esi), %al movb %al, FSEG(%edi) /* write the pixel */ movl ZBUF, %esi fsts (%esi) 2: fadd %st(1), %st(0) addl $4, ZBUF decl W jg 1b fstp %st(0) fstp %st(0) popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_zbuf_grgb8() */ #endif /* first part of a grgb routine */ #define INIT_GRGB(depth, r_sft, g_sft, b_sft) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $16, %esp ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ ; \ flds POLYSEG_DZ(%esi) ; \ flds POLYSEG_Z(%esi) ; \ movl POLYSEG_ZBADDR(%esi), %edx ; \ movl POLYSEG_DR(%esi), %ebx /* move delta's on stack */ ; \ movl %edx, ZBUF ; \ movl POLYSEG_DG(%esi), %edi ; \ movl POLYSEG_DB(%esi), %edx ; \ movl %ebx, DR ; \ movl %edi, DG ; \ movl %edx, DB ; \ ; \ movl POLYSEG_R(%esi), %ebx ; \ movl POLYSEG_G(%esi), %edi ; \ movl POLYSEG_B(%esi), %edx ; \ ; \ subl DR, %ebx ; \ subl DG, %edi ; \ subl DB, %edx ; \ ; \ _align_ ; \ 1: ; \ movl ZBUF, %esi ; \ addl DR, %ebx ; \ fcoms (%esi) ; \ addl DG, %edi ; \ addl DB, %edx ; \ fnstsw %ax ; \ andb $0x41, %ah ; \ jnz 2f ; \ ; \ movl %ebx, %eax /* red */ ; \ movb GLOBL(_rgb_r_shift_##depth), %cl ; \ shrl $r_sft, %eax ; \ shll %cl, %eax ; \ movl %edi, %esi /* green */ ; \ movb GLOBL(_rgb_g_shift_##depth), %cl ; \ shrl $g_sft, %esi ; \ shll %cl, %esi ; \ orl %esi, %eax ; \ movl %edx, %esi /* blue */ ; \ movb GLOBL(_rgb_b_shift_##depth), %cl ; \ shrl $b_sft, %esi ; \ shll %cl, %esi ; \ orl %esi, %eax ; \ movl ADDR, %esi /* end of grgb routine */ #define END_GRGB(bpp) \ movl ZBUF, %esi ; \ fsts (%esi) ; \ 2: ; \ fadd %st(1), %st(0) ; \ addl $4, ZBUF ; \ addl $bpp, ADDR ; \ decl W ; \ jg 1b ; \ ; \ fstp %st(0) ; \ fstp %st(0) ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_grgb15(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_zbuf_grgb15) INIT_GRGB(15, 19, 19, 19) movw %ax, FSEG(%esi) /* write the pixel */ END_GRGB(2) ret /* end of _poly_zbuf_grgb15() */ /* void _poly_zbuf_grgb16(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_zbuf_grgb16) INIT_GRGB(16, 19, 18, 19) movw %ax, FSEG(%esi) /* write the pixel */ END_GRGB(2) ret /* end of _poly_zbuf_grgb16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_grgb32(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_zbuf_grgb32) INIT_GRGB(32, 16, 16, 16) movl %eax, FSEG(%esi) /* write the pixel */ END_GRGB(4) ret /* end of _poly_zbuf_grgb32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_grgb24(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an RGB gouraud shaded polygon scanline. */ FUNC(_poly_zbuf_grgb24) INIT_GRGB(24, 16, 16, 16) movw %ax, FSEG(%esi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%esi) END_GRGB(3) ret /* end of _poly_zbuf_grgb24() */ #endif /* COLOR24 */ #undef DR #undef DG #undef DB #define VMASK -8(%ebp) #define VSHIFT -12(%ebp) #define DV -16(%ebp) #define DU -20(%ebp) #define ALPHA2 -22(%ebp) #define ALPHA -24(%ebp) #define DALPHA -28(%ebp) #define UMASK -32(%ebp) #define READ_ADDR -36(%ebp) /* first part of an affine texture mapping operation */ #define INIT_ATEX(extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $36, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ extra ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %eax ; \ movl POLYSEG_ZBADDR(%esi), %ebx ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ movl %ebx, ZBUF ; \ addl $16, %ecx ; \ movl %eax, VMASK ; \ movl %ecx, VSHIFT ; \ ; \ movl POLYSEG_UMASK(%esi), %eax ; \ movl POLYSEG_DU(%esi), %ebx ; \ movl POLYSEG_DV(%esi), %edx ; \ movl %eax, UMASK ; \ movl %ebx, DU ; \ movl %edx, DV ; \ ; \ flds POLYSEG_DZ(%esi) ; \ flds POLYSEG_Z(%esi) ; \ movl POLYSEG_U(%esi), %ebx ; \ movl POLYSEG_V(%esi), %edx ; \ movl ADDR, %edi ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ ; \ subl DU, %ebx ; \ subl DV, %edx ; \ ; \ _align_ ; \ 1: ; \ movl ZBUF, %ecx ; \ addl DU, %ebx ; \ fcoms (%ecx) ; \ addl DV, %edx ; \ fnstsw %ax ; \ andb $0x41, %ah ; \ jnz 2f ; \ ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax /* end of atex routine */ #define END_ATEX(extra) \ movl ZBUF, %ecx ; \ fsts (%ecx) ; \ 2: ; \ fadd %st(1), %st(0) ; \ addl $4, ZBUF ; \ extra ; \ decl W ; \ jg 1b ; \ ; \ fstp %st(0) ; \ fstp %st(0) ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_atex8(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex8) INIT_ATEX(/**/) movb (%esi, %eax), %al /* read texel */ movb %al, FSEG(%edi) /* write the pixel */ END_ATEX(incl %edi) ret /* end of _poly_zbuf_atex8() */ /* void _poly_zbuf_atex_mask8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask8) INIT_ATEX(/**/) movb (%esi, %eax), %al /* read texel */ orb %al, %al jz 2f movb %al, FSEG(%edi) /* write solid pixels */ END_ATEX(incl %edi) ret /* end of _poly_zbuf_atex_mask8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_atex16(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex16) INIT_ATEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ #define END_CODE \ addl $2, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex16() */ /* void _poly_zbuf_atex_mask15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask15) INIT_ATEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 2f movw %ax, FSEG(%edi) /* write solid pixels */ #define END_CODE \ addl $2, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask15() */ /* void _poly_zbuf_atex_mask16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask16) INIT_ATEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 2f movw %ax, FSEG(%edi) /* write solid pixels */ #define END_CODE \ addl $2, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_atex32(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex32) INIT_ATEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ movl %eax, FSEG(%edi) /* write the pixel */ #define END_CODE \ addl $4, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex32() */ /* void _poly_zbuf_atex_mask32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask32) INIT_ATEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 2f movl %eax, FSEG(%edi) /* write solid pixels */ #define END_CODE \ addl $4, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_atex24(unsigned long addr, int w, POLYGON_SEGMENT *info); * Fills an affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex24) INIT_ATEX(/**/) leal (%eax, %eax, 2), %ecx movw (%esi, %ecx), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ movb 2(%esi, %ecx), %al /* read texel */ movb %al, FSEG 2(%edi) /* write the pixel */ #define END_CODE \ addl $3, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex24() */ /* void _poly_zbuf_atex_mask24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask24) INIT_ATEX(/**/) leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 2f movw %ax, FSEG(%edi) /* write solid pixels */ shrl $16, %eax movb %al, FSEG 2(%edi) #define END_CODE \ addl $3, %edi END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_atex_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ movb ALPHA2, %ah movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ movl DALPHA, %eax ; \ incl %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_lit8() */ /* void _poly_zbuf_atex_mask_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 2f movb ALPHA2, %ah movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ movl DALPHA, %eax ; \ incl %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_lit8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_atex_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_lit15() */ /* void _poly_zbuf_atex_mask_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_lit15() */ /* void _poly_zbuf_atex_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_lit16() */ /* void _poly_zbuf_atex_mask_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_lit16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_atex_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movl (%esi, %eax, 4), %eax /* read texel */ pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $4, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_lit32() */ /* void _poly_zbuf_atex_mask_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $4, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_lit32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_atex_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx leal (%eax, %eax, 2), %ecx movb 2(%esi, %ecx), %al /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $3, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_lit24() */ /* void _poly_zbuf_atex_mask_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_ATEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $3, %edi ; \ addl %eax, ALPHA END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_lit24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_atex_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ incl %edi ; \ incl READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_trans8() */ /* void _poly_zbuf_atex_mask_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 2f shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ incl %edi ; \ incl READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_trans8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_atex_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_trans15() */ /* void _poly_zbuf_atex_mask_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 2f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_trans15() */ /* void _poly_zbuf_atex_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_trans16() */ /* void _poly_zbuf_atex_mask_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 2f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_trans16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_atex_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) movl %edi, ALPHA movl READ_ADDR, %edi pushl FSEG (%edi) movl ALPHA, %edi pushl (%esi, %eax, 4) call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $4, %edi ; \ addl $4, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_trans32() */ /* void _poly_zbuf_atex_mask_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 2f pushl %edx pushl GLOBL(_blender_alpha) movl %edi, ALPHA movl READ_ADDR, %edi pushl FSEG (%edi) movl ALPHA, %edi pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $4, %edi ; \ addl $4, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_trans32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_atex_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) leal (%eax, %eax, 2), %ecx pushl %edi movl READ_ADDR, %edi movb FSEG 2(%edi), %dl movb 2(%esi, %ecx), %al /* read texel */ shll $16, %edx shll $16, %eax movw FSEG (%edi), %dx popl %edi movw (%esi, %ecx), %ax pushl %edx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ addl $3, %edi ; \ addl $3, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_trans24() */ /* void _poly_zbuf_atex_mask_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans affine texture mapped polygon scanline. */ FUNC(_poly_zbuf_atex_mask_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_ATEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 2f movl %edi, ALPHA movl READ_ADDR, %edi movb FSEG 2(%edi), %cl pushl %edx movl ALPHA, %edi pushl GLOBL(_blender_alpha) shll $16, %ecx movw FSEG (%edi), %cx pushl %ecx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ addl $3, %edi ; \ addl $3, READ_ADDR END_ATEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_atex_mask_trans24() */ #endif /* COLOR24 */ #undef VMASK #undef VSHIFT #undef UMASK #undef DU #undef DV #undef ALPHA #undef ALPHA2 #undef DALPHA #undef READ_ADDR #define VMASK -8(%ebp) #define VSHIFT -12(%ebp) #define ALPHA -16(%ebp) #define DALPHA -20(%ebp) #define U1 -24(%ebp) #define V1 -28(%ebp) #define DU -32(%ebp) #define DV -36(%ebp) #define DZ -40(%ebp) #define DU4 -44(%ebp) #define DV4 -48(%ebp) #define DZ4 -52(%ebp) #define UMASK -56(%ebp) #define COUNT -60(%ebp) #define READ_ADDR -64(%ebp) /* helper for starting an fpu 1/z division */ #define START_FP_DIV() \ fld1 ; \ fdiv %st(1), %st(0) /* helper for ending an fpu division, returning corrected u and v values */ #define END_FP_DIV() \ fst %st(1) /* duplicate the 1/z value */ ; \ fmul %st(3), %st(0) /* divide u by z */ ; \ fxch %st(1) ; \ fmul %st(2), %st(0) /* divide v by z */ #define UPDATE_FP_POS_4() \ fadds DV4 /* update v coord */ ; \ fxch %st(1) /* swap vuz stack to uvz */ ; \ fadds DU4 /* update u coord */ ; \ fxch %st(1) /* swap uvz stack back to vuz */ ; \ fld %st(2) /* zvuz */ ; \ fadds DZ4 /* update z value */ /* main body of the perspective-correct texture mapping routine */ #define INIT_PTEX(extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $64, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ ; \ flds POLYSEG_DFU(%esi) /* multiply diffs by four */ ; \ flds POLYSEG_DFV(%esi) ; \ flds POLYSEG_DZ(%esi) ; \ fsts DZ ; \ fxch %st(2) /* u v z */ ; \ fadd %st(0), %st(0) /* 2u v z */ ; \ fxch %st(1) /* v 2u z */ ; \ fadd %st(0), %st(0) /* 2v 2u z */ ; \ fxch %st(2) /* z 2u 2v */ ; \ fadd %st(0), %st(0) /* 2z 2u 2v */ ; \ fxch %st(1) /* 2u 2z 2v */ ; \ fadd %st(0), %st(0) /* 4u 2z 2v */ ; \ fxch %st(2) /* 2v 2z 4u */ ; \ fadd %st(0), %st(0) /* 4v 2z 4u */ ; \ fxch %st(1) /* 2z 4v 4u */ ; \ fadd %st(0), %st(0) /* 4z 4v 4u */ ; \ fxch %st(2) /* 4u 4v 4z */ ; \ fstps DU4 ; \ fstps DV4 ; \ fstps DZ4 ; \ ; \ flds POLYSEG_Z(%esi) /* z at bottom of fpu stack */ ; \ flds POLYSEG_FU(%esi) /* followed by u */ ; \ flds POLYSEG_FV(%esi) /* followed by v */ ; \ fld %st(2) /* zvuz */ ; \ ; \ START_FP_DIV() ; \ ; \ extra ; \ ; \ movl POLYSEG_ZBADDR(%esi), %edx ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl %edx, ZBUF ; \ movl POLYSEG_VMASK(%esi), %eax ; \ movl POLYSEG_UMASK(%esi), %edx ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ addl $16, %ecx ; \ movl %ecx, VSHIFT ; \ movl %eax, VMASK ; \ movl %edx, UMASK ; \ ; \ END_FP_DIV() ; \ fistpl V1 /* store v */ ; \ fistpl U1 /* store u */ ; \ UPDATE_FP_POS_4() ; \ START_FP_DIV() ; \ ; \ movl ADDR, %edi ; \ movl V1, %edx ; \ movl U1, %ebx ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ movl $0, COUNT /* COUNT ranges from 3 to -1 */ ; \ jmp 3f ; \ ; \ _align_ ; \ 1: /* step 2: compute DU, DV for next 4 steps */ ; \ movl $3, COUNT ; \ ; \ END_FP_DIV() /* finish the divide */ ; \ fistpl V1 ; \ fistpl U1 ; \ UPDATE_FP_POS_4() /* 4 pixels away */ ; \ START_FP_DIV() ; \ ; \ movl V1, %eax ; \ movl U1, %ecx ; \ subl %edx, %eax ; \ subl %ebx, %ecx ; \ sarl $2, %eax ; \ sarl $2, %ecx ; \ movl %eax, DV ; \ movl %ecx, DU ; \ 4: /* step 3 & 4: next U, V */ ; \ addl DV, %edx ; \ addl DU, %ebx ; \ 3: /* step 1: just use U and V */ ; \ movl ZBUF, %ecx ; \ fxch %st(4) ; \ fcoms (%ecx) ; \ fnstsw %ax ; \ andb $0x41, %ah ; \ jnz 2f ; \ ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax #define END_PTEX(extra) \ movl ZBUF, %ecx ; \ fsts (%ecx) ; \ 2: ; \ fadds DZ ; \ fxch %st(4) ; \ addl $4, ZBUF ; \ ; \ extra ; \ decl W ; \ jle 6f ; \ decl COUNT ; \ jg 4b ; \ nop ; \ jl 1b ; \ movl V1, %edx ; \ movl U1, %ebx ; \ jmp 3b ; \ _align_ ; \ 6: ; \ fstp %st(0) /* pop fpu stack */ ; \ fstp %st(0) ; \ fstp %st(0) ; \ fstp %st(0) ; \ fstp %st(0) ; \ ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_ptex8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex8) INIT_PTEX(/**/) movb (%esi, %eax), %al /* read texel */ movb %al, FSEG(%edi) /* write the pixel */ END_PTEX(incl %edi) ret /* end of _poly_zbuf_ptex8() */ /* void _poly_zbuf_ptex_mask8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask8) INIT_PTEX(/**/) movb (%esi, %eax), %al /* read texel */ orb %al, %al jz 2f movb %al, FSEG(%edi) /* write solid pixels */ END_PTEX(incl %edi) ret /* end of _poly_zbuf_ptex_mask8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_ptex16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex16) INIT_PTEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ #define END_CODE \ addl $2, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex16() */ /* void _poly_zbuf_ptex_mask15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask15) INIT_PTEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 2f movw %ax, FSEG(%edi) /* write solid pixels */ #define END_CODE \ addl $2, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask15() */ /* void _poly_zbuf_ptex_mask16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask16) INIT_PTEX(/**/) movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 2f movw %ax, FSEG(%edi) /* write solid pixels */ #define END_CODE \ addl $2, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_ptex32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex32) INIT_PTEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ movl %eax, FSEG(%edi) /* write the pixel */ #define END_CODE \ addl $4, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex32() */ /* void _poly_zbuf_ptex_mask32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask32) INIT_PTEX(/**/) movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 2f movl %eax, FSEG(%edi) /* write solid pixels */ #define END_CODE \ addl $4, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_ptex24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex24) INIT_PTEX(/**/) leal (%eax, %eax, 2), %ecx movw (%esi, %ecx), %ax /* read texel */ movw %ax, FSEG(%edi) /* write the pixel */ movb 2(%esi, %ecx), %al /* read texel */ movb %al, FSEG 2(%edi) /* write the pixel */ #define END_CODE \ addl $3, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex24() */ /* void _poly_zbuf_ptex_mask24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a masked perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask24) INIT_PTEX(/**/) leal (%eax, %eax, 2), %ecx xorl %eax, %eax movb 2(%esi, %ecx), %al /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 2f movw %ax, FSEG(%edi) /* write solid pixels */ shrl $16, %eax movb %al, FSEG 2(%edi) #define END_CODE \ addl $3, %edi END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_ptex_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ movb 2+ALPHA, %ah movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ movl DALPHA, %eax ; \ incl %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_lit8() */ /* void _poly_zbuf_ptex_mask_lit8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_lit8) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 2f movb 2+ALPHA, %ah movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ movl DALPHA, %eax ; \ incl %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_lit8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_ptex_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_lit15() */ /* void _poly_zbuf_ptex_mask_lit15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_lit15) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_15) pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_lit15() */ /* void _poly_zbuf_ptex_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movw (%esi, %eax, 2), %ax /* read texel */ pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_lit16() */ /* void _poly_zbuf_ptex_mask_lit16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_lit16) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_16) pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $2, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_lit16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_ptex_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx movl (%esi, %eax, 4), %eax /* read texel */ pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $4, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_lit32() */ /* void _poly_zbuf_ptex_mask_lit32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_lit32) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_32) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $4, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_lit32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_ptex_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx movzbl 2+ALPHA, %edx pushl %edx leal (%eax, %eax, 2), %ecx movb 2(%esi, %ecx), %al /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $3, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_lit24() */ /* void _poly_zbuf_ptex_mask_lit24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a lit perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_lit24) #define INIT_CODE \ movl POLYSEG_C(%esi), %eax ; \ movl POLYSEG_DC(%esi), %edx ; \ movl %eax, ALPHA ; \ movl %edx, DALPHA INIT_PTEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 2f pushl %edx movzbl 2+ALPHA, %edx pushl %edx pushl GLOBL(_blender_col_24) pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ movl DALPHA, %eax ; \ addl $3, %edi ; \ addl %eax, ALPHA END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_lit24() */ #endif /* COLOR24 */ #ifdef ALLEGRO_COLOR8 /* void _poly_zbuf_ptex_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ incl %edi ; \ incl READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_trans8() */ /* void _poly_zbuf_ptex_mask_trans8(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_trans8) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movzbl (%esi, %eax), %eax /* read texel */ orl %eax, %eax jz 2f shll $8, %eax pushl %edi movl READ_ADDR, %edi movb FSEG (%edi), %al popl %edi movl GLOBL(color_map), %ecx movb (%ecx, %eax), %al movb %al, FSEG(%edi) #define END_CODE \ incl %edi ; \ incl READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_trans8() */ #endif #ifdef ALLEGRO_COLOR16 /* void _poly_zbuf_ptex_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_trans15() */ /* void _poly_zbuf_ptex_mask_trans15(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_trans15) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_15, %ax jz 2f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func15) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_trans15() */ /* void _poly_zbuf_ptex_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi movw (%esi, %eax, 2), %ax /* read texel */ pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_trans16() */ /* void _poly_zbuf_ptex_mask_trans16(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_trans16) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax /* read texel */ cmpw $MASK_COLOR_16, %ax jz 2f pushl %edi movl READ_ADDR, %edi movw FSEG (%edi), %cx popl %edi pushl %edx pushl GLOBL(_blender_alpha) pushl %ecx pushl %eax call *GLOBL(_blender_func16) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $2, %edi ; \ addl $2, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_trans16() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 /* void _poly_zbuf_ptex_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) movl %edi, ALPHA movl READ_ADDR, %edi pushl FSEG (%edi) movl ALPHA, %edi pushl (%esi, %eax, 4) call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $4, %edi ; \ addl $4, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_trans32() */ /* void _poly_zbuf_ptex_mask_trans32(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_trans32) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax /* read texel */ cmpl $MASK_COLOR_32, %eax jz 2f pushl %edx pushl GLOBL(_blender_alpha) movl %edi, ALPHA movl READ_ADDR, %edi pushl FSEG (%edi) movl ALPHA, %edi pushl %eax call *GLOBL(_blender_func32) addl $12, %esp movl %eax, FSEG(%edi) /* write the pixel */ popl %edx #define END_CODE \ addl $4, %edi ; \ addl $4, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_trans32() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 /* void _poly_zbuf_ptex_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE pushl %edx pushl GLOBL(_blender_alpha) leal (%eax, %eax, 2), %ecx pushl %edi movl READ_ADDR, %edi movb FSEG 2(%edi), %dl movb 2(%esi, %ecx), %al /* read texel */ shll $16, %edx shll $16, %eax movw FSEG (%edi), %dx popl %edi movw (%esi, %ecx), %ax pushl %edx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ addl $3, %edi ; \ addl $3, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_trans24() */ /* void _poly_zbuf_ptex_mask_trans24(ulong addr, int w, POLYGON_SEGMENT *info); * Fills a trans perspective correct texture mapped polygon scanline. */ FUNC(_poly_zbuf_ptex_mask_trans24) #define INIT_CODE \ movl POLYSEG_RADDR(%esi), %eax ; \ movl %eax, READ_ADDR INIT_PTEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax /* read texel */ shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 2f movl %edi, ALPHA movl READ_ADDR, %edi movb FSEG 2(%edi), %cl pushl %edx pushl GLOBL(_blender_alpha) shll $16, %ecx movw FSEG (%edi), %cx movl ALPHA, %edi pushl %ecx pushl %eax call *GLOBL(_blender_func24) addl $12, %esp movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) popl %edx #define END_CODE \ addl $3, %edi ; \ addl $3, READ_ADDR END_PTEX(END_CODE) #undef END_CODE ret /* end of _poly_zbuf_ptex_mask_trans24() */ #endif /* COLOR24 */ allegro-4.4.3.1/src/i386/iblit24.s0000664000175000017500000002204313437077643015216 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit bitmap blitting (written for speed, not readability :-) * * By Michal Mertl. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "blit.inc" #ifdef ALLEGRO_COLOR24 .text /* void _linear_clear_to_color24(BITMAP *bitmap, int color); * Fills a linear bitmap with the specified color. */ FUNC(_linear_clear_to_color24) pushl %ebp movl %esp, %ebp subl $12, %esp /* 12 bytes temp space for local variables */ pushl %edi pushl %ebx pushl %es movl ARG1, %edx /* edx = bmp */ movl BMP_CT(%edx), %ebx /* line to start at */ movl BMP_SEG(%edx), %eax /* select segment */ movl %eax, %es cld movl ARG2, %eax /* pixel color */ movl %eax, -8(%ebp) movl %eax, -5(%ebp) movl %ebx, ARG2 /* line to start at (in ARG2 is line now)*/ movl BMP_CB(%edx), %eax subl %ebx, %eax movl %eax, -12(%ebp) /* line counter */ movl BMP_CR(%edx), %ecx subl BMP_CL(%edx), %ecx /* line length */ _align_ clear_loop: pushl %ecx movl ARG2, %eax movl ARG1, %edx movl BMP_CL(%edx), %edi /* xstart */ WRITE_BANK() /* select bank */ leal (%edi, %edi, 2), %edi /* xstart *= 3 */ addl %eax, %edi /* address = lineoffset+xstart*3 */ movl -8(%ebp), %eax movl -7(%ebp), %ebx movl -6(%ebp), %edx cmpl $4, %ecx jb clear_short_line subl $4, %ecx /* test loop for sign flag */ cld _align_ clear_inner_loop: /* plots 4 pixels an once */ movl %eax, %es:(%edi) movl %ebx, %es:4(%edi) movl %edx, %es:8(%edi) addl $12, %edi subl $4, %ecx jns clear_inner_loop addl $4, %ecx /* add the helper back */ jz clear_normal_line _align_ clear_short_line: movw %ax, %es:(%edi) /* plots remaining pixels (max 3) */ movb %dl, %es:2(%edi) addl $3, %edi decl %ecx jg clear_short_line _align_ clear_normal_line: popl %ecx incl ARG2 /* inc current line */ decl -12(%ebp) /* dec loop counter */ jnz clear_loop /* and loop */ popl %es movl ARG1, %edx UNWRITE_BANK() popl %ebx popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_clear_to_color() */ /* void _linear_blit24(BITMAP *source, BITMAP *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Normal forwards blitting routine for linear bitmaps. */ FUNC(_linear_blit24) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es movl B_DEST_X, %edi leal (%edi, %edi, 2), %edi movl %edi, B_DEST_X movl B_SOURCE_X, %esi leal (%esi, %esi, 2), %esi movl %esi, B_SOURCE_X movl B_WIDTH, %ecx leal (%ecx, %ecx, 2), %ecx movl %ecx, B_WIDTH movl %ds, %ebx /* save data segment selector */ cld /* for forward copy */ _align_ blit_loop_blitter24: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi /* edi = eax+3*edi */ movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi /* esi = eax+3*esi */ movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds shrl $1, %ecx jnc notcarry1 movsb _align_ notcarry1: shrl $1, %ecx jnc notcarry2 movsw _align_ notcarry2: rep ; movsl movl %ebx, %ds /* restore data segment */ incl B_SOURCE_Y incl B_DEST_Y decl B_HEIGHT jg blit_loop_blitter24 /* and loop */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit24() */ /* void _linear_blit_backward24(BITMAP *source, BITMAP *dest, int source_x, * int source_y, int dest_x, dest_y, int width, height); * Reverse blitting routine, for overlapping linear bitmaps. */ FUNC(_linear_blit_backward24) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_HEIGHT, %eax /* y values go from high to low */ decl %eax addl %eax, B_SOURCE_Y addl %eax, B_DEST_Y movl B_WIDTH, %eax /* x values go from high to low */ decl %eax addl %eax, B_SOURCE_X addl %eax, B_DEST_X movl B_DEST_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_DEST_X movl B_SOURCE_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_SOURCE_X movl B_WIDTH, %eax leal (%eax, %eax, 2), %eax movl %eax, B_WIDTH movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es _align_ blit_backwards_loop: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi /* edi = eax+3*esi */ movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi /* esi = eax+3*esi */ movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds std /* backwards */ shrl $1, %ecx jnc not_carry1 movsb _align_ not_carry1: shrl $1, %ecx jnc not_carry2 movsw _align_ not_carry2: rep ; movsl movl %ebx, %ds /* restore data segment */ decl B_SOURCE_Y decl B_DEST_Y decl B_HEIGHT jg blit_backwards_loop /* and loop */ cld /* finished */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit_backward24() */ FUNC(_linear_blit24_end) ret /* void _linear_masked_blit24(BITMAP *source, *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Masked (skipping zero pixels) blitting routine for linear bitmaps. */ FUNC(_linear_masked_blit24) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx movl BMP_SEG(%edx), %eax movl %eax, %es cld movl B_DEST_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_DEST_X movl B_SOURCE_X, %eax leal (%eax, %eax, 2), %eax movl %eax, B_SOURCE_X _align_ blit_loop_blitter: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi movl B_SOURCE,%edx movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi movl B_WIDTH, %ecx /* x loop counter */ _align_ inner: lodsl decl %esi andl $0xFFFFFF, %eax cmpl $MASK_COLOR_24, %eax je masked_blit_skip movw %ax, %es:(%edi) shrl $16, %eax movb %al, %es:2(%edi) addl $3, %edi jmp befloop _align_ masked_blit_skip: addl $3, %edi _align_ befloop: loop inner movl %ebx, %ds /* restore data segment */ incl B_SOURCE_Y incl B_DEST_Y decl B_HEIGHT jg blit_loop_blitter /* and loop */ popl %es /* the source must be a memory bitmap, no need for * movl B_SOURCE, %edx * UNREAD_BANK() */ movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_masked_blit24() */ #endif /* ifdef ALLEGRO_COLOR24 */ allegro-4.4.3.1/src/i386/ispr32.s0000664000175000017500000005262213437077643015075 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit sprite drawing (written for speed, not readability :-) * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "sprite.inc" #ifdef ALLEGRO_COLOR32 .text /* void _linear_draw_sprite32(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite onto a linear bitmap at the specified x, y position, * using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_sprite32) START_SPRITE_DRAW(sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(draw_sprite) movl (%esi), %ebx /* read a pixel */ cmpl $MASK_COLOR_32, %ebx /* test */ jz draw_sprite_skip movl %ebx, %es:(%eax) /* write */ draw_sprite_skip: addl $4, %esi addl $4, %eax SPRITE_END_X(draw_sprite) SPRITE_END_Y(draw_sprite) _align_ sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite32() */ FUNC(_linear_draw_sprite32_end) ret /* void _linear_draw_256_sprite32(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a 256 color sprite onto a linear bitmap at the specified x, y * position, using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_256_sprite32) START_SPRITE_DRAW(sprite256) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ pushl %edx /* get color expansion lookup table */ pushl $32 call *GLOBL(_palette_expansion_table) addl $4, %esp popl %edx movl %eax, %edi _align_ SPRITE_LOOP(draw_sprite256) movzbl (%esi), %ebx /* read a pixel */ orb %bl, %bl /* test */ jz draw_256_sprite_skip movl (%edi, %ebx, 4), %ebx /* lookup in palette table */ movl %ebx, %es:(%eax) /* write */ draw_256_sprite_skip: incl %esi addl $4, %eax SPRITE_END_X(draw_sprite256) SPRITE_END_Y(draw_sprite256) _align_ sprite256_done: END_SPRITE_DRAW() ret /* end of _linear_draw_256_sprite32() */ /* void _linear_draw_sprite_v_flip32(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping vertically. */ FUNC(_linear_draw_sprite_v_flip32) START_SPRITE_DRAW(sprite_v_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax addl S_W, %eax /* + w */ shll $2, %eax negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X shll $2, S_LGAP negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(v_flip) movl (%esi), %ebx /* read pixel */ cmpl $MASK_COLOR_32, %ebx /* test */ je sprite_v_flip_skip movl %ebx, %es:(%eax) /* write */ sprite_v_flip_skip: addl $4, %esi addl $4, %eax SPRITE_END_X(v_flip) SPRITE_END_Y(v_flip) sprite_v_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_v_flip32() */ /* void _linear_draw_sprite_h_flip32(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping horizontally. */ FUNC(_linear_draw_sprite_h_flip32) START_SPRITE_DRAW(sprite_h_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax addl S_W, %eax /* + w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X shll $2, S_LGAP movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi leal (%esi, %ecx, 4), %esi subl S_LGAP, %esi subl $4, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(h_flip) movl (%esi), %ebx /* read pixel */ cmpl $MASK_COLOR_32, %ebx /* test */ je sprite_h_flip_skip movl %ebx, %es:(%eax) /* write */ sprite_h_flip_skip: subl $4, %esi addl $4, %eax SPRITE_END_X(h_flip) SPRITE_END_Y(h_flip) sprite_h_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_h_flip32() */ /* void _linear_draw_sprite_vh_flip32(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping both vertically and horizontally. */ FUNC(_linear_draw_sprite_vh_flip32) START_SPRITE_DRAW(sprite_vh_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X shll $2, S_LGAP negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi leal (%esi, %ecx, 4), %esi subl S_LGAP, %esi subl $4, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(vh_flip) movl (%esi), %ebx /* read pixel */ cmpl $MASK_COLOR_32, %ebx /* test */ je sprite_vh_flip_skip movl %ebx, %es:(%eax) /* write */ sprite_vh_flip_skip: subl $4, %esi addl $4, %eax SPRITE_END_X(vh_flip) SPRITE_END_Y(vh_flip) sprite_vh_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_vh_flip32() */ /* void _linear_draw_trans_sprite32(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a translucent sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_sprite32) START_SPRITE_DRAW(trans_sprite) movl BMP_VTABLE(%esi), %eax /* check the color depth */ cmpl $8, VTABLE_COLOR_DEPTH(%eax) je trans_sprite_256 movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans, %edi) movl (%esi), %eax /* read source pixel */ cmpl $MASK_COLOR_32, %eax jz trans_sprite_skip pushl GLOBL(_blender_alpha) pushl %es:(%ebx, %edi) /* read memory pixel */ pushl %eax call *GLOBL(_blender_func32) /* blend */ addl $12, %esp movl %eax, %es:(%ebx) /* write the result */ trans_sprite_skip: addl $4, %ebx addl $4, %esi T_SPRITE_END_X(trans) /* no cleanup at end of line */ SPRITE_END_Y(trans) trans_sprite_done: END_SPRITE_DRAW() ret /* special version for drawing 8 bit alpha channels onto 32 bit RGBA */ _align_ trans_sprite_256: movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ TT_SPRITE_LOOP(trans_256, %edi) movzbl (%esi), %eax /* read source pixel */ orl %eax, %eax jz trans_sprite_256_skip pushl GLOBL(_blender_alpha) pushl %es:(%ebx, %edi) /* read memory pixel */ pushl %eax call *GLOBL(_blender_func32) /* blend */ addl $12, %esp movl %eax, %es:(%ebx) /* write the result */ trans_sprite_256_skip: addl $4, %ebx incl %esi T_SPRITE_END_X(trans_256) /* no cleanup at end of line */ SPRITE_END_Y(trans_256) END_SPRITE_DRAW() ret /* end of _linear_draw_trans_sprite32() */ /* void _linear_draw_lit_sprite32(BITMAP *bmp, BITMAP *sprite, int x, y, color); * Draws a lit sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_sprite32) #define ALPHA ARG5 START_SPRITE_DRAW(lit_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ shrl $2, %eax subl S_W, %eax /* - w */ shll $2, %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X shll $2, S_LGAP movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl ALPHA, %edi _align_ LT_SPRITE_LOOP(lit_sprite) movl (%esi), %eax /* read pixel */ cmpl $MASK_COLOR_32, %eax jz lit_sprite_skip pushl %edi pushl %eax pushl GLOBL(_blender_col_32) call *GLOBL(_blender_func32) /* blend */ addl $12, %esp movl %eax, %es:(%ebx) /* write pixel */ lit_sprite_skip: addl $4, %esi addl $4, %ebx T_SPRITE_END_X(lit_sprite) SPRITE_END_Y(lit_sprite) lit_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_lit_sprite32() */ /* void _linear_draw_character32(BITMAP *bmp, BITMAP *sprite, int x, y, color, bg); * For proportional font output onto a linear bitmap: uses the sprite as * a mask, replacing all set pixels with the specified color. */ FUNC(_linear_draw_character32) #define COLOR ARG5 #define BG ARG6 START_SPRITE_DRAW(draw_char) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ shll $2, S_X movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movl COLOR, %ebx /* bx = text color */ movl BG, %edi /* di = background color */ cmpl $0, %edi jl draw_masked_char /* opaque (bg >= 0) character output */ _align_ SPRITE_LOOP(draw_opaque_char) cmpb $0, (%esi) /* test pixel */ jz draw_opaque_background movl %ebx, %es:(%eax) /* write pixel */ jmp draw_opaque_done draw_opaque_background: movl %edi, %es:(%eax) /* write background */ draw_opaque_done: incl %esi addl $4, %eax SPRITE_END_X(draw_opaque_char) SPRITE_END_Y(draw_opaque_char) jmp draw_char_done /* masked (bg -1) character output */ _align_ draw_masked_char: SPRITE_LOOP(draw_masked_char) cmpb $0, (%esi) /* test pixel */ jz draw_masked_skip movl %ebx, %es:(%eax) /* write pixel */ draw_masked_skip: incl %esi addl $4, %eax SPRITE_END_X(draw_masked_char) SPRITE_END_Y(draw_masked_char) draw_char_done: END_SPRITE_DRAW() ret /* end of _linear_draw_character32() */ /* void _linear_draw_rle_sprite32(BITMAP *bmp, RLE_SPRITE *sprite, int x, y) * Draws an RLE sprite onto a linear bitmap at the specified position. */ FUNC(_linear_draw_rle_sprite32) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 4), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ rep ; movsl /* no special initialisation required */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ rep ; movsl /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ cmpl $MASK_COLOR_32, %eax ; \ je done ; \ testl %eax, %eax ; \ js skip /* adds the offset in %eax onto the destination address */ #define ADD_EAX_EDI() \ leal (%edi, %eax, 4), %edi /* no zero or sign extend required */ #define RLE_ZEX_EAX() #define RLE_SEX_EAX() /* this can be a simple copy... */ #define RLE_ZEX_ECX() \ movl %eax, %ecx /* do it! */ DO_RLE(rle, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_trans_rle_sprite32(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rle_sprite32) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl R_X, %edi ; \ leal (%eax, %edi, 4), %edi ; \ subl %eax, R_TMP /* calculate read/write diff */ /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_clipped_run_loop##n: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func32) /* blend */ ; \ addl $12, %esp ; \ movl %eax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $4, %edi ; \ decl R_TMP2 ; \ jg trans_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP2 ; \ ; \ trans_rle_run_loop: ; \ movl R_TMP, %edx ; \ pushl GLOBL(_blender_alpha) ; \ pushl %es:(%edi, %edx) /* read memory pixel */ ; \ pushl (%esi) /* read sprite pixel */ ; \ call *GLOBL(_blender_func32) /* blend */ ; \ addl $12, %esp ; \ movl %eax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $4, %edi ; \ decl R_TMP2 ; \ jg trans_rle_run_loop /* do it! */ DO_RLE(rle_trans, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_lit_rle_sprite32(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y, int color) * Draws a tinted RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_rle_sprite32) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl R_X, %edi ; \ leal (%eax, %edi, 4), %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl R_COLOR, %ebx ; \ movl %ecx, R_TMP ; \ ; \ lit_rle_clipped_run_loop##n: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_32) ; \ call *GLOBL(_blender_func32) /* blend */ ; \ addl $12, %esp ; \ movl %eax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $4, %edi ; \ decl R_TMP ; \ jg lit_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ movl R_COLOR, %ebx /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ movl %ecx, R_TMP ; \ ; \ lit_rle_run_loop: ; \ pushl %ebx ; \ pushl (%esi) /* read sprite pixel */ ; \ pushl GLOBL(_blender_col_32) ; \ call *GLOBL(_blender_func32) /* blend */ ; \ addl $12, %esp ; \ movl %eax, %es:(%edi) /* write the pixel */ ; \ addl $4, %esi ; \ addl $4, %edi ; \ decl R_TMP ; \ jg lit_rle_run_loop /* do it! */ DO_RLE(rle_lit, 4, l, %eax, $MASK_COLOR_32) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #endif /* ifdef ALLEGRO_COLOR32 */ allegro-4.4.3.1/src/i386/ispr8.s0000664000175000017500000015037113437077643015020 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color sprite drawing (written for speed, not readability :-) * * By Shawn Hargreaves. * * draw_sprite() and draw_trans_sprite() optimised by Erik Sandberg. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "sprite.inc" #ifdef ALLEGRO_COLOR8 .text /* void _linear_draw_sprite8(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite onto a linear bitmap at the specified x, y position, * using a masked drawing mode where zero pixels are not output. */ FUNC(_linear_draw_sprite8) /* loop for sprites more than 7 pixels wide */ /* dest: destination seg. */ /* name: the start of the label names */ /* init_edi: code to init edi every line */ #define LINEAR_SPRITE_LOOP(dest, name, init_edi) \ movl S_Y, %eax /* load line */ ; \ movl S_W, %edx /* convert x loop counter */ ; \ addl %edx, S_SGAP /* increase sprite gap */ ; \ subl $4, %edx /* less iterations */ ; \ addl %eax, S_H /* S_H = end y */ ; \ addl %edx, %esi /* end of src line in esi */ ; \ movl S_X, %edi /* edi = left edge of dest */ ; \ addl %edx, %edi /* add width to left edge */ ; \ movl %edi, S_X /* store right edge */ ; \ negl %edx /* counter/offset negative */ ; \ movl %edx, S_W /* store converted counter */ ; \ ; \ sprite_y_loop_##name: ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ pushl %ebp ; \ movl S_W, %ebp /* x loop counter */ ; \ init_edi ; \ leal (%esi, %ebp), %eax /* check unaligned bytes */ ; \ testb $1, %al ; \ jz sprite_##name##_before_waligned ; \ movb (%esi, %ebp), %bl /* write unaligned byte */ ; \ incl %ebp ; \ testb %bl, %bl ; \ jz sprite_##name##_before_waligned ; \ movb %bl, dest -1(%edi, %ebp) ; \ sprite_##name##_before_waligned: ; \ incb %al ; \ testb $2, %al ; \ jz sprite_##name##_before_laligned ; \ movw (%esi, %ebp), %bx /* write unaligned word */ ; \ addl $2, %ebp ; \ testb %bl, %bl ; \ jz sprite_##name##_before_lalign_skip_0 ; \ movb %bl, dest -2(%edi, %ebp) ; \ sprite_##name##_before_lalign_skip_0: ; \ testb %bh, %bh ; \ jz sprite_##name##_before_laligned ; \ movb %bh, dest -1(%edi, %ebp) ; \ sprite_##name##_before_laligned: /* now src is long-aligned */ ; \ ; \ sprite_x_loop_##name##_begin: /* write longs */ ; \ movl (%esi, %ebp), %eax ; \ testl %eax, %eax ; \ jz sprite_x_loop_##name##_skip_all /* skip empty long */ ; \ leal -0x01010101(%eax), %ebx ; \ xorl %eax, %ebx ; \ andl $0x80808080, %ebx ; \ jnz sprite_x_loop_##name##_not_full ; \ ; \ sprite_x_loop_##name##_full: /* write long */ ; \ movl %eax, dest (%edi, %ebp) ; \ ; \ addl $4, %ebp /* move to next long */ ; \ jle sprite_x_loop_##name##_begin ; \ jmp sprite_x_loop_##name##_end ; \ ; \ sprite_x_loop_##name##_not_full: ; \ testb %al, %al ; \ jz sprite_x_loop_##name##_skip_0 /* skip byte #0 */ ; \ movb %al, dest (%edi, %ebp) /* write byte #0 */ ; \ ; \ sprite_x_loop_##name##_skip_0: ; \ testb %ah, %ah ; \ jz sprite_x_loop_##name##_skip_1 /* skip byte #1 */ ; \ movb %ah, dest 1(%edi, %ebp) /* write byte #1 */ ; \ ; \ sprite_x_loop_##name##_skip_1: ; \ shrl $16, %eax ; \ testb %al, %al ; \ jz sprite_x_loop_##name##_skip_2 /* skip byte #2 */ ; \ movb %al, dest 2(%edi, %ebp) /* write byte #2 */ ; \ ; \ sprite_x_loop_##name##_skip_2: ; \ testb %ah, %ah ; \ jz sprite_x_loop_##name##_skip_3 /* skip byte #3 */ ; \ movb %ah, dest 3(%edi, %ebp) /* write byte #3 */ ; \ ; \ sprite_x_loop_##name##_skip_3: ; \ sprite_x_loop_##name##_skip_all: ; \ addl $4, %ebp /* move to next long */ ; \ jle sprite_x_loop_##name##_begin ; \ ; \ sprite_x_loop_##name##_end: /* write leftover data */ ; \ movl %ebp, %eax ; \ testb $1, %al /* test for leftover byte */ ; \ jz sprite_##name##_after_waligned ; \ movb (%esi, %ebp), %bl ; \ incl %ebp ; \ testb %bl, %bl ; \ jz sprite_##name##_after_waligned ; \ movb %bl, dest -1(%edi, %ebp) /* write leftover byte */ ; \ ; \ sprite_##name##_after_waligned: ; \ incb %al ; \ testb $2, %al /* test for leftover word */ ; \ jz sprite_##name##_after_laligned ; \ movw (%esi, %ebp), %bx ; \ testb %bl, %bl ; \ jz sprite_##name##_after_lalign_skip_0 /* skip byte #0 */ ; \ movb %bl, dest (%edi, %ebp) /* write byte #0 */ ; \ ; \ sprite_##name##_after_lalign_skip_0: ; \ testb %bh, %bh ; \ jz sprite_##name##_after_lalign_skip_1 /* skip byte #1 */ ; \ movb %bh, dest 1(%edi, %ebp) /* write byte #1 */ ; \ ; \ sprite_##name##_after_lalign_skip_1: ; \ sprite_##name##_after_laligned: ; \ popl %ebp /* need stack variables */ ; \ movl S_Y, %eax /* y counter */ ; \ incl %eax ; \ movl S_X, %edi /* reload dest x position */ ; \ movl %eax, S_Y /* store counter */ ; \ addl S_SGAP, %esi /* skip sprite bytes */ ; \ cmpl S_H, %eax /* check if complete */ ; \ jl sprite_y_loop_##name /* draws a tiny sprite (width < 8) onto a video or memory bitmap */ #define LOOP_TINY \ movl S_Y, %eax /* load line */ ; \ movl S_W, %edx /* convert x loop counter */ ; \ addl %edx, S_SGAP /* increase sprite gap */ ; \ addl %eax, S_H /* S_H = end y */ ; \ addl %edx, %esi /* end of src line in esi */ ; \ movl S_X, %edi /* edi = left edge of dest */ ; \ addl %edx, %edi /* add width to left edge */ ; \ decl %edi ; \ movl %edi, S_X /* store right edge */ ; \ negl %edx /* counter/offset negative */ ; \ movl %edx, S_W /* store converted counter */ ; \ sprite_y_loop_tiny: ; \ movl S_BMP, %edx ; \ movl S_Y, %eax /* load line */ ; \ WRITE_BANK() /* select bank */ ; \ addl S_X, %eax /* add x offset */ ; \ movl S_W, %ecx /* x loop counter */ ; \ movb (%esi, %ecx), %bl ; \ jmp sprite_tiny_next_pixel ; \ sprite_tiny_write_pixel: ; \ movb %bl, %es:(%eax, %ecx) ; \ movb (%esi, %ecx), %bl ; \ jz sprite_tiny_line_complete ; \ sprite_tiny_next_pixel: ; \ cmpb $1, %bl ; \ incl %ecx ; \ jnc sprite_tiny_write_pixel ; \ movb (%esi, %ecx), %bl ; \ jnz sprite_tiny_next_pixel ; \ sprite_tiny_line_complete: ; \ movl S_Y, %eax /* y counter */ ; \ addl S_SGAP, %esi /* skip sprite bytes */ ; \ incl %eax ; \ movl %eax, S_Y /* store counter */ ; \ cmpl S_H, %eax /* check if complete */ ; \ jl sprite_y_loop_tiny /* the actual sprite drawing routine */ START_SPRITE_DRAW(sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ cmpl $8, S_W jl sprite_tiny /* sprite width < 8, tiny */ movl S_BMP, %eax /* check if dest is video memory */ testl $(BMP_ID_VIDEO | BMP_ID_SYSTEM), BMP_ID(%eax) jnz sprite_video /* dest = memory bitmap */ #define INIT_EDI_CODE \ addl BMP_LINE(%edx, %eax, 4), %edi LINEAR_SPRITE_LOOP(/**/ , mem, INIT_EDI_CODE) #undef INIT_EDI_CODE jmp sprite_done sprite_video: /* dest = video memory bitmap */ #define INIT_EDI_CODE \ WRITE_BANK(); \ addl %eax, %edi LINEAR_SPRITE_LOOP(%es: , video, INIT_EDI_CODE) #undef INIT_EDI_CODE jmp sprite_done sprite_tiny: LOOP_TINY _align_ sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite8() */ FUNC(_linear_draw_sprite8_end) ret /* void _linear_draw_sprite_v_flip8(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping vertically. */ FUNC(_linear_draw_sprite_v_flip8) START_SPRITE_DRAW(sprite_v_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ addl S_W, %eax /* + w */ negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(v_flip) movb (%esi), %bl /* read pixel */ testb %bl, %bl /* test */ jz sprite_v_flip_skip movb %bl, %es:(%eax) /* write */ sprite_v_flip_skip: incl %esi incl %eax SPRITE_END_X(v_flip) SPRITE_END_Y(v_flip) sprite_v_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_v_flip8() */ /* void _linear_draw_sprite_h_flip8(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping horizontally. */ FUNC(_linear_draw_sprite_h_flip8) START_SPRITE_DRAW(sprite_h_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ addl S_W, %eax /* + w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi addl %ecx, %esi subl S_LGAP, %esi decl %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(h_flip) movb (%esi), %bl /* read pixel */ testb %bl, %bl /* test */ jz sprite_h_flip_skip movb %bl, %es:(%eax) /* write */ sprite_h_flip_skip: decl %esi incl %eax SPRITE_END_X(h_flip) SPRITE_END_Y(h_flip) sprite_h_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_h_flip8() */ /* void _linear_draw_sprite_vh_flip8(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a sprite to a linear bitmap, flipping both vertically and horizontally. */ FUNC(_linear_draw_sprite_vh_flip8) START_SPRITE_DRAW(sprite_vh_flip) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ negl %eax movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ negl %eax /* - tgap */ addl BMP_H(%esi), %eax /* + sprite->h */ decl %eax movl BMP_W(%esi), %ecx movl BMP_LINE(%esi, %eax, 4), %esi addl %ecx, %esi subl S_LGAP, %esi decl %esi /* esi = sprite data ptr */ _align_ SPRITE_LOOP(vh_flip) movb (%esi), %bl /* read pixel */ testb %bl, %bl /* test */ jz sprite_vh_flip_skip movb %bl, %es:(%eax) /* write */ sprite_vh_flip_skip: decl %esi incl %eax SPRITE_END_X(vh_flip) SPRITE_END_Y(vh_flip) sprite_vh_flip_done: END_SPRITE_DRAW() ret /* end of _linear_draw_sprite_vh_flip8() */ /* void _linear_draw_trans_sprite8(BITMAP *bmp, BITMAP *sprite, int x, y); * Draws a translucent sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_sprite8) /* this loop is used when drawing onto video RAM */ #define TRANS_LOOP_VIDEO \ subl $4, S_W ; \ _align_ ; \ sprite_y_loop_trans_video: ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ movl S_Y, %eax /* load line */ ; \ READ_BANK() /* select read bank */ ; \ movl %eax, %ecx /* read address in ecx */ ; \ movl S_Y, %eax /* reload line */ ; \ WRITE_BANK() /* select write bank */ ; \ subl %eax, %ecx /* convert ecx to offset */ ; \ addl S_X, %eax /* add x offset */ ; \ pushl %ebp ; \ movl S_W, %ebp /* x loop counter */ ; \ testl %ebp, %ebp ; \ jle sprite_x_loop_trans_video_few_pixels ; \ _align_ ; \ sprite_x_loop_trans_video: ; \ movl %es:(%eax, %ecx), %edx /* read four pixels */ ; \ movb %dl, %bl /* lookup pixel 1 */ ; \ movb (%esi), %bh ; \ movb (%edi, %ebx), %dl ; \ movb %dh, %bl /* lookup pixel 2 */ ; \ movb 1(%esi), %bh ; \ movb (%edi, %ebx), %dh ; \ roll $16, %edx ; \ movb %dl, %bl /* lookup pixel 3 */ ; \ movb 2(%esi), %bh ; \ movb (%edi, %ebx), %dl ; \ movb %dh, %bl /* lookup pixel 4 */ ; \ movb 3(%esi), %bh ; \ movb (%edi, %ebx), %dh ; \ roll $16, %edx ; \ movl %edx, %es:(%eax) /* write four pixels */ ; \ addl $4, %eax ; \ addl $4, %esi ; \ subl $4, %ebp ; \ jg sprite_x_loop_trans_video ; \ sprite_x_loop_trans_video_few_pixels: ; \ addl $4, %ebp ; \ _align_ ; \ sprite_x_loop_trans_video_last_pixels: ; \ movb %es:(%eax, %ecx), %bl /* read pixel */ ; \ movb (%esi), %bh ; \ movb (%edi, %ebx), %bl /* lookup pixel */ ; \ movb %bl, %es:(%eax) /* write pixel */ ; \ incl %eax ; \ incl %esi ; \ decl %ebp ; \ jg sprite_x_loop_trans_video_last_pixels ; \ popl %ebp ; \ SPRITE_END_Y(trans_video) /* this loop is used when drawing onto memory bitmaps */ #define TRANS_LOOP_MEMORY \ movl S_Y, %ecx /* load line */ ; \ movl S_W, %edx /* convert x loop counter */ ; \ addl %edx, S_SGAP /* increase sprite gap */ ; \ addl %ecx, S_H /* S_H = end y */ ; \ movl $0, %ebx /* clear ebx */ ; \ cmpl $2, %edx /* if sprite width > 2 */ ; \ jg m_trans_sprite_not_tiny /* the sprite isn't tiny */ ; \ pushl %edx /* tiny sprite, unaligned */ ; \ jmp m_trans_sprite_aligned /* aligning complete */ ; \ _align_ ; \ m_trans_sprite_not_tiny: ; \ subl S_X, %ebx /* unaligned bytes */ ; \ andl $3, %ebx /* at start of line in bl */ ; \ movb %dl, %bh /* unaligned bytes */ ; \ subb %bl, %bh /* at end of line in bh */ ; \ andb $3, %bh ; \ pushl %ebx /* store on the stack */ ; \ m_trans_sprite_aligned: ; \ movzbl %bh, %eax /* subtract number of */ ; \ subl %eax, %edx /* leftover bytes */ ; \ subl $4, %edx /* one iteration less */ ; \ addl %edx, %esi /* end of src line in esi */ ; \ movl S_X, %eax /* eax = left edge of dest */ ; \ addl %edx, %eax /* add width to left edge */ ; \ movl %eax, S_X /* store right edge */ ; \ negl %edx /* counter/offset negative */ ; \ movl %edx, S_W /* store converted counter */ ; \ _align_ ; \ m_sprite_y_loop_trans: ; \ movl S_BMP, %edx /* load bitmap pointer */ ; \ pushl %ebp /* I need ebp as counter */ ; \ movl S_W, %ebp /* x loop counter */ ; \ addl BMP_LINE(%edx, %ecx, 4), %eax /* end of dest line in eax */ ; \ movl $0, %ecx /* clear the high word */ ; \ movl 4(%esp), %ebx /* leftover count in ebx */ ; \ cmpb $0, %bl /* check if long-aligned */ ; \ je m_trans_sprite_before_laligned /* no aligning */ ; \ cmpb $2, %bl /* check if word-aligned */ ; \ je m_trans_sprite_before_waligned /* copy one word */ ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ incl %ebp /* increment counter/index */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb %dl, -1(%eax, %ebp) /* write the pixel */ ; \ cmpb $1, %bl /* check if long-aligned */ ; \ je m_trans_sprite_before_laligned /* no more aligning */ ; \ m_trans_sprite_before_waligned: ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ movb 1(%eax, %ebp), %bl /* load dest pixel 1 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ movb 1(%esi, %ebp), %bh /* load src pixel 1 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 1 */ ; \ movw %dx, (%eax, %ebp) /* write two pixels */ ; \ addl $2, %ebp /* increment counter/index */ ; \ m_trans_sprite_before_laligned: /* src is long-aligned */ ; \ testl %ebp, %ebp /* check number of longs */ ; \ jg m_sprite_x_loop_trans_few /* no aligned long in src */ ; \ movb 2(%eax, %ebp), %cl /* load dest pixel 2 */ ; \ jz m_sprite_x_loop_trans_1long /* one aligned long in src */ ; \ movb 3(%esi, %ebp), %bh /* load src pixel 3 */ ; \ movb 2(%esi, %ebp), %ch /* load src pixel 2 */ ; \ movb 3(%eax, %ebp), %bl /* load dest pixel 3 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 2 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 3 */ ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ shll $16, %edx ; \ movb 1(%eax, %ebp), %bl /* load dest pixel 1 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb 1(%esi, %ebp), %bh /* load src pixel 1 */ ; \ movb 6(%eax, %ebp), %cl /* load next loop pixel 2 */ ; \ addl $4, %ebp /* increment counter/index */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 1 */ ; \ jz m_sprite_x_loop_trans_2longs /* 2 aligned longs in src */ ; \ _align_ ; \ sprite_x_loop_trans_m: ; \ movb 2(%esi, %ebp), %ch /* load src pixel 2 */ ; \ movb 3(%eax, %ebp), %bl /* load dest pixel 2 */ ; \ movb 3(%esi, %ebp), %bh /* load src pixel 3 */ ; \ movl %edx, -4(%eax, %ebp) /* write prev. pixels */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 2 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 3 */ ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ shll $16, %edx /* high word done; shift */ ; \ movb 1(%eax, %ebp), %bl /* load dest pixel 1 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb 1(%esi, %ebp), %bh /* load src pixel 1 */ ; \ movb 6(%eax, %ebp), %cl /* load next loop pixel 2 */ ; \ addl $4, %ebp /* increment counter/index */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 1 */ ; \ jl sprite_x_loop_trans_m ; \ m_sprite_x_loop_trans_2longs: ; \ movl %edx, -4(%eax, %ebp) /* write last pixels */ ; \ m_sprite_x_loop_trans_1long: ; \ movb 3(%esi, %ebp), %bh /* load src pixel 3 */ ; \ movb 2(%esi, %ebp), %ch /* load src pixel 2 */ ; \ movb 3(%eax, %ebp), %bl /* load dest pixel 3 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 2 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 3 */ ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ shll $16, %edx ; \ movb 1(%eax, %ebp), %bl /* load dest pixel 1 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb 1(%esi, %ebp), %bh /* load src pixel 1 */ ; \ addl $4, %ebp /* increment counter/index */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 1 */ ; \ movl %edx, -4(%eax, %ebp) /* write four pixels */ ; \ m_sprite_x_loop_trans_few: ; \ movl 4(%esp), %ebx /* leftover count in ebx */ ; \ cmpb $0, %bh /* any leftover bytes? */ ; \ je m_trans_sprite_line_complete /* no leftovers */ ; \ cmpb $1, %bh /* any leftover word? */ ; \ je m_trans_sprite_leftover_byte /* only copy one byte */ ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ movb 1(%eax, %ebp), %bl /* load dest pixel 1 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ movb 1(%esi, %ebp), %bh /* load src pixel 1 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb (%edi, %ebx), %dh /* lookup pixel 1 */ ; \ cmpb $2, 5(%esp) /* check if complete */ ; \ movw %dx, (%eax, %ebp) /* write two pixels */ ; \ leal 2(%ebp), %ebp /* increment counter/index */ ; \ je m_trans_sprite_line_complete /* don't draw any more */ ; \ m_trans_sprite_leftover_byte: /* draw the final pixel */ ; \ movb (%esi, %ebp), %ch /* load src pixel 0 */ ; \ movb (%eax, %ebp), %cl /* load dest pixel 0 */ ; \ movb (%edi, %ecx), %dl /* lookup pixel 0 */ ; \ movb %dl, (%eax, %ebp) /* write the pixel */ ; \ m_trans_sprite_line_complete: ; \ popl %ebp /* I need stack variables */ ; \ movl S_Y, %ecx /* y counter */ ; \ incl %ecx ; \ movl S_X, %eax /* reload dest x position */ ; \ movl %ecx, S_Y /* store counter */ ; \ addl S_SGAP, %esi /* esi points to next line */ ; \ cmpl S_H, %ecx /* check if complete */ ; \ jc m_sprite_y_loop_trans /* loop */ ; \ popl %ebx /* pop unaligned counter */ /* the actual translucent sprite drawing routine */ START_SPRITE_DRAW(trans_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ xorl %ebx, %ebx movl GLOBL(color_map), %edi /* edi = color mapping table */ movl S_BMP, %eax /* check if it's video memory */ testl $(BMP_ID_VIDEO | BMP_ID_SYSTEM), BMP_ID(%eax) jnz trans_sprite_video TRANS_LOOP_MEMORY jmp trans_sprite_done trans_sprite_video: TRANS_LOOP_VIDEO _align_ trans_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_trans_sprite8() */ /* void _linear_draw_lit_sprite8(BITMAP *bmp, BITMAP *sprite, int x, y, color); * Draws a lit sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_sprite8) #define COLOR ARG5 START_SPRITE_DRAW(lit_sprite) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ xorl %ebx, %ebx movb COLOR, %bh /* store color in high byte */ movl GLOBL(color_map), %edi /* edi = color mapping table */ _align_ SPRITE_LOOP(lit_sprite) movb (%esi), %bl /* read pixel into low byte */ orb %bl, %bl jz lit_sprite_skip movb (%edi, %ebx), %bl /* color table lookup */ movb %bl, %es:(%eax) /* write pixel */ lit_sprite_skip: incl %esi incl %eax SPRITE_END_X(lit_sprite) SPRITE_END_Y(lit_sprite) lit_sprite_done: END_SPRITE_DRAW() ret /* end of _linear_draw_lit_sprite8() */ /* void _linear_draw_character8(BITMAP *bmp, BITMAP *sprite, int x, y, color, bg); * For proportional font output onto a linear bitmap: uses the sprite as * a mask, replacing all set pixels with the specified color. */ FUNC(_linear_draw_character8) #undef COLOR #define COLOR ARG5 #define BG ARG6 START_SPRITE_DRAW(draw_char) movl BMP_LINE+4(%esi), %eax subl BMP_LINE(%esi), %eax /* eax = sprite data pitch */ subl S_W, %eax /* - w */ movl %eax, S_SGAP /* store sprite gap */ movl S_LGAP, %eax addl %eax, S_X /* X += lgap */ movl S_TGAP, %eax addl %eax, S_Y /* Y += tgap */ movl BMP_LINE(%esi, %eax, 4), %esi addl S_LGAP, %esi /* esi = sprite data ptr */ movb COLOR, %bl /* bl = text color */ movb BG, %bh /* bh = background color */ cmpl $0, BG jl draw_masked_char /* opaque (bg >= 0) character output */ _align_ SPRITE_LOOP(draw_opaque_char) cmpb $0, (%esi) /* test pixel */ jz draw_opaque_background movb %bl, %es:(%eax) /* write pixel */ jmp draw_opaque_done draw_opaque_background: movb %bh, %es:(%eax) /* write background */ draw_opaque_done: incl %esi incl %eax SPRITE_END_X(draw_opaque_char) SPRITE_END_Y(draw_opaque_char) jmp draw_char_done /* masked (bg -1) character output */ _align_ draw_masked_char: SPRITE_LOOP(draw_masked_char) cmpb $0, (%esi) /* test pixel */ jz draw_masked_skip movb %bl, %es:(%eax) /* write pixel */ draw_masked_skip: incl %esi incl %eax SPRITE_END_X(draw_masked_char) SPRITE_END_Y(draw_masked_char) draw_char_done: END_SPRITE_DRAW() ret /* end of _linear_draw_character8() */ /* void _linear_draw_rle_sprite8(BITMAP *bmp, RLE_SPRITE *sprite, int x, int y) * Draws an RLE sprite onto a linear bitmap at the specified position. */ FUNC(_linear_draw_rle_sprite8) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl %eax, %edi ; \ addl R_X, %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ rep ; movsb /* no special initialisation required */ #define INIT_FAST_RLE_LOOP() /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ shrl $1, %ecx ; \ jnc rle_noclip_no_byte ; \ movsb /* copy odd byte? */ ; \ rle_noclip_no_byte: ; \ jz rle_noclip_x_loop ; \ shrl $1, %ecx ; \ jnc rle_noclip_no_word ; \ movsw /* copy odd word? */ ; \ rle_noclip_no_word: ; \ jz rle_noclip_x_loop ; \ rep ; movsl /* 32 bit string copy */ /* tests an RLE command byte */ #define TEST_RLE_COMMAND(done, skip) \ testb %al, %al ; \ jz done ; \ js skip /* adds the offset in %eax onto the destination address */ #define ADD_EAX_EDI() \ addl %eax, %edi /* zero extend %al into %eax */ #define RLE_ZEX_EAX() \ movzbl %al, %eax /* zero extend %al into %ecx */ #define RLE_ZEX_ECX() \ movzbl %al, %ecx /* sign extend %al into %eax */ #define RLE_SEX_EAX() \ movsbl %al, %eax /* do it! */ DO_RLE(rle, 1, b, %al, $0) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_trans_rle_sprite8(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y) * Draws a translucent RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_trans_rle_sprite8) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ READ_BANK() /* select read bank */ ; \ movl %eax, R_TMP ; \ movl R_Y, %eax ; \ WRITE_BANK() /* select write bank */ ; \ movl %eax, %edi ; \ movl R_TMP, %edx /* calculate read/write diff */ ; \ subl %edi, %edx ; \ addl R_X, %edi /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ pushl %ebx ; \ movl GLOBL(color_map), %ebx ; \ xorl %eax, %eax ; \ ; \ trans_rle_clipped_run_loop##n: ; \ movb (%esi), %ah /* read sprite pixel */ ; \ movb %es:(%edi, %edx), %al /* read destination pixel */ ; \ movb (%ebx, %eax), %al /* blend */ ; \ movb %al, %es:(%edi) /* write the pixel */ ; \ incl %esi ; \ incl %edi ; \ decl %ecx ; \ jg trans_rle_clipped_run_loop##n ; \ ; \ popl %ebx /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ movl GLOBL(color_map), %ebx /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ xorl %eax, %eax ; \ ; \ shrl $1, %ecx ; \ jnc trans_rle_run_no_byte ; \ ; \ movb (%esi), %ah /* read sprite pixel */ ; \ movb %es:(%edi, %edx), %al /* read destination pixel */ ; \ movb (%ebx, %eax), %al /* blend */ ; \ movb %al, %es:(%edi) /* write the pixel */ ; \ incl %esi ; \ incl %edi ; \ ; \ trans_rle_run_no_byte: ; \ orl %ecx, %ecx ; \ jz trans_rle_run_done ; \ ; \ shrl $1, %ecx ; \ jnc trans_rle_run_no_word ; \ ; \ pushl %ecx ; \ xorl %ecx, %ecx ; \ movw (%esi), %ax /* read two sprite pixels */ ; \ movw %ax, R_TMP ; \ movw %es:(%edi, %edx), %ax /* read two destination pixels */ ; \ movb %al, %cl ; \ movb R_TMP, %ch ; \ movb (%ebx, %ecx), %al /* blend pixel 1 */ ; \ movb %ah, %cl ; \ movb 1+R_TMP, %ch ; \ movb (%ebx, %ecx), %ah /* blend pixel 2 */ ; \ movw %ax, %es:(%edi) /* write two pixels */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ popl %ecx ; \ ; \ trans_rle_run_no_word: ; \ orl %ecx, %ecx ; \ jz trans_rle_run_done ; \ ; \ movl %ecx, R_TMP2 ; \ xorl %ecx, %ecx ; \ ; \ trans_rle_run_loop: ; \ movl (%esi), %eax /* read four sprite pixels */ ; \ movl %eax, R_TMP ; \ movl %es:(%edi, %edx), %eax /* read four destination pixels */ ; \ movb %al, %cl ; \ movb R_TMP, %ch ; \ movb (%ebx, %ecx), %al /* blend pixel 1 */ ; \ movb %ah, %cl ; \ movb 1+R_TMP, %ch ; \ movb (%ebx, %ecx), %ah /* blend pixel 2 */ ; \ roll $16, %eax ; \ movb %al, %cl ; \ movb 2+R_TMP, %ch ; \ movb (%ebx, %ecx), %al /* blend pixel 3 */ ; \ movb %ah, %cl ; \ movb 3+R_TMP, %ch ; \ movb (%ebx, %ecx), %ah /* blend pixel 4 */ ; \ roll $16, %eax ; \ movl %eax, %es:(%edi) /* write four pixels */ ; \ addl $4, %esi ; \ addl $4, %edi ; \ decl R_TMP2 ; \ jg trans_rle_run_loop ; \ ; \ trans_rle_run_done: /* do it! */ DO_RLE(rle_trans, 1, b, %al, $0) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN /* void _linear_draw_lit_rle_sprite8(BITMAP *bmp, RLE_SPRITE *sprite, * int x, int y, int color) * Draws a tinted RLE sprite onto a linear bitmap. */ FUNC(_linear_draw_lit_rle_sprite8) /* bank switch routine */ #define INIT_RLE_LINE() \ movl R_BMP, %edx ; \ movl R_Y, %eax ; \ WRITE_BANK() ; \ movl %eax, %edi ; \ addl R_X, %edi ; \ movl GLOBL(color_map), %edx /* copy a clipped pixel run */ #define SLOW_RLE_RUN(n) \ xorl %eax, %eax ; \ movb R_COLOR, %ah /* store color in high byte */ ; \ ; \ lit_rle_clipped_run_loop##n: ; \ movb (%esi), %al /* read a pixel */ ; \ movb (%edx, %eax), %al /* lookup in color table */ ; \ movb %al, %es:(%edi) /* write the pixel */ ; \ incl %esi ; \ incl %edi ; \ decl %ecx ; \ jg lit_rle_clipped_run_loop##n /* initialise the drawing loop */ #define INIT_FAST_RLE_LOOP() \ xorl %ebx, %ebx ; \ movb R_COLOR, %bh /* store color in high byte */ /* copy a run of solid pixels */ #define FAST_RLE_RUN() \ shrl $1, %ecx ; \ jnc lit_rle_run_no_byte ; \ ; \ movb (%esi), %bl /* read pixel into low byte */ ; \ movb (%edx, %ebx), %bl /* lookup in lighting table */ ; \ movb %bl, %es:(%edi) /* write the pixel */ ; \ incl %esi ; \ incl %edi ; \ ; \ lit_rle_run_no_byte: ; \ orl %ecx, %ecx ; \ jz lit_rle_run_done ; \ ; \ shrl $1, %ecx ; \ jnc lit_rle_run_no_word ; \ ; \ movw (%esi), %ax /* read two pixels */ ; \ movb %al, %bl ; \ movb (%edx, %ebx), %al /* lookup pixel 1 */ ; \ movb %ah, %bl ; \ movb (%edx, %ebx), %ah /* lookup pixel 2 */ ; \ movw %ax, %es:(%edi) /* write two pixels */ ; \ addl $2, %esi ; \ addl $2, %edi ; \ ; \ lit_rle_run_no_word: ; \ orl %ecx, %ecx ; \ jz lit_rle_run_done ; \ ; \ lit_rle_run_loop: ; \ movl (%esi), %eax /* read four pixels */ ; \ movb %al, %bl ; \ movb (%edx, %ebx), %al /* lookup pixel 1 */ ; \ movb %ah, %bl ; \ movb (%edx, %ebx), %ah /* lookup pixel 2 */ ; \ roll $16, %eax ; \ movb %al, %bl ; \ movb (%edx, %ebx), %al /* lookup pixel 3 */ ; \ movb %ah, %bl ; \ movb (%edx, %ebx), %ah /* lookup pixel 4 */ ; \ roll $16, %eax ; \ movl %eax, %es:(%edi) /* write four pixels */ ; \ addl $4, %esi ; \ addl $4, %edi ; \ decl %ecx ; \ jg lit_rle_run_loop ; \ ; \ lit_rle_run_done: /* do it! */ DO_RLE(rle_lit, 1, b, %al, $0) ret #undef INIT_RLE_LINE #undef SLOW_RLE_RUN #undef INIT_FAST_RLE_LOOP #undef FAST_RLE_RUN #endif /* ifdef ALLEGRO_COLOR8 */ allegro-4.4.3.1/src/i386/asmdef.c0000664000175000017500000002303113437077643015162 0ustar siegesiege/* * This a little on the complex side, but I couldn't think of any * other way to do it. I was getting fed up with having to rewrite * my asm code every time I altered the layout of a C struct, but I * couldn't figure out any way to get the asm stuff to read and * understand the C headers. So I made this program. It includes * allegro.h so it knows about everything the C code uses, and when * run it spews out a bunch of #defines containing information about * structure sizes which the asm code can refer to. */ #define ALLEGRO_NO_MAGIC_MAIN #define ALLEGRO_USE_CONSOLE /* to avoid linking errors with compilers that don't properly * support the 'static inline' keyword (Watcom) */ #define ALLEGRO_NO_CLEAR_BITMAP_ALIAS #define ALLEGRO_NO_FIX_ALIASES #define ALLEGRO_NO_VHLINE_ALIAS #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_DOS #include "allegro/platform/aintdos.h" #endif #ifdef ALLEGRO_ASMCAPA_HEADER #include ALLEGRO_ASMCAPA_HEADER #endif typedef struct { char *name; int value; }offset_entry_t; offset_entry_t list[] = { #ifdef ALLEGRO_DJGPP {"##ALLEGRO_DJGPP", 0}, #endif #ifdef ALLEGRO_WATCOM {"##ALLEGRO_WATCOM", 0}, #endif #ifdef ALLEGRO_DOS {"##ALLEGRO_DOS", 0}, #endif #ifdef ALLEGRO_WINDOWS {"##ALLEGRO_WINDOWS", 0}, #endif #ifdef ALLEGRO_LINUX {"##ALLEGRO_LINUX", 0}, #endif #ifdef ALLEGRO_LINUX_VGA {"##ALLEGRO_LINUX_VGA", 0}, #endif #ifdef ALLEGRO_LINUX_VBEAF {"##ALLEGRO_LINUX_VBEAF", 0}, #endif #ifdef ALLEGRO_WITH_MODULES {"##ALLEGRO_WITH_MODULES", 0}, #endif #ifdef ALLEGRO_COLOR8 {"##ALLEGRO_COLOR8", 0}, #endif #ifdef ALLEGRO_COLOR16 {"##ALLEGRO_COLOR16", 0}, #endif #ifdef ALLEGRO_COLOR24 {"##ALLEGRO_COLOR24", 0}, #endif #ifdef ALLEGRO_COLOR32 {"##ALLEGRO_COLOR32", 0}, #endif #ifdef ALLEGRO_MMX {"##ALLEGRO_MMX", 0}, #endif #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH {"##ALLEGRO_COLORCONV_ALIGNED_WIDTH", 0}, #endif #ifdef ALLEGRO_NO_COLORCOPY {"##ALLEGRO_NO_COLORCOPY", 0}, #endif #ifdef ALLEGRO_NO_ASM {"##ALLEGRO_NO_ASM", 0}, #endif {"BMP_W", (int)offsetof(BITMAP, w)}, {"BMP_H", (int)offsetof(BITMAP, h)}, {"BMP_CLIP", (int)offsetof(BITMAP, clip)}, {"BMP_CL", (int)offsetof(BITMAP, cl)}, {"BMP_CR", (int)offsetof(BITMAP, cr)}, {"BMP_CT", (int)offsetof(BITMAP, ct)}, {"BMP_CB", (int)offsetof(BITMAP, cb)}, {"BMP_VTABLE", (int)offsetof(BITMAP, vtable)}, {"BMP_WBANK", (int)offsetof(BITMAP, write_bank)}, {"BMP_RBANK", (int)offsetof(BITMAP, read_bank)}, {"BMP_DAT", (int)offsetof(BITMAP, dat)}, {"BMP_ID", (int)offsetof(BITMAP, id)}, {"BMP_EXTRA", (int)offsetof(BITMAP, extra)}, {"BMP_XOFFSET",(int)offsetof(BITMAP, x_ofs)}, {"BMP_YOFFSET",(int)offsetof(BITMAP, y_ofs)}, {"BMP_SEG", (int)offsetof(BITMAP, seg)}, {"BMP_LINE", (int)offsetof(BITMAP, line)}, {"NEWLINE", 0}, {"#ifndef BMP_ID_VIDEO", 0}, // next lot are 0x%08X in original {"BMP_ID_VIDEO", BMP_ID_VIDEO}, {"BMP_ID_SYSTEM", BMP_ID_SYSTEM}, {"BMP_ID_SUB", BMP_ID_SUB}, {"BMP_ID_PLANAR", BMP_ID_PLANAR}, {"BMP_ID_NOBLIT", BMP_ID_NOBLIT}, {"BMP_ID_LOCKED", BMP_ID_LOCKED}, {"BMP_ID_AUTOLOCK", BMP_ID_AUTOLOCK}, {"BMP_ID_MASK", BMP_ID_MASK}, {"#endif", 0 }, {"NEWLINE", 0}, #if !defined ALLEGRO_NO_ASM && defined ALLEGRO_I386 {"CMP_PLANAR", (int)offsetof(COMPILED_SPRITE, planar)}, {"CMP_COLOR_DEPTH", (int)offsetof(COMPILED_SPRITE, color_depth)}, {"CMP_DRAW", (int)offsetof(COMPILED_SPRITE, proc)}, {"NEWLINE", 0}, #endif {"VTABLE_COLOR_DEPTH", (int)offsetof(GFX_VTABLE, color_depth)}, {"VTABLE_MASK_COLOR", (int)offsetof(GFX_VTABLE, mask_color)}, {"VTABLE_UNBANK", (int)offsetof(GFX_VTABLE, unwrite_bank)}, {"NEWLINE", 0}, {"RLE_W", (int)offsetof(RLE_SPRITE, w)}, {"RLE_H", (int)offsetof(RLE_SPRITE, h)}, {"RLE_DAT", (int)offsetof(RLE_SPRITE, dat)}, {"NEWLINE", 0}, {"GFXRECT_WIDTH", (int)offsetof(GRAPHICS_RECT, width)}, {"GFXRECT_HEIGHT", (int)offsetof(GRAPHICS_RECT, height)}, {"GFXRECT_PITCH", (int)offsetof(GRAPHICS_RECT, pitch)}, {"GFXRECT_DATA", (int)offsetof(GRAPHICS_RECT, data)}, {"NEWLINE", 0 }, {"DRAW_SOLID", DRAW_MODE_SOLID}, {"DRAW_XOR", DRAW_MODE_XOR}, {"DRAW_COPY_PATTERN", DRAW_MODE_COPY_PATTERN}, {"DRAW_SOLID_PATTERN", DRAW_MODE_SOLID_PATTERN}, {"DRAW_MASKED_PATTERN", DRAW_MODE_MASKED_PATTERN}, {"DRAW_TRANS", DRAW_MODE_TRANS}, {"NEWLINE", 0}, {"#ifndef MASK_COLOR_8", 0}, {"MASK_COLOR_8", MASK_COLOR_8}, {"MASK_COLOR_15", MASK_COLOR_15}, {"MASK_COLOR_16", MASK_COLOR_16}, {"MASK_COLOR_24", MASK_COLOR_24}, {"MASK_COLOR_32", MASK_COLOR_32}, {"#endif", 0}, {"NEWLINE", 0}, {"POLYSEG_U", (int)offsetof(POLYGON_SEGMENT, u)}, {"POLYSEG_V", (int)offsetof(POLYGON_SEGMENT, v)}, {"POLYSEG_DU", (int)offsetof(POLYGON_SEGMENT, du)}, {"POLYSEG_DV", (int)offsetof(POLYGON_SEGMENT, dv)}, {"POLYSEG_C", (int)offsetof(POLYGON_SEGMENT, c)}, {"POLYSEG_DC", (int)offsetof(POLYGON_SEGMENT, dc)}, {"POLYSEG_R", (int)offsetof(POLYGON_SEGMENT, r)}, {"POLYSEG_G", (int)offsetof(POLYGON_SEGMENT, g)}, {"POLYSEG_B", (int)offsetof(POLYGON_SEGMENT, b)}, {"POLYSEG_DR", (int)offsetof(POLYGON_SEGMENT, dr)}, {"POLYSEG_DG", (int)offsetof(POLYGON_SEGMENT, dg)}, {"POLYSEG_DB", (int)offsetof(POLYGON_SEGMENT, db)}, {"POLYSEG_Z", (int)offsetof(POLYGON_SEGMENT, z)}, {"POLYSEG_DZ", (int)offsetof(POLYGON_SEGMENT, dz)}, {"POLYSEG_FU", (int)offsetof(POLYGON_SEGMENT, fu)}, {"POLYSEG_FV", (int)offsetof(POLYGON_SEGMENT, fv)}, {"POLYSEG_DFU", (int)offsetof(POLYGON_SEGMENT, dfu)}, {"POLYSEG_DFV", (int)offsetof(POLYGON_SEGMENT, dfv)}, {"POLYSEG_TEXTURE", (int)offsetof(POLYGON_SEGMENT, texture)}, {"POLYSEG_UMASK", (int)offsetof(POLYGON_SEGMENT, umask)}, {"POLYSEG_VMASK", (int)offsetof(POLYGON_SEGMENT, vmask)}, {"POLYSEG_VSHIFT", (int)offsetof(POLYGON_SEGMENT, vshift)}, {"POLYSEG_SEG ", (int)offsetof(POLYGON_SEGMENT, seg)}, {"POLYSEG_ZBADDR", (int)offsetof(POLYGON_SEGMENT, zbuf_addr)}, {"POLYSEG_RADDR", (int)offsetof(POLYGON_SEGMENT, read_addr)}, {"NEWLINE", 0}, {"ERANGE", ERANGE}, {"NEWLINE", 0}, {"M_V00", (int)offsetof(MATRIX_f, v[0][0])}, {"M_V01", (int)offsetof(MATRIX_f, v[0][1])}, {"M_V02", (int)offsetof(MATRIX_f, v[0][2])}, {"M_V10", (int)offsetof(MATRIX_f, v[1][0])}, {"M_V11", (int)offsetof(MATRIX_f, v[1][1])}, {"M_V12", (int)offsetof(MATRIX_f, v[1][2])}, {"M_V20", (int)offsetof(MATRIX_f, v[2][0])}, {"M_V21", (int)offsetof(MATRIX_f, v[2][1])}, {"M_V22", (int)offsetof(MATRIX_f, v[2][2])}, {"NEWLINE", 0}, {"M_T0", (int)offsetof(MATRIX_f, t[0])}, {"M_T1", (int)offsetof(MATRIX_f, t[1])}, {"M_T2", (int)offsetof(MATRIX_f, t[2])}, {"NEWLINE", 0}, #ifdef ALLEGRO_DOS {"IRQ_SIZE", (int)sizeof(_IRQ_HANDLER)}, {"IRQ_HANDLER", (int)offsetof(_IRQ_HANDLER, handler)}, {"IRQ_NUMBER", (int)offsetof(_IRQ_HANDLER, number)}, {"IRQ_OLDVEC", (int)offsetof(_IRQ_HANDLER, old_vector)}, {"NEWLINE", 0}, {"DPMI_AX", (int)offsetof(__dpmi_regs, x.ax)}, {"DPMI_BX", (int)offsetof(__dpmi_regs, x.bx)}, {"DPMI_CX", (int)offsetof(__dpmi_regs, x.cx)}, {"DPMI_DX", (int)offsetof(__dpmi_regs, x.dx)}, {"DPMI_SP", (int)offsetof(__dpmi_regs, x.sp)}, {"DPMI_SS", (int)offsetof(__dpmi_regs, x.ss)}, {"DPMI_FLAGS", (int)offsetof(__dpmi_regs, x.flags)}, {"NEWLINE", 0}, #endif #ifdef ALLEGRO_ASM_USE_FS {"#define USE_FS", 0}, {"#define FSEG %fs:", 0}, #else {"#define FSEG", 0}, #endif {"NEWLINE", 0}, {"#ifndef CPU_ID", 0}, {"CPU_ID", CPU_ID}, {"CPU_FPU", CPU_FPU}, {"CPU_MMX", CPU_MMX}, {"CPU_MMXPLUS", CPU_MMXPLUS}, {"CPU_SSE", CPU_SSE}, {"CPU_SSE2", CPU_SSE2}, {"CPU_3DNOW", CPU_3DNOW}, {"CPU_ENH3DNOW", CPU_ENH3DNOW}, {"CPU_CMOV", CPU_CMOV}, {"#endif", 0}, {"NEWLINE", 0}, #ifdef ALLEGRO_ASM_PREFIX #define PREFIX ALLEGRO_ASM_PREFIX "##" #else #define PREFIX "" #endif #ifdef ALLEGRO_WATCOM {"#define FUNC(name) .globl " PREFIX "name ; nop ; _align_ ; " PREFIX "name:", 0}, #elif defined ALLEGRO_UNIX {"#define FUNC(name) .globl " PREFIX "name ; _align_ ; .type " PREFIX "name,@function ; " PREFIX "name:", 0}, #else {"#define FUNC(name) .globl " PREFIX "name ; _align_ ; " PREFIX "name:", 0}, #endif {"#define GLOBL(name) " PREFIX "name", 0}, {"NEWLINE", 0}, {NULL, 0} }; int main(int argc, char *argv[]) { offset_entry_t *p; FILE *f; if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } printf("writing structure offsets into %s...\n", argv[1]); f = fopen(argv[1], "w"); if (f == 0) { fprintf(stderr, "%s: can not open file %s\n", argv[0], argv[1]); return 1; } fprintf(f, "/* Allegro " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR " */\n"); fprintf(f, "/* automatically generated structure offsets */\n\n"); p = list; while (p->name != NULL) { if (p->name[0] == '#') { if (p->name[1] == '#') { fprintf(f, "#ifndef %s\n#define %s\n#endif\n\n", p->name+2, p->name+2); } else fprintf(f, "%s\n", p->name); } else { fprintf(f, "#define %s %d\n", p->name, p->value); } p++; } if (ferror(f)) { fprintf(stderr, "%s: cannot write file %s\n", argv[0], argv[1]); return 1; } if (fclose(f)) { fprintf(stderr, "%s: cannot close file %s\n", argv[0], argv[1]); return 1; } return 0; } allegro-4.4.3.1/src/i386/igfx15.s0000664000175000017500000002604013437077643015051 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit linear graphics functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #ifdef ALLEGRO_COLOR16 .text /* void _linear_putpixel15(BITMAP *bmp, int x, int y, int color); * Draws a pixel onto a linear bitmap. */ FUNC(_linear_putpixel15) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %eax /* eax = y */ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ je putpix_noclip cmpl %ecx, BMP_CL(%edx) /* test cl */ jg putpix_done cmpl %ecx, BMP_CR(%edx) /* test cr */ jle putpix_done cmpl %eax, BMP_CT(%edx) /* test ct */ jg putpix_done cmpl %eax, BMP_CB(%edx) /* test cb */ jle putpix_done putpix_noclip: movw BMP_SEG(%edx), %es /* segment selector */ movl ARG4, %ebx /* bx = color */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je putpix_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) je putpix_xor_mode /* XOR? */ cmpl $DRAW_TRANS, GLOBL(_drawing_mode) je putpix_trans_mode /* translucent? */ LOOKUP_PATTERN_POS(%ecx, %eax, %edx) movw (%eax, %ecx, 2), %bx /* read pixel from pattern bitmap */ movl ARG1, %edx /* reload clobbered registers */ movl ARG2, %ecx movl ARG3, %eax cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je putpix_solid_mode /* draw the pattern pixel? */ cmpw $MASK_COLOR_15, %bx /* test the pattern pixel */ je putpix_zero_pattern movl ARG4, %ebx /* if set, draw color */ jmp putpix_solid_mode _align_ putpix_zero_pattern: cmpl $DRAW_MASKED_PATTERN, GLOBL(_drawing_mode) je putpix_done /* skip zero pixels in masked mode */ xorl %ebx, %ebx jmp putpix_solid_mode /* draw zero pixels in solid mode */ _align_ putpix_xor_mode: READ_BANK() /* read pixel from screen */ xorw %es:(%eax, %ecx, 2), %bx /* XOR */ movl ARG3, %eax /* re-read Y position */ jmp putpix_solid_mode _align_ putpix_trans_mode: READ_BANK() pushl %ecx pushl %edx movw %es:(%eax, %ecx, 2), %dx /* read pixel from screen */ pushl GLOBL(_blender_alpha) pushl %edx pushl %ebx /* and the drawing color */ call *GLOBL(_blender_func15) /* blend */ addl $12, %esp popl %edx popl %ecx movl %eax, %ebx movl ARG3, %eax /* re-read Y position */ _align_ putpix_solid_mode: WRITE_BANK() /* select bank */ movw %bx, %es:(%eax, %ecx, 2) /* store the pixel */ putpix_done: popw %es UNWRITE_BANK() popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_putpixel15() */ /* void _linear_hline15(BITMAP *bmp, int x1, int y, int x2, int color); * Draws a horizontal line onto a linear bitmap. */ FUNC(_linear_hline15) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ebx /* ebx = x1 */ movl ARG3, %eax /* eax = y */ movl ARG4, %ecx /* ecx = x2 */ cmpl %ebx, %ecx jge hline_no_xswap xchgl %ecx, %ebx hline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je hline_noclip cmpl BMP_CT(%edx), %eax /* test bmp->ct */ jl hline_done cmpl BMP_CB(%edx), %eax /* test bmp->cb */ jge hline_done cmpl BMP_CL(%edx), %ebx /* test x1, bmp->cl */ jge hline_x1_ok cmpl BMP_CL(%edx), %ecx /* test x2, bmp->cl */ jl hline_done movl BMP_CL(%edx), %ebx /* clip x1 */ hline_x1_ok: cmpl BMP_CR(%edx), %ecx /* test x2, bmp->cr */ jl hline_noclip cmpl BMP_CR(%edx), %ebx /* test x1, bmp->cr */ jge hline_done movl BMP_CR(%edx), %ecx /* clip x2 */ decl %ecx hline_noclip: subl %ebx, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* segment selector */ WRITE_BANK() /* select write bank */ leal (%eax, %ebx, 2), %edi /* dest address in edi */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je hline_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) jne hline_not_xor /* XOR? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%eax, %ebx, 2), %esi /* source address in esi */ movw ARG5, %bx /* read the color */ _align_ hline_xor_loop: movw %es:(%esi), %ax /* read a pixel */ xorw %bx, %ax /* xor */ movw %ax, %es:(%edi) /* and write it */ addl $2, %esi addl $2, %edi decl %ecx jg hline_xor_loop jmp hline_done _align_ hline_not_xor: cmpl $DRAW_TRANS, GLOBL(_drawing_mode) jne hline_not_trans /* translucent? */ movl ARG3, %eax /* select read bank */ READ_BANK() leal (%eax, %ebx, 2), %esi /* source address in esi */ movl %ecx, ARG4 /* loop counter on the stack */ _align_ hline_trans_loop: movw %es:(%esi), %ax /* read pixel from screen */ pushl GLOBL(_blender_alpha) pushl %eax pushl ARG5 /* and the drawing color */ call *GLOBL(_blender_func15) /* blend */ addl $12, %esp movw %ax, %es:(%edi) /* and write it */ addl $2, %esi addl $2, %edi decl ARG4 jg hline_trans_loop jmp hline_done _align_ hline_not_trans: movl ARG3, %eax /* get position in pattern bitmap */ LOOKUP_PATTERN_POS(%ebx, %eax, %edx) movl %eax, %esi movl GLOBL(_drawing_x_mask), %edx cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je hline_copy_pattern_loop cmpl $DRAW_SOLID_PATTERN, GLOBL(_drawing_mode) je hline_solid_pattern_loop _align_ hline_masked_pattern_loop: movw (%esi, %ebx, 2), %ax /* read a pixel */ cmpw $MASK_COLOR_15, %ax /* test it */ je hline_masked_skip movw ARG5, %ax movw %ax, %es:(%edi) /* write a colored pixel */ hline_masked_skip: incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_masked_pattern_loop jmp hline_done _align_ hline_copy_pattern_loop: movw (%esi, %ebx, 2), %ax /* read a pixel */ movw %ax, %es:(%edi) /* and write it */ incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_copy_pattern_loop jmp hline_done _align_ hline_solid_pattern_loop: movw (%esi, %ebx, 2), %ax /* read a pixel */ cmpw $MASK_COLOR_15, %ax /* test it */ je hline_solid_zero movw ARG5, %ax movw %ax, %es:(%edi) /* write a colored pixel */ incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_zero: movw $0, %es:(%edi) /* write a zero pixel */ incl %ebx andl %edx, %ebx addl $2, %edi decl %ecx jg hline_solid_pattern_loop jmp hline_done _align_ hline_solid_mode: /* regular hline drawer */ movw ARG5, %ax /* get color */ shll $16, %eax movw ARG5, %ax /* get two copies of the color */ cld testl $2, %edi /* are we long aligned? */ jz hline_l_aligned stosw /* if not, copy a word */ decl %ecx hline_l_aligned: shrl $1, %ecx /* for long copy */ jz hline_no_long rep ; stosl /* do some 32 bit copies */ hline_no_long: jnc hline_done stosw /* do we need a 16 bit copy? */ hline_done: popw %es movl ARG1, %edx UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_hline15() */ /* void _linear_vline15(BITMAP *bmp, int x, int y1, int y2, int color); * Draws a vertical line onto a linear bitmap. */ FUNC(_linear_vline15) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %edi /* edi = x */ movl ARG3, %esi /* esi = y1 */ movl ARG4, %ecx /* ecx = y2 */ cmpl %esi, %ecx jge vline_no_xswap xchgl %ecx, %esi vline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je vline_noclip cmpl BMP_CL(%edx), %edi /* test bmp->cl */ jl vline_done cmpl BMP_CR(%edx), %edi /* test bmp->cr */ jge vline_done cmpl BMP_CT(%edx), %esi /* test y1, bmp->ct */ jge vline_y1_ok cmpl BMP_CT(%edx), %ecx /* test y2, bmp->ct */ jl vline_done movl BMP_CT(%edx), %esi /* clip y1 */ vline_y1_ok: cmpl BMP_CB(%edx), %ecx /* test y2, bmp->cb */ jl vline_noclip cmpl BMP_CB(%edx), %esi /* test y1, bmp->cb */ jge vline_done movl BMP_CB(%edx), %ecx /* clip y2 */ decl %ecx vline_noclip: subl %esi, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* load segment */ cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je vline_solid_mode /* solid draw? */ movl BMP_CLIP(%edx), %eax /* store destination clipping flag */ pushl %eax movl $0, BMP_CLIP(%edx) /* turn clipping off (we already did it) */ movl ARG5, %eax pushl %eax /* push color */ pushl %esi /* push y */ pushl %edi /* push x */ pushl %edx /* push bitmap */ movl %ecx, %ebx /* ebx = loop counter */ _align_ vline_special_mode_loop: /* vline drawer for funny modes */ call GLOBL(_linear_putpixel15)/* draw the pixel */ incl 8(%esp) /* next y */ decl %ebx jg vline_special_mode_loop /* loop */ popl %edx /* clean up stack */ addl $12, %esp popl %eax movl %eax, BMP_CLIP(%edx) /* restore bitmap clipping flag */ jmp vline_done _align_ vline_solid_mode: /* normal vline drawer */ movl ARG5, %ebx /* get color */ _align_ vline_loop: movl %esi, %eax WRITE_BANK() /* select bank */ movw %bx, %es:(%eax, %edi, 2) /* write pixel */ incl %esi decl %ecx jg vline_loop /* loop */ vline_done: popw %es UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _linear_vline15() */ #endif /* ifdef ALLEGRO_COLOR16 */ allegro-4.4.3.1/src/i386/icpu.c0000664000175000017500000001216213437077643014666 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * i386 CPU detection routines, by Phil Frisbie. * * Theuzifan improved the support for Cyrix chips. * * Calin Andrian added 3DNow! detection code. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* helpers from icpus.s */ int _i_is_486(void); int _i_is_fpu(void); int _i_is_cyrix(void); void _i_cx_w(int index, int value); char _i_cx_r(int index); int _i_is_cpuid_supported(void); void _i_get_cpuid_info(uint32_t cpuid_levels, uint32_t *reg); /* cyrix_type: * Detects which type of Cyrix CPU is in use. */ static void cyrix_type(void) { char orgc2, newc2, orgc3, newc3; int cr2_rw = FALSE, cr3_rw = FALSE, type; type = 0xFF; orgc2 = _i_cx_r(0xC2); /* get current c2 value */ newc2 = orgc2 ^ 4; /* toggle test bit */ _i_cx_w(0xC2, newc2); /* write test value to c2 */ _i_cx_r(0xC0); /* dummy read to change bus */ if (_i_cx_r(0xC2) != orgc2) /* did test bit toggle */ cr2_rw = TRUE; /* yes bit changed */ _i_cx_w(0xC2, orgc2); /* return c2 to original value */ orgc3 = _i_cx_r(0xC3); /* get current c3 value */ newc3 = orgc3 ^ 0x80; /* toggle test bit */ _i_cx_w(0xC3, newc3); /* write test value to c3 */ _i_cx_r(0xC0); /* dummy read to change bus */ if (_i_cx_r(0xC3) != orgc3) /* did test bit change */ cr3_rw = TRUE; /* yes it did */ _i_cx_w(0xC3, orgc3); /* return c3 to original value */ if (((cr2_rw) && (cr3_rw)) || ((!cr2_rw) && (cr3_rw))) { type = _i_cx_r(0xFE); /* DEV ID register ok */ } else if ((cr2_rw) && (!cr3_rw)) { type = 0xFE; /* Cx486S A step */ } else if ((!cr2_rw) && (!cr3_rw)) { type = 0xFD; /* Pre ID Regs. Cx486SLC or DLC */ } if ((type < 0x30) || (type > 0xFC)) { cpu_family = 4; /* 486 class-including 5x86 */ cpu_model = 14; /* Cyrix */ } else if (type < 0x50) { cpu_family = 5; /* Pentium class-6x86 and Media GX */ cpu_model = 14; /* Cyrix */ } else { cpu_family = 6; /* Pentium || class- 6x86MX */ cpu_model = 14; /* Cyrix */ cpu_capabilities |= CPU_MMX; } } /* check_cpu: * This is the function to call to set the globals */ void check_cpu() { uint32_t cpuid_levels; uint32_t vendor_temp[4]; uint32_t reg[4]; cpu_capabilities = 0; if (_i_is_cpuid_supported()) { cpu_capabilities |= CPU_ID; _i_get_cpuid_info(0x00000000, reg); cpuid_levels = reg[0]; vendor_temp[0] = reg[1]; vendor_temp[1] = reg[3]; vendor_temp[2] = reg[2]; vendor_temp[3] = 0; do_uconvert((char *)vendor_temp, U_ASCII, cpu_vendor, U_CURRENT, _AL_CPU_VENDOR_SIZE); if (cpuid_levels > 0) { reg[0] = reg[1] = reg[2] = reg[3] = 0; _i_get_cpuid_info(1, reg); cpu_family = (reg[0] & 0xF00) >> 8; cpu_model = (reg[0] & 0xF0) >> 4; /* Note: cpu_family = 15 can mean a Pentium IV, Xeon, AMD64, Opteron... */ cpu_capabilities |= (reg[3] & 1 ? CPU_FPU : 0); cpu_capabilities |= (reg[3] & 0x800000 ? CPU_MMX : 0); /* SSE has MMX+ included */ cpu_capabilities |= (reg[3] & 0x02000000 ? CPU_SSE | CPU_MMXPLUS : 0); cpu_capabilities |= (reg[3] & 0x04000000 ? CPU_SSE2 : 0); cpu_capabilities |= (reg[2] & 0x00000001 ? CPU_SSE3 : 0); cpu_capabilities |= (reg[2] & 0x00000200 ? CPU_SSSE3 : 0); cpu_capabilities |= (reg[2] & 0x00080000 ? CPU_SSE41 : 0); cpu_capabilities |= (reg[2] & 0x00100000 ? CPU_SSE42 : 0); cpu_capabilities |= (reg[3] & 0x00008000 ? CPU_CMOV : 0); cpu_capabilities |= (reg[3] & 0x40000000 ? CPU_IA64 : 0); } _i_get_cpuid_info(0x80000000, reg); if (reg[0] > 0x80000000) { _i_get_cpuid_info(0x80000001, reg); cpu_capabilities |= (reg[3] & 0x80000000 ? CPU_3DNOW : 0); cpu_capabilities |= (reg[3] & 0x20000000 ? CPU_AMD64 : 0); /* Enhanced 3DNow! has MMX+ included */ cpu_capabilities |= (reg[3] & 0x40000000 ? CPU_ENH3DNOW | CPU_MMXPLUS : 0); } if (_i_is_cyrix()) cpu_model = 14; } else { cpu_capabilities |= (_i_is_fpu() ? CPU_FPU : 0); if (!_i_is_486()) { cpu_family = 3; } else { if (_i_is_cyrix()) { do_uconvert("CyrixInstead", U_ASCII, cpu_vendor, U_CURRENT, _AL_CPU_VENDOR_SIZE); cyrix_type(); } else { cpu_family = 4; cpu_model = 15; } } } } allegro-4.4.3.1/src/i386/iscanmmx.s0000664000175000017500000020365413437077643015575 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MMX polygon scanline filler helpers (gouraud shading, tmapping, etc). * MMX instructions will be #ifdef'ed out if your assembler doesn't * support them. * * By Calin Andrian. * * See readme.txt for copyright information. */ #include "asmdefs.inc" .text /* all these functions share the same parameters */ #define ADDR ARG1 #define W ARG2 #define INFO ARG3 #define MMX_REGS(src, dst) .byte 0xc0 + 8 * dst + src #define MMX_REGM(src, dst) \ .byte 5 + 8 * dst ; \ .long src /* pand is broken in GAS 2.8.1 */ #define PAND_R(src, dst) \ .byte 0x0f, 0xdb ; \ MMX_REGS(src, dst) #define PAND_M(src, dst) \ .byte 0x0f, 0xdb ; \ MMX_REGM(src, dst) /* Macros for 3Dnow! opcodes */ #define OP3D(src, dst, suf) \ .byte 0x0f, 0x0f ; \ MMX_REGS(src, dst) ; \ .byte suf #define FEMMS_R() .byte 0x0f, 0x0e #define PAVGUSB_R(src, dst) OP3D(src, dst, 0xbf) #define PF2ID_R(src, dst) OP3D(src, dst, 0x1d) #define PFACC_R(src, dst) OP3D(src, dst, 0xae) #define PFADD_R(src, dst) OP3D(src, dst, 0x9e) #define PFCMPEQ_R(src, dst) OP3D(src, dst, 0xb0) #define PFCMPGE_R(src, dst) OP3D(src, dst, 0x90) #define PFCMPGT_R(src, dst) OP3D(src, dst, 0xa0) #define PFMAX_R(src, dst) OP3D(src, dst, 0xa4) #define PFMIN_R(src, dst) OP3D(src, dst, 0x94) #define PFMUL_R(src, dst) OP3D(src, dst, 0xb4) #define PFRCP_R(src, dst) OP3D(src, dst, 0x96) #define PFRCPIT1_R(src, dst) OP3D(src, dst, 0xa6) #define PFRCPIT2_R(src, dst) OP3D(src, dst, 0xb6) #define PFRSQIT1_R(src, dst) OP3D(src, dst, 0xa7) #define PFRSQRT_R(src, dst) OP3D(src, dst, 0x97) #define PFSUB_R(src, dst) OP3D(src, dst, 0x9a) #define PFSUBR_R(src, dst) OP3D(src, dst, 0xaa) #define PI2FD_R(src, dst) OP3D(src, dst, 0x0d) #define PMULHRW_R(src, dst) OP3D(src, dst, 0xb7) #ifdef ALLEGRO_MMX #ifdef ALLEGRO_COLOR8 FUNC(_poly_scanline_grgb8x) pushl %ebp movl %esp, %ebp subl $8, %esp #define TMP4 -4(%ebp) #define TMP -8(%ebp) pushl %ebx pushl %esi pushl %edi movl INFO, %esi /* load registers */ movl POLYSEG_R(%esi), %eax movl %eax, TMP movl POLYSEG_DR(%esi), %edi addl %edi, %eax movl %eax, TMP4 shll $1, %edi movq TMP, %mm0 movd %edi, %mm1 punpckldq %mm1, %mm1 movl POLYSEG_G(%esi), %eax movl %eax, TMP movl POLYSEG_DG(%esi), %edi addl %edi, %eax movl %eax, TMP4 shll $1, %edi movq TMP, %mm2 movd %edi, %mm3 punpckldq %mm3, %mm3 movl POLYSEG_B(%esi), %eax movl %eax, TMP movl POLYSEG_DB(%esi), %edi addl %edi, %eax movl %eax, TMP4 shll $1, %edi movq TMP, %mm4 movd %edi, %mm5 punpckldq %mm5, %mm5 movl GLOBL(rgb_map), %esi movl ADDR, %edi movl W, %ecx _align_ grgb_loop_x: movq %mm0, %mm7 /* red */ movq %mm2, %mm6 /* green */ psrld $19, %mm7 psrld $19, %mm6 pslld $10, %mm7 pslld $5, %mm6 por %mm6, %mm7 movq %mm4, %mm6 /* blue */ psrld $19, %mm6 por %mm6, %mm7 movd %mm7, %edx movb (%esi, %edx), %al /* table lookup */ subl $2, %ecx jl grgb_last_x psrlq $32, %mm7 movd %mm7, %edx movb (%esi, %edx), %ah /* table lookup */ paddd %mm1, %mm0 paddd %mm3, %mm2 paddd %mm5, %mm4 movw %ax, FSEG(%edi) /* write two pixels */ leal 2(%edi), %edi jg grgb_loop_x grgb_done_x: emms popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _poly_scanline_grgb8x() */ _align_ grgb_last_x: movb %al, FSEG(%edi) /* write last pixel */ jmp grgb_done_x #undef TMP #undef TMP4 #endif /* COLOR8 */ #define DB -4(%ebp) #define DG -8(%ebp) #define DR -12(%ebp) #define TMP4 -4(%ebp) #define TMP -8(%ebp) #define SB -16(%ebp) #define SG -24(%ebp) #define SR -32(%ebp) /* first part of MMX grgb routine - two for the price of one */ #define INIT_GRGB_MMX(depth, r_sft, g_sft, b_sft) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $32, %esp ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ ; \ movl POLYSEG_R(%esi), %eax ; \ movl %eax, TMP ; \ movl POLYSEG_DR(%esi), %edi ; \ addl %edi, %eax ; \ movl %eax, TMP4 ; \ shll $1, %edi ; \ movq TMP, %mm0 ; \ movd %edi, %mm1 ; \ movd GLOBL(_rgb_r_shift_##depth), %mm7 ; \ punpckldq %mm1, %mm1 ; \ movq %mm7, SR ; \ ; \ movl POLYSEG_G(%esi), %eax ; \ movl %eax, TMP ; \ movl POLYSEG_DG(%esi), %edi ; \ addl %edi, %eax ; \ movl %eax, TMP4 ; \ shll $1, %edi ; \ movq TMP, %mm2 ; \ movd %edi, %mm3 ; \ movd GLOBL(_rgb_g_shift_##depth), %mm7 ; \ punpckldq %mm3, %mm3 ; \ movq %mm7, SG ; \ ; \ movl POLYSEG_B(%esi), %eax ; \ movl %eax, TMP ; \ movl POLYSEG_DB(%esi), %edi ; \ addl %edi, %eax ; \ movl %eax, TMP4 ; \ shll $1, %edi ; \ movq TMP, %mm4 ; \ movd %edi, %mm5 ; \ movd GLOBL(_rgb_b_shift_##depth), %mm7 ; \ punpckldq %mm5, %mm5 ; \ movq %mm7, SB ; \ ; \ movl ADDR, %edi ; \ movl W, %ecx ; \ ; \ _align_ ; \ grgb_loop_x_##depth: ; \ movq %mm0, %mm7 /* red */ ; \ movq %mm2, %mm6 /* green */ ; \ psrld $r_sft, %mm7 ; \ psrld $g_sft, %mm6 ; \ pslld SR, %mm7 ; \ pslld SG, %mm6 ; \ por %mm6, %mm7 ; \ movq %mm4, %mm6 /* blue */ ; \ psrld $b_sft, %mm6 ; \ pslld SB, %mm6 ; \ por %mm6, %mm7 /* end of grgb MMX routine */ #define END_GRGB_MMX(depth) \ paddd %mm1, %mm0 ; \ paddd %mm3, %mm2 ; \ paddd %mm5, %mm4 ; \ jg grgb_loop_x_##depth /* watch out for flags */ ; \ 99: ; \ emms ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR16 FUNC(_poly_scanline_grgb15x) INIT_GRGB_MMX(15, 19, 19, 19) subl $2, %ecx jl 7f /* from here on, flags don't change */ packssdw %mm7, %mm7 movd %mm7, FSEG(%edi) /* write two pixels */ leal 4(%edi), %edi END_GRGB_MMX(15) ret /* end of _poly_scanline_grgb15x() */ _align_ 7: movd %mm7, %eax movw %ax, FSEG(%edi) /* write the pixel */ jmp 99b FUNC(_poly_scanline_grgb16x) INIT_GRGB_MMX(16, 19, 18, 19) subl $2, %ecx jl 7f movd %mm7, %edx psrlq $16, %mm7 movd %mm7, %eax movw %dx, %ax movl %eax, FSEG(%edi) /* write two pixels */ leal 4(%edi), %edi END_GRGB_MMX(16) ret /* end of _poly_scanline_grgb16x() */ _align_ 7: movd %mm7, %eax movw %ax, FSEG(%edi) /* write the pixel */ jmp 99b #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 FUNC(_poly_scanline_grgb32x) INIT_GRGB_MMX(32, 16, 16, 16) subl $2, %ecx jl 7f movq %mm7, FSEG(%edi) /* write two pixels */ leal 8(%edi), %edi END_GRGB_MMX(32) ret /* end of _poly_scanline_grgb32x() */ _align_ 7: movd %mm7, FSEG(%edi) /* write the pixel */ jmp 99b #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 FUNC(_poly_scanline_grgb24x) INIT_GRGB_MMX(24, 16, 16, 16) movd %mm7, %eax movw %ax, FSEG(%edi) /* write the pixel */ shrl $16, %eax movb %al, FSEG 2(%edi) subl $2, %ecx jl 99f psrlq $32, %mm7 movd %mm7, %eax movw %ax, FSEG 3(%edi) /* write second pixel */ shrl $16, %eax movb %al, FSEG 5(%edi) leal 6(%edi), %edi cmpl $0, %ecx END_GRGB_MMX(24) ret /* end of _poly_scanline_grgb24x() */ #endif /* COLOR24 */ #undef DR #undef DG #undef DB #undef TMP #undef TMP2 #undef TMP4 #undef TMP6 #undef SR #undef SG #undef SB #define VMASK -8(%ebp) #define VSHIFT -16(%ebp) #define DV -20(%ebp) #define DU -24(%ebp) #define ALPHA4 -28(%ebp) #define ALPHA2 -30(%ebp) #define ALPHA -32(%ebp) #define DALPHA4 -36(%ebp) #define DALPHA -40(%ebp) #define UMASK -44(%ebp) /* first part of an affine texture mapping operation */ #define INIT_ATEX(extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $44, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ extra ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %eax ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ addl $16, %ecx ; \ movl %ecx, VSHIFT ; \ movl %eax, VMASK ; \ ; \ movl POLYSEG_UMASK(%esi), %eax ; \ movl POLYSEG_DU(%esi), %ebx ; \ movl POLYSEG_DV(%esi), %edx ; \ movl %eax, UMASK ; \ movl %ebx, DU ; \ movl %edx, DV ; \ ; \ movl POLYSEG_U(%esi), %ebx ; \ movl POLYSEG_V(%esi), %edx ; \ movl ADDR, %edi ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ ; \ _align_ ; \ 1: ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax /* end of atex routine */ #define END_ATEX() ; \ addl DU, %ebx ; \ addl DV, %edx ; \ decl W ; \ jg 1b ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp /* helper for setting up ALPHA and DALPHA before MMX lit routines */ #define INIT_MMX_ALPHA() \ movd POLYSEG_C(%esi), %mm0 ; \ movd POLYSEG_DC(%esi), %mm1 ; \ psrad $9, %mm0 /* alpha precision = 15 bits */ ; \ psrad $9, %mm1 ; \ punpcklwd %mm0, %mm0 /* double */ ; \ punpcklwd %mm1, %mm1 ; \ punpckldq %mm0, %mm0 /* quad */ ; \ punpckldq %mm1, %mm1 #ifdef ALLEGRO_COLOR16 FUNC(_poly_scanline_atex_lit15x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq GLOBL(_mask_mmx_15), %mm7 ; \ movl GLOBL(_blender_col_15), %eax ; \ movw %ax, ALPHA ; \ movw %ax, ALPHA2 ; \ movb %ah, ALPHA4 ; \ movq ALPHA, %mm6 ; \ PAND_R(7, 6) INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax movw %ax, ALPHA movw %ax, ALPHA2 movb %ah, ALPHA4 movq ALPHA, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ psubw %mm6, %mm2 paddw %mm2, %mm2 /* this trick solves everything */ pmulhw %mm0, %mm2 paddw %mm6, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ movq %mm2, ALPHA movd %mm2, %eax orw ALPHA2, %ax orb ALPHA4, %ah /* %ax = RGB */ paddw %mm1, %mm0 movw %ax, FSEG(%edi) addl $2, %edi END_ATEX() emms ret /* end of _poly_scanline_atex_lit15x() */ FUNC(_poly_scanline_atex_mask_lit15x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq GLOBL(_mask_mmx_15), %mm7 ; \ movl GLOBL(_blender_col_15), %eax ; \ movw %ax, ALPHA ; \ movw %ax, ALPHA2 ; \ movb %ah, ALPHA4 ; \ movq ALPHA, %mm6 ; \ PAND_R(7, 6) INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax cmpw $MASK_COLOR_15, %ax jz 7f movw %ax, ALPHA movw %ax, ALPHA2 movb %ah, ALPHA4 movq ALPHA, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ movq %mm2, ALPHA movd %mm2, %eax orw ALPHA2, %ax orb ALPHA4, %ah /* %ax = RGB */ movw %ax, FSEG(%edi) 7: addl $2, %edi paddw %mm1, %mm0 END_ATEX() emms ret /* end of _poly_scanline_atex_mask_lit15x() */ FUNC(_poly_scanline_atex_lit16x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq GLOBL(_mask_mmx_16), %mm7 ; \ movl GLOBL(_blender_col_16), %eax ; \ movw %ax, ALPHA ; \ movw %ax, ALPHA2 ; \ movb %ah, ALPHA4 ; \ movq ALPHA, %mm6 ; \ PAND_R(7, 6) INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax movw %ax, ALPHA movw %ax, ALPHA2 movb %ah, ALPHA4 movq ALPHA, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ movq %mm2, ALPHA movd %mm2, %eax orw ALPHA2, %ax orb ALPHA4, %ah /* %ax = RGB */ paddw %mm1, %mm0 movw %ax, FSEG(%edi) addl $2, %edi END_ATEX() emms ret /* end of _poly_scanline_atex_lit16x() */ FUNC(_poly_scanline_atex_mask_lit16x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq GLOBL(_mask_mmx_16), %mm7 ; \ movl GLOBL(_blender_col_16), %eax ; \ movw %ax, ALPHA ; \ movw %ax, ALPHA2 ; \ movb %ah, ALPHA4 ; \ movq ALPHA, %mm6 ; \ PAND_R(7, 6) INIT_ATEX(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax cmpw $MASK_COLOR_16, %ax jz 7f movw %ax, ALPHA movw %ax, ALPHA2 movb %ah, ALPHA4 movq ALPHA, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 PAND_R(7, 2) /* pand %mm7, %mm2 */ movq %mm2, ALPHA movd %mm2, %eax orw ALPHA2, %ax orb ALPHA4, %ah /* %ax = RGB */ movw %ax, FSEG(%edi) 7: addl $2, %edi paddw %mm1, %mm0 END_ATEX() emms ret /* end of _poly_scanline_atex_mask_lit16x() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 FUNC(_poly_scanline_atex_lit32x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ pxor %mm7, %mm7 ; \ movd GLOBL(_blender_col_32), %mm6 ; \ punpcklbw %mm7, %mm6 /* extend RGB to words */ INIT_ATEX(INIT_CODE) #undef INIT_CODE movd (%esi, %eax, 4), %mm2 punpcklbw %mm7, %mm2 /* extend RGB to words */ psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 packuswb %mm2, %mm2 paddw %mm1, %mm0 movd %mm2, FSEG(%edi) addl $4, %edi END_ATEX() emms ret /* end of _poly_scanline_atex_lit32x() */ FUNC(_poly_scanline_atex_mask_lit32x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ pxor %mm7, %mm7 ; \ movd GLOBL(_blender_col_32), %mm6 ; \ punpcklbw %mm7, %mm6 /* extend RGB to words */ INIT_ATEX(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax cmpl $MASK_COLOR_32, %eax jz 7f movd %eax, %mm2 punpcklbw %mm7, %mm2 /* extend RGB to words */ psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 packuswb %mm2, %mm2 movd %mm2, FSEG(%edi) 7: addl $4, %edi paddw %mm1, %mm0 END_ATEX() emms ret /* end of _poly_scanline_atex_mask_lit32x() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 FUNC(_poly_scanline_atex_lit24x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ pxor %mm7, %mm7 ; \ movd GLOBL(_blender_col_24), %mm6 ; \ punpcklbw %mm7, %mm6 INIT_ATEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movb 2(%esi, %ecx), %al shll $16, %eax movw (%esi, %ecx), %ax movd %eax, %mm2 punpcklbw %mm7, %mm2 psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 packuswb %mm2, %mm2 paddw %mm1, %mm0 movd %mm2, %eax movw %ax, FSEG(%edi) shrl $16, %eax movb %al, FSEG 2(%edi) addl $3, %edi END_ATEX() emms ret /* end of _poly_scanline_atex_lit24x() */ FUNC(_poly_scanline_atex_mask_lit24x) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ pxor %mm7, %mm7 ; \ movd GLOBL(_blender_col_24), %mm6 ; \ punpcklbw %mm7, %mm6 INIT_ATEX(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f movd %eax, %mm2 punpcklbw %mm7, %mm2 psubw %mm6, %mm2 paddw %mm2, %mm2 pmulhw %mm0, %mm2 paddw %mm6, %mm2 packuswb %mm2, %mm2 movd %mm2, %eax movw %ax, FSEG(%edi) shrl $16, %eax movb %al, FSEG 2(%edi) 7: addl $3, %edi paddw %mm1, %mm0 END_ATEX() emms ret /* end of _poly_scanline_atex_mask_lit24x() */ #endif /* COLOR24 */ #undef VMASK #undef VSHIFT #undef UMASK #undef DU #undef DV #undef ALPHA #undef ALPHA2 #undef ALPHA4 #undef DALPHA #undef DALPHA4 #define VMASK -4(%ebp) #define VSHIFT -8(%ebp) #define ALPHA4 -12(%ebp) #define ALPHA -16(%ebp) #define DALPHA4 -20(%ebp) #define DALPHA -24(%ebp) #define TMP4 -28(%ebp) #define TMP2 -30(%ebp) #define TMP -32(%ebp) #define BLEND4 -36(%ebp) #define BLEND2 -38(%ebp) #define BLEND -40(%ebp) #define U1 -44(%ebp) #define V1 -48(%ebp) #define DU -52(%ebp) #define DV -56(%ebp) #define DU4 -60(%ebp) #define DV4 -64(%ebp) #define DZ4 -68(%ebp) #define UMASK -72(%ebp) #define COUNT -76(%ebp) #define SM -80(%ebp) #define SV -84(%ebp) #define SU -88(%ebp) #define SZ -92(%ebp) /* helper for starting an fpu 1/z division */ #define START_FP_DIV() \ fld1 ; \ fdiv %st(3), %st(0) /* helper for ending an fpu division, returning corrected u and v values */ #define END_FP_DIV() \ fld %st(0) /* duplicate the 1/z value */ ; \ fmul %st(3), %st(0) /* divide u by z */ ; \ fxch %st(1) ; \ fmul %st(2), %st(0) /* divide v by z */ #define UPDATE_FP_POS_4() \ fadds DV4 /* update v coord */ ; \ fxch %st(1) /* swap vuz stack to uvz */ ; \ fadds DU4 /* update u coord */ ; \ fxch %st(2) /* swap uvz stack to zvu */ ; \ fadds DZ4 /* update z value */ ; \ fxch %st(2) /* swap zvu stack to uvz */ ; \ fxch %st(1) /* swap uvz stack back to vuz */ /* main body of the perspective-correct texture mapping routine, using 3D enhancement CPUs */ #define INIT_PTEX_3D(extra) \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $100, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ FEMMS_R() ; \ movl INFO, %esi /* load registers */ ; \ ; \ extra ; \ ; \ movd POLYSEG_DZ(%esi), %mm1 ; \ movl POLYSEG_DFV(%esi), %eax ; \ movl POLYSEG_DFU(%esi), %edx ; \ movl %eax, DV4 ; \ movl %edx, DU4 ; \ movq DV4, %mm3 ; \ PFADD_R(1, 1) /* pfadd %mm1, %mm1 */ ; \ PFADD_R(3, 3) /* pfadd %mm3, %mm3 */ ; \ PFADD_R(1, 1) /* pfadd %mm1, %mm1 */ ; \ PFADD_R(3, 3) /* pfadd %mm3, %mm3 */ ; \ ; \ movd POLYSEG_Z(%esi), %mm0 ; \ PFRCP_R(0, 4) /* pfrcp %mm0, %mm4 */ ; \ movl POLYSEG_FV(%esi), %eax ; \ movl POLYSEG_FU(%esi), %edx ; \ movl %eax, V1 ; \ movl %edx, U1 ; \ movq V1, %mm2 ; \ PFMUL_R(2, 4) /* pfmul %mm2, %mm4 */ ; \ PF2ID_R(4, 4) /* pf2id %mm4, %mm4 */ ; \ movq %mm4, V1 ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %eax ; \ movl POLYSEG_UMASK(%esi), %edx ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ addl $16, %ecx ; \ movl %ecx, VSHIFT ; \ movl %eax, VMASK ; \ movl %edx, UMASK ; \ ; \ movl ADDR, %edi ; \ movl V1, %edx ; \ movl U1, %ebx ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ movl $0, COUNT /* COUNT ranges from 3 to -1 */ ; \ jmp 3f ; \ ; \ _align_ ; \ 1: /* step 2: compute DU, DV for next 4 steps */ ; \ movl $3, COUNT ; \ ; \ PFADD_R(1, 0) /* pfadd %mm1, %mm0 */ ; \ PFADD_R(3, 2) /* pfadd %mm3, %mm2 */ ; \ PFRCP_R(0, 4) /* pfrcp %mm0, %mm4 */ ; \ PFMUL_R(2, 4) /* pfmul %mm2, %mm4 */ ; \ PF2ID_R(4, 4) /* pf2id %mm4, %mm4 */ ; \ ; \ movq V1, %mm5 ; \ movq %mm4, V1 ; \ psubd %mm5, %mm4 ; \ psrad $2, %mm4 ; \ movq %mm4, DV ; \ 2: /* step 3 & 4: next U, V */ ; \ addl DV, %edx ; \ addl DU, %ebx ; \ 3: /* step 1: just use U and V */ ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax #define END_PTEX_3D() \ decl W ; \ jle 6f ; \ decl COUNT ; \ jg 2b ; \ nop ; \ jl 1b ; \ movl V1, %edx ; \ movl U1, %ebx ; \ jmp 3b ; \ _align_ ; \ 6: ; \ FEMMS_R() ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp /* main body of the perspective-correct texture mapping routine special version for PTEX LIT with MMX */ #define DO_PTEX_LIT() \ pushl %ebp ; \ movl %esp, %ebp ; \ subl $100, %esp /* local variables */ ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ ; \ movl INFO, %esi /* load registers */ ; \ ; \ INIT() ; \ ; \ flds POLYSEG_Z(%esi) /* z at bottom of fpu stack */ ; \ flds POLYSEG_FU(%esi) /* followed by u */ ; \ flds POLYSEG_FV(%esi) /* followed by v */ ; \ ; \ flds POLYSEG_DFU(%esi) /* multiply diffs by four */ ; \ flds POLYSEG_DFV(%esi) ; \ flds POLYSEG_DZ(%esi) ; \ fxch %st(2) /* u v z */ ; \ fadd %st(0), %st(0) /* 2u v z */ ; \ fxch %st(1) /* v 2u z */ ; \ fadd %st(0), %st(0) /* 2v 2u z */ ; \ fxch %st(2) /* z 2u 2v */ ; \ fadd %st(0), %st(0) /* 2z 2u 2v */ ; \ fxch %st(1) /* 2u 2z 2v */ ; \ fadd %st(0), %st(0) /* 4u 2z 2v */ ; \ fxch %st(2) /* 2v 2z 4u */ ; \ fadd %st(0), %st(0) /* 4v 2z 4u */ ; \ fxch %st(1) /* 2z 4v 4u */ ; \ fadd %st(0), %st(0) /* 4z 4v 4u */ ; \ fxch %st(2) /* 4u 4v 4z */ ; \ fstps DU4 ; \ fstps DV4 ; \ fstps DZ4 ; \ ; \ START_FP_DIV() ; \ ; \ movl POLYSEG_VSHIFT(%esi), %ecx ; \ movl POLYSEG_VMASK(%esi), %eax ; \ movl POLYSEG_UMASK(%esi), %edx ; \ shll %cl, %eax /* adjust v mask and shift value */ ; \ negl %ecx ; \ addl $16, %ecx ; \ movl %ecx, VSHIFT ; \ movl %eax, VMASK ; \ movl %edx, UMASK ; \ ; \ END_FP_DIV() ; \ fistpl V1 /* store v */ ; \ fistpl U1 /* store u */ ; \ UPDATE_FP_POS_4() ; \ START_FP_DIV() ; \ ; \ movl ADDR, %edi ; \ movl V1, %edx ; \ movl U1, %ebx ; \ movl POLYSEG_TEXTURE(%esi), %esi ; \ ; \ fstps SM ; \ fstps SV ; \ fstps SU ; \ fstps SZ ; \ ; \ LOAD() ; \ ; \ _align_ ; \ 1: /* step 1: just use U and V */ ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ PIXEL() ; \ decl W ; \ jle 99f ; \ SAVE() ; \ emms ; \ /* step 2: compute DU, DV for next 4 steps */ ; \ flds SZ ; \ flds SU ; \ flds SV ; \ flds SM ; \ ; \ END_FP_DIV() /* finish the divide */ ; \ fistpl V1 ; \ fistpl U1 ; \ UPDATE_FP_POS_4() /* 4 pixels away */ ; \ START_FP_DIV() ; \ ; \ movl V1, %eax ; \ movl U1, %ecx ; \ subl %edx, %eax ; \ subl %ebx, %ecx ; \ sarl $2, %eax ; \ sarl $2, %ecx ; \ movl %eax, DV ; \ movl %ecx, DU ; \ ; \ addl %eax, %edx ; \ addl %ecx, %ebx ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ fstps SM ; \ fstps SV ; \ fstps SU ; \ fstps SZ ; \ ; \ LOAD() ; \ PIXEL() ; \ decl W ; \ jle 99f ; \ /* step 3 : next U, V */ ; \ addl DV, %edx ; \ addl DU, %ebx ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ ; \ PIXEL() ; \ decl W ; \ jle 99f ; \ /* step 4: next U, V */ ; \ addl DV, %edx ; \ addl DU, %ebx ; \ movl %edx, %eax /* get v */ ; \ movb VSHIFT, %cl ; \ sarl %cl, %eax ; \ andl VMASK, %eax ; \ ; \ movl %ebx, %ecx /* get u */ ; \ sarl $16, %ecx ; \ andl UMASK, %ecx ; \ addl %ecx, %eax ; \ movl V1, %edx ; \ movl U1, %ebx ; \ ; \ PIXEL() ; \ decl W ; \ jg 1b ; \ 99: ; \ emms ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ movl %ebp, %esp ; \ popl %ebp #ifdef ALLEGRO_COLOR16 FUNC(_poly_scanline_ptex_lit15x) #define INIT() \ INIT_MMX_ALPHA() ; \ movq %mm0, ALPHA ; \ movq %mm1, DALPHA ; \ emms ; \ movl GLOBL(_blender_col_15), %eax ; \ movl %eax, %ecx ; \ movl %eax, %edx ; \ andl $0x001f, %eax ; \ andl $0x03e0, %ecx ; \ andl $0x7c00, %edx ; \ movw %ax, BLEND ; \ shrl $8, %edx ; \ movw %cx, BLEND2 ; \ movl %edx, BLEND4 #define LOAD() \ movq ALPHA, %mm0 ; \ movq DALPHA, %mm1 ; \ movq BLEND, %mm6 ; \ movq GLOBL(_mask_mmx_15), %mm7 #define PIXEL() \ movw (%esi, %eax, 2), %ax ; \ movw %ax, TMP ; \ movw %ax, TMP2 ; \ movb %ah, TMP4 ; \ movq TMP, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ movq %mm2, TMP ; \ movd %mm2, %eax ; \ orw TMP2, %ax ; \ orb TMP4, %ah ; \ movw %ax, FSEG(%edi) ; \ ; \ addl $2, %edi ; \ paddw %mm1, %mm0 #define SAVE() \ movq %mm0, ALPHA DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_lit15x() */ #undef PIXEL FUNC(_poly_scanline_ptex_mask_lit15x) #define PIXEL() \ movw (%esi, %eax, 2), %ax ; \ cmpw $MASK_COLOR_15, %ax ; \ jz 7f ; \ movw %ax, TMP ; \ movw %ax, TMP2 ; \ movb %ah, TMP4 ; \ movq TMP, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ movq %mm2, TMP ; \ movd %mm2, %eax ; \ orw TMP2, %ax ; \ orb TMP4, %ah ; \ movw %ax, FSEG(%edi) ; \ 7: ; \ addl $2, %edi ; \ paddw %mm1, %mm0 DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_mask_lit15x() */ #undef INIT #undef LOAD #undef SAVE #undef PIXEL FUNC(_poly_scanline_ptex_lit15d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ movl GLOBL(_blender_col_15), %eax ; \ movw %ax, BLEND ; \ movw %ax, BLEND2 ; \ movb %ah, BLEND4 ; \ movq BLEND, %mm6 ; \ PAND_M(GLOBL(_mask_mmx_15), 6) /* pand mem, %mm6 */ INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax movw %ax, TMP movw %ax, TMP2 movb %ah, TMP4 movq TMP, %mm4 PAND_M(GLOBL(_mask_mmx_15), 4) /* pand mem, %mm4 */ psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 PAND_M(GLOBL(_mask_mmx_15), 4) /* pand mem, %mm4 */ movq %mm4, TMP movd %mm4, %eax orw TMP2, %ax orb TMP4, %ah /* %ax = RGB */ movw %ax, FSEG(%edi) addl $2, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_lit15d() */ FUNC(_poly_scanline_ptex_mask_lit15d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ movl GLOBL(_blender_col_15), %eax ; \ movw %ax, BLEND ; \ movw %ax, BLEND2 ; \ movb %ah, BLEND4 ; \ movq BLEND, %mm6 ; \ PAND_M(GLOBL(_mask_mmx_15), 6) /* pand mem, %mm6 */ INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax cmpw $MASK_COLOR_15, %ax jz 7f movw %ax, TMP movw %ax, TMP2 movb %ah, TMP4 movq TMP, %mm4 PAND_M(GLOBL(_mask_mmx_15), 4) /* pand mem, %mm4 */ psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 PAND_M(GLOBL(_mask_mmx_15), 4) /* pand mem, %mm4 */ movq %mm4, TMP movd %mm4, %eax orw TMP2, %ax orb TMP4, %ah /* %ax = RGB */ movw %ax, FSEG(%edi) 7: addl $2, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_mask_lit15d() */ FUNC(_poly_scanline_ptex_lit16x) #define INIT() \ INIT_MMX_ALPHA() ; \ movq %mm0, ALPHA ; \ movq %mm1, DALPHA ; \ emms ; \ movl GLOBL(_blender_col_16), %eax ; \ movl %eax, %ecx ; \ movl %eax, %edx ; \ andl $0x001f, %eax ; \ andl $0x07e0, %ecx ; \ andl $0xf800, %edx ; \ movw %ax, BLEND ; \ shrl $8, %edx ; \ movw %cx, BLEND2 ; \ movl %edx, BLEND4 #define LOAD() \ movq ALPHA, %mm0 ; \ movq DALPHA, %mm1 ; \ movq BLEND, %mm6 ; \ movq GLOBL(_mask_mmx_16), %mm7 #define PIXEL() \ movw (%esi, %eax, 2), %ax ; \ movw %ax, TMP ; \ movw %ax, TMP2 ; \ movb %ah, TMP4 ; \ movq TMP, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ movq %mm2, TMP ; \ movd %mm2, %eax ; \ orw TMP2, %ax ; \ orb TMP4, %ah ; \ movw %ax, FSEG(%edi) ; \ ; \ addl $2, %edi ; \ paddw %mm1, %mm0 #define SAVE() \ movq %mm0, ALPHA DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_lit16x() */ #undef PIXEL FUNC(_poly_scanline_ptex_mask_lit16x) #define PIXEL() \ movw (%esi, %eax, 2), %ax ; \ cmpw $MASK_COLOR_16, %ax ; \ jz 7f ; \ movw %ax, TMP ; \ movw %ax, TMP2 ; \ movb %ah, TMP4 ; \ movq TMP, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ PAND_R(7, 2) /* pand %mm7, %mm2 */ ; \ ; \ movq %mm2, TMP ; \ movd %mm2, %eax ; \ orw TMP2, %ax ; \ orb TMP4, %ah ; \ movw %ax, FSEG(%edi) ; \ 7: ; \ addl $2, %edi ; \ paddw %mm1, %mm0 DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_mask_lit16x() */ #undef INIT #undef LOAD #undef SAVE #undef PIXEL FUNC(_poly_scanline_ptex_lit16d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ movl GLOBL(_blender_col_16), %eax ; \ movw %ax, BLEND ; \ movw %ax, BLEND2 ; \ movb %ah, BLEND4 ; \ movq BLEND, %mm6 ; \ PAND_M(GLOBL(_mask_mmx_16), 6) /* pand mem, %mm6 */ INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax movw %ax, TMP movw %ax, TMP2 movb %ah, TMP4 movq TMP, %mm4 PAND_M(GLOBL(_mask_mmx_16), 4) /* pand mem, %mm4 */ psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 PAND_M(GLOBL(_mask_mmx_16), 4) /* pand mem, %mm4 */ movq %mm4, TMP movd %mm4, %eax orw TMP2, %ax orb TMP4, %ah /* %ax = RGB */ movw %ax, FSEG(%edi) addl $2, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_lit16d() */ FUNC(_poly_scanline_ptex_mask_lit16d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ movl GLOBL(_blender_col_16), %eax ; \ movw %ax, BLEND ; \ movw %ax, BLEND2 ; \ movb %ah, BLEND4 ; \ movq BLEND, %mm6 ; \ PAND_M(GLOBL(_mask_mmx_16), 6) /* pand mem, %mm6 */ INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE movw (%esi, %eax, 2), %ax cmpw $MASK_COLOR_16, %ax jz 7f movw %ax, TMP movw %ax, TMP2 movb %ah, TMP4 movq TMP, %mm4 PAND_M(GLOBL(_mask_mmx_16), 4) /* pand mem, %mm4 */ psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 PAND_M(GLOBL(_mask_mmx_16), 4) /* pand mem, %mm4 */ movq %mm4, TMP movd %mm4, %eax orw TMP2, %ax orb TMP4, %ah /* %ax = RGB */ movw %ax, FSEG(%edi) 7: addl $2, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_mask_lit16d() */ #endif /* COLOR16 */ #ifdef ALLEGRO_COLOR32 FUNC(_poly_scanline_ptex_lit32x) #define INIT() \ INIT_MMX_ALPHA() ; \ movq %mm0, ALPHA ; \ movq %mm1, DALPHA ; \ emms #define LOAD() \ movq ALPHA, %mm0 ; \ movq DALPHA, %mm1 ; \ pxor %mm7, %mm7 ; \ movd GLOBL(_blender_col_32), %mm6 ; \ punpcklbw %mm7, %mm6 #define PIXEL() \ movd (%esi, %eax, 4), %mm2 ; \ punpcklbw %mm7, %mm2 ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ ; \ packuswb %mm2, %mm2 ; \ movd %mm2, FSEG(%edi) ; \ ; \ addl $4, %edi ; \ paddw %mm1, %mm0 #define SAVE() \ movq %mm0, ALPHA DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_lit32x() */ #undef PIXEL FUNC(_poly_scanline_ptex_mask_lit32x) #define PIXEL() \ movl (%esi, %eax, 4), %eax ; \ cmpl $MASK_COLOR_32, %eax ; \ jz 7f ; \ movd %eax, %mm2 ; \ punpcklbw %mm7, %mm2 ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ ; \ packuswb %mm2, %mm2 ; \ movd %mm2, FSEG(%edi) ; \ 7: ; \ addl $4, %edi ; \ paddw %mm1, %mm0 DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_mask_lit32x() */ #undef INIT #undef LOAD #undef SAVE #undef PIXEL FUNC(_poly_scanline_ptex_lit32d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ pxor %mm5, %mm5 ; \ movd GLOBL(_blender_col_32), %mm6 ; \ punpcklbw %mm5, %mm6 INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE movd (%esi, %eax, 4), %mm4 pxor %mm5, %mm5 punpcklbw %mm5, %mm4 psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 packuswb %mm4, %mm4 movd %mm4, FSEG(%edi) addl $4, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_lit32d() */ FUNC(_poly_scanline_ptex_mask_lit32d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ pxor %mm5, %mm5 ; \ movd GLOBL(_blender_col_32), %mm6 ; \ punpcklbw %mm5, %mm6 INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE movl (%esi, %eax, 4), %eax cmpl $MASK_COLOR_32, %eax jz 7f movd %eax, %mm4 pxor %mm5, %mm5 punpcklbw %mm5, %mm4 psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 packuswb %mm4, %mm4 movd %mm4, FSEG(%edi) 7: addl $4, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_mask_lit32d() */ #endif /* COLOR32 */ #ifdef ALLEGRO_COLOR24 FUNC(_poly_scanline_ptex_lit24x) #define INIT() \ INIT_MMX_ALPHA() ; \ movq %mm0, ALPHA ; \ movq %mm1, DALPHA ; \ emms #define LOAD() \ movq ALPHA, %mm0 ; \ movq DALPHA, %mm1 ; \ pxor %mm7, %mm7 ; \ movd GLOBL(_blender_col_24), %mm6 ; \ punpcklbw %mm7, %mm6 #define PIXEL() \ leal (%eax, %eax, 2), %ecx ; \ movb 2(%esi, %ecx), %al ; \ shll $16, %eax ; \ movw (%esi, %ecx), %ax ; \ movd %eax, %mm2 ; \ punpcklbw %mm7, %mm2 ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ ; \ packuswb %mm2, %mm2 ; \ movd %mm2, %eax ; \ movw %ax, FSEG(%edi) ; \ shrl $16, %eax ; \ movb %al, FSEG 2(%edi) ; \ ; \ addl $3, %edi ; \ paddw %mm1, %mm0 #define SAVE() \ movq %mm0, ALPHA DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_lit24x() */ #undef PIXEL FUNC(_poly_scanline_ptex_mask_lit24x) #define PIXEL() \ leal (%eax, %eax, 2), %ecx ; \ movzbl 2(%esi, %ecx), %eax ; \ shll $16, %eax ; \ movw (%esi, %ecx), %ax ; \ cmpl $MASK_COLOR_24, %eax ; \ jz 7f ; \ movd %eax, %mm2 ; \ punpcklbw %mm7, %mm2 ; \ ; \ psubw %mm6, %mm2 ; \ paddw %mm2, %mm2 ; \ pmulhw %mm0, %mm2 ; \ paddw %mm6, %mm2 ; \ ; \ packuswb %mm2, %mm2 ; \ movd %mm2, %eax ; \ movw %ax, FSEG(%edi) ; \ shrl $16, %eax ; \ movb %al, FSEG 2(%edi) ; \ 7: ; \ addl $3, %edi ; \ paddw %mm1, %mm0 DO_PTEX_LIT() ret /* end of _poly_scanline_ptex_mask_lit24x() */ #undef INIT #undef LOAD #undef SAVE #undef PIXEL FUNC(_poly_scanline_ptex_lit24d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ pxor %mm5, %mm5 ; \ movd GLOBL(_blender_col_24), %mm6 ; \ punpcklbw %mm5, %mm6 INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movb 2(%esi, %ecx), %al shll $16, %eax movw (%esi, %ecx), %ax movd %eax, %mm4 pxor %mm5, %mm5 punpcklbw %mm5, %mm4 psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 packuswb %mm4, %mm4 movd %mm4, %eax movw %ax, FSEG(%edi) shrl $16, %eax movb %al, FSEG 2(%edi) addl $3, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_lit24d() */ FUNC(_poly_scanline_ptex_mask_lit24d) #define INIT_CODE \ INIT_MMX_ALPHA() ; \ movq %mm0, %mm7 ; \ movq %mm1, DALPHA ; \ pxor %mm5, %mm5 ; \ movd GLOBL(_blender_col_24), %mm6 ; \ punpcklbw %mm5, %mm6 INIT_PTEX_3D(INIT_CODE) #undef INIT_CODE leal (%eax, %eax, 2), %ecx movzbl 2(%esi, %ecx), %eax shll $16, %eax movw (%esi, %ecx), %ax cmpl $MASK_COLOR_24, %eax jz 7f movd %eax, %mm4 pxor %mm5, %mm5 punpcklbw %mm5, %mm4 psubw %mm6, %mm4 paddw %mm4, %mm4 pmulhw %mm7, %mm4 paddw %mm6, %mm4 packuswb %mm4, %mm4 movd %mm4, %eax movw %ax, FSEG(%edi) shrl $16, %eax movb %al, FSEG 2(%edi) 7: addl $3, %edi paddw DALPHA, %mm7 END_PTEX_3D() ret /* end of _poly_scanline_ptex_mask_lit24d() */ #endif /* COLOR24 */ #endif /* MMX */ allegro-4.4.3.1/src/i386/imisc.s0000664000175000017500000003445013437077643015056 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Math routines, compiled sprite wrapper, etc. * * By Shawn Hargreaves. * * fixsqrt() and fixhypot() routines by David Kuhling. * * See readme.txt for copyright information. */ #include "asmdefs.inc" .text /* empty bank switch routine for the standard VGA mode and memory bitmaps */ FUNC(_stub_bank_switch) movl BMP_LINE(%edx, %eax, 4), %eax ret FUNC(_stub_unbank_switch) ret FUNC(_stub_bank_switch_end) ret /* void apply_matrix_f(MATRIX_f *m, float x, float y, float z, * float *xout, float *yout, float *zout); * Floating point vector by matrix multiplication routine. */ FUNC(apply_matrix_f) #define MTX ARG1 #define X ARG2 #define Y ARG3 #define Z ARG4 #define XOUT ARG5 #define YOUT ARG6 #define ZOUT ARG7 pushl %ebp movl %esp, %ebp pushl %ebx movl MTX, %edx movl XOUT, %eax movl YOUT, %ebx movl ZOUT, %ecx flds M_V00(%edx) fmuls X flds M_V01(%edx) fmuls Y flds M_V02(%edx) fmuls Z fxch %st(2) faddp %st(0), %st(1) flds M_V10(%edx) fxch %st(2) faddp %st(0), %st(1) fxch %st(1) fmuls X fxch %st(1) fadds M_T0(%edx) flds M_V11(%edx) fmuls Y flds M_V12(%edx) fmuls Z fxch %st(1) faddp %st(0), %st(3) flds M_V20(%edx) fxch %st(3) faddp %st(0), %st(1) fxch %st(2) fmuls X fxch %st(2) fadds M_T1(%edx) flds M_V21(%edx) fmuls Y flds M_V22(%edx) fmuls Z fxch %st(4) faddp %st(0), %st(1) fxch %st(1) fstps (%ebx) faddp %st(0), %st(2) fstps (%eax) fadds M_T2(%edx) fstps (%ecx) popl %ebx movl %ebp, %esp popl %ebp ret /* end of apply_matrix_f() */ #undef X #undef Y /* void draw_compiled_sprite(BITMAP *bmp, COMPILED_SPRITE *sprite, int x, y) * Draws a compiled sprite onto the specified bitmap at the specified * position, _ignoring_ clipping. The bitmap must be in the same format * that the sprite was compiled for. */ FUNC(draw_compiled_sprite) #define BMP ARG1 #define SPRITE ARG2 #define X ARG3 #define Y ARG4 pushl %ebp movl %esp, %ebp subl $4, %esp /* 1 local variable: */ #define PLANE -4(%ebp) pushl %ebx pushl %esi pushl %edi movl BMP, %edx /* bitmap pointer in edx */ #ifdef USE_FS movw BMP_SEG(%edx), %fs /* load segment selector into fs */ #endif movl SPRITE, %ebx cmpw $0, CMP_PLANAR(%ebx) /* is the sprite planar or linear? */ je linear_compiled_sprite movl X, %ecx /* get write plane mask in bx */ andb $3, %cl movl $0x1102, %ebx shlb %cl, %bh movl BMP_LINE+4(%edx), %ecx /* get line width in ecx */ subl BMP_LINE(%edx), %ecx movl X, %esi /* get destination address in edi */ shrl $2, %esi movl Y, %edi movl BMP_LINE(%edx, %edi, 4), %edi addl %esi, %edi movl $0x3C4, %edx /* port address in dx */ movl $0, PLANE /* zero the plane counter */ _align_ planar_compiled_sprite_loop: movl %ebx, %eax /* set the write plane */ outw %ax, %dx movl %edi, %eax /* get address in eax */ movl PLANE, %esi /* get the drawer function in esi */ shll $3, %esi addl SPRITE, %esi movl CMP_DRAW(%esi), %esi call *%esi /* and draw the plane! */ incl PLANE /* next plane */ cmpl $4, PLANE jge draw_compiled_sprite_done rolb $1, %bh /* advance the plane position */ adcl $0, %edi jmp planar_compiled_sprite_loop _align_ linear_compiled_sprite: movl X, %eax movzwl CMP_COLOR_DEPTH(%ebx), %ecx cmpl $24, %ecx jne normal_linear_compiled_sprite leal (%eax, %eax, 2), %eax jmp end24bpp_linear_compiled_sprite _align_ normal_linear_compiled_sprite: addl $7, %ecx shrl $4, %ecx shll %cl, %eax end24bpp_linear_compiled_sprite: movl %eax, %ecx /* x coordinate in ecx */ movl Y, %edi /* y coordinate in edi */ movl BMP_WBANK(%edx), %esi /* bank switch function in esi */ movl CMP_DRAW(%ebx), %ebx /* drawer function in ebx */ call *%ebx /* and draw it! */ draw_compiled_sprite_done: movl BMP, %edx UNWRITE_BANK() popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of draw_compiled_sprite() */ /* void _do_stretch(BITMAP *source, BITMAP *dest, void *drawer, * int sx, fixed sy, fixed syd, int dx, int dy, int dh, * int color_depth); * * Helper function for stretch_blit(), calls the compiled line drawer. */ FUNC(_do_stretch) #define SOURCE ARG1 #define DEST ARG2 #define DRAWER ARG3 #define SX ARG4 #define SY ARG5 #define SYD ARG6 #define DX ARG7 #define DY ARG8 #define DH ARG9 #define COL_DEPTH ARG10 pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushw %es movl DEST, %edx movw BMP_SEG(%edx), %es /* load destination segment */ movl DRAWER, %ebx /* the actual line drawer */ movl BMP_ID(%edx), %eax testl $BMP_ID_PLANAR, %eax jnz stretch_modex_loop movl COL_DEPTH, %eax cmpl $8, %eax je stretch_normal_loop cmpl $15, %eax je stretch_bpp_16 cmpl $16, %eax je stretch_bpp_16 cmpl $24, %eax je stretch_bpp_24 cmpl $32, %eax je stretch_bpp_32 jmp stretch_done /* special loop for 24 bit */ _align_ stretch_bpp_24: movl SX, %eax leal (%eax, %eax, 2), %eax movl %eax, SX movl DX, %eax leal (%eax, %eax, 2), %eax movl %eax, DX _align_ stretch_loop24: movl SOURCE, %edx /* get source line (in esi) and bank */ movl SY, %eax shrl $16, %eax READ_BANK() movl %eax, %esi addl SX, %esi movl DEST, %edx /* get dest line (in edi) and bank */ movl DY, %eax WRITE_BANK() movl %eax, %edi addl DX, %edi pushl %edx pushl %ebx call *%ebx /* draw (clobbers eax, ebx, ecx, edx) */ popl %ebx popl %edx movl SYD, %eax /* next line in source bitmap */ addl %eax, SY incl DY /* next line in dest bitmap */ decl DH jg stretch_loop24 jmp stretch_done /* special loop for mode-X */ _align_ stretch_modex_loop: movl SOURCE, %edx /* get source line (in esi) and bank */ movl SY, %eax shrl $16, %eax movl BMP_LINE(%edx, %eax, 4), %esi addl SX, %esi movl DEST, %edx /* get dest line (in edi) and bank */ movl DY, %eax movl BMP_LINE(%edx, %eax, 4), %edi addl DX, %edi call *%ebx /* draw the line (clobbers eax and ecx) */ movl SYD, %eax /* next line in source bitmap */ addl %eax, SY incl DY /* next line in dest bitmap */ decl DH jg stretch_modex_loop jmp stretch_done _align_ stretch_bpp_16: shll $1, SX shll $1, DX jmp stretch_normal_loop _align_ stretch_bpp_32: shll $2, SX shll $2, DX /* normal stretching loop */ _align_ stretch_normal_loop: movl SOURCE, %edx /* get source line (in esi) and bank */ movl SY, %eax shrl $16, %eax READ_BANK() movl %eax, %esi addl SX, %esi movl DEST, %edx /* get dest line (in edi) and bank */ movl DY, %eax WRITE_BANK() movl %eax, %edi addl DX, %edi call *%ebx /* draw the line (clobbers eax and ecx) */ movl SYD, %eax /* next line in source bitmap */ addl %eax, SY incl DY /* next line in dest bitmap */ decl DH jg stretch_normal_loop stretch_done: popw %es movl SOURCE, %edx UNWRITE_BANK() movl DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _do_stretch() */ /* unsigned long _blender_trans24(unsigned long x, y, n); * 24 bit trans blender function. See colblend.c for the others. */ FUNC(_blender_trans24) pushl %ebp movl %esp, %ebp pushl %esi pushl %ecx pushl %ebx movl ARG1, %esi movl ARG2, %ebx movl ARG3, %ecx movl %esi, %eax movl %ebx, %edx andl $0xFF00FF, %eax andl $0xFF00FF, %edx orl %ecx, %ecx jz noinc incl %ecx noinc: subl %edx, %eax imull %ecx, %eax shrl $8, %eax addl %ebx, %eax andl $0xFF00, %ebx andl $0xFF00, %esi subl %ebx, %esi imull %ecx, %esi shrl $8, %esi addl %ebx, %esi andl $0xFF00FF, %eax andl $0xFF00, %esi orl %esi, %eax popl %ebx popl %ecx popl %esi movl %ebp, %esp popl %ebp ret /* end of _blender_trans24() */ /* fixed fixsqrt(fixed x); * Fixed point square root routine. This code is based on the fixfloat * library by Arne Steinarson. */ FUNC(fixsqrt) pushl %ebp movl %esp, %ebp /* This routine is based upon the following idea: * sqrt (x) = sqrt (x/d) * sqrt(d) * d = 2^(2n) * sqrt (x) = sqrt (x / 2^(2n)) * 2^n * `x/2^(2n)' has to fall into the range 0..255 so that we can use the * square root lookup table. So `2n' is the number of bits `x' has to be * shifted to the left to become smaller than 256. The best way to find `2n' * is to do a reverse bit scan on `x'. This is achieved by the i386 ASM * instruction `bsr'. */ movl ARG1, %eax /* eax = `x' */ orl %eax, %eax /* check whether `x' is negative... */ jle sqrt_error_check /* jump to error-checking if x <= 0 */ movl %eax, %edx /* bit-scan is done on edx */ shrl $6, %edx xorl %ecx, %ecx /* if no bit set: default %cl = 2n = 0 */ bsrl %edx, %ecx andb $0xFE, %cl /* make result even --> %cl = 2n */ shrl %cl, %eax /* shift x to fall into range 0..255 */ /* table lookup... */ movzwl GLOBL(_sqrt_table)(,%eax,2), %eax shrb $1, %cl /* %cl = n */ shll %cl, %eax /* multiply `sqrt(x/2^(2n))' by `2^n' */ shrl $4, %eax /* adjust the result */ jmp sqrt_done _align_ sqrt_error_check: /* here we go if x<=0 */ jz sqrt_done /* if zero, return eax=0 */ movl GLOBL(allegro_errno), %edx movl $ERANGE, (%edx) /* on overflow, set errno */ xorl %eax, %eax /* return zero */ _align_ sqrt_done: movl %ebp, %esp popl %ebp ret /* end of fixsqrt() */ /* fixed fixhypot(fixed x, fixed y); * Return fixed point sqrt (x*x+y*y), which is the length of the * hypotenuse of a right triangle with sides of length x and y, or the * distance of point (x|y) from the origin. This routine is faster and more * accurate than using the direct formula fixsqrt (fixmul (x,x), fixmul(y,y)). * It will also return correct results for x>=256 or y>=256 where fixmul(x) * or fixmul(y) would overflow. */ FUNC(fixhypot) pushl %ebp movl %esp, %ebp /* The idea of this routine is: * sqrt (x^2+y^2) = sqrt ((x/d)^2+(y/d)^2) * d * d = 2^n * Since `x' and `y' are fixed point numbers, they are multiplied in the * following way: * x^2 = (x*x)/2^16 * so we come to the formula: * sqrt(x^2+y^2) = sqrt((x*x + y*y)/2^(16+2n)) * 2^n * and this is almost the same problem as calculating the square root in * `fixsqrt': find `2n' so that `(x*x+y*y)/2^(16+2n)' is in the range 0..255 * so that we can use the square root lookup table. */ movl ARG1, %eax /* edx:eax = x*x */ imull %eax movl %eax, %ecx /* save edx:eax */ pushl %edx movl ARG2, %eax /* edx:eax = y*y */ imull %eax addl %ecx, %eax /* edx:eax = x*x + y*y */ popl %ecx adcl %ecx, %edx cmpl $0x3FFFFFFF, %edx /* check for overflow */ ja hypot_overflow /* And now we're doing a bit-scan on `x*x+y*y' to find out by how * many bits it needs to be shifted to fall into the range 0..255. * Since the intermediate result is 64 bit we may need two bitscans * in case that no bit is set in the upper 32 bit. */ bsrl %edx, %ecx jz hypot_part2 /* we got the bit with the first step */ incb %cl /* make cl even */ incb %cl andb $0xFE, %cl shrdl %cl, %edx, %eax /* make eax fall into range 0..255 */ shrl $24, %eax /* eax = table lookup square root */ movzwl GLOBL(_sqrt_table)(,%eax,2), %eax shrb $1, %cl /* adjust result... */ shll %cl, %eax jmp hypot_done /* we didn't get the bit with the first step -- so we make another * scan on the remaining bits in `eax' to get `2n'. */ _align_ hypot_part2: shrl $16, %eax /* eax = (x*x+y*y)/2^16 */ movl %eax, %edx /* edx is used for scanning */ shrl $6, %edx xorl %ecx, %ecx /* default `2n' if no bit is set */ bsrl %edx, %ecx andb $0xFE, %cl /* make cl=2n even */ shrl %cl, %eax /* make eax fall into range 0..255 */ /* eax = table lookup square root */ movzwl GLOBL(_sqrt_table)(,%eax,2), %eax shrb $1, %cl /* cl = n */ shll %cl, %eax /* adjust result... */ shrl $4, %eax jmp hypot_done _align_ hypot_overflow: /* overflow */ movl GLOBL(allegro_errno), %eax movl $ERANGE, (%eax) /* set errno */ movl $0x7FFFFFFF, %eax /* and return MAXINT */ _align_ hypot_done: movl %ebp, %esp popl %ebp ret /* end of fixhypot() */ allegro-4.4.3.1/src/i386/iblit8.s0000664000175000017500000007424713437077643015155 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color bitmap blitting (written for speed, not readability :-) * * By Shawn Hargreaves. * * Stefan Schimanski optimised the reverse blitting function. * * MMX clear code by Robert Ohannessian. * * See readme.txt for copyright information. */ #include "asmdefs.inc" #include "blit.inc" #ifdef ALLEGRO_COLOR8 .text /* void _linear_clear_to_color8(BITMAP *bitmap, int color); * Fills a linear bitmap with the specified color. */ FUNC(_linear_clear_to_color8) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx movl ARG1, %edx /* edx = bmp */ pushl %es movl BMP_SEG(%edx), %eax /* select segment */ movl %eax, %es movl BMP_CT(%edx), %ebx /* line to start at */ movl BMP_CR(%edx), %esi /* width to clear */ subl BMP_CL(%edx), %esi #ifdef ALLEGRO_MMX /* only use MMX if compiler supports it */ movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz clear_no_mmx movl %esi, %eax /* if less than 32 pixels, use non-MMX */ shrl $5, %eax orl %eax, %eax jz clear_no_mmx movb ARG2, %al /* duplicate color 4 times */ movb %al, %ah shll $16, %eax movb ARG2, %al movb %al, %ah pushl %eax movl %ds, %eax movl %es, %ecx cmpw %ax, %cx /* can we use nearptr ? */ jne clearMMXseg_loop /* if not, then we have to decode segments...*/ /* else, we save one cycle per 8 pixels on PMMX/K6 */ _align_ clearMMX_loop: movl %ebx, %eax WRITE_BANK() /* select bank */ movl %eax, %edi addl BMP_CL(%edx), %edi /* get line address */ popl %eax /* get eax back */ movl %esi, %ecx /* width to clear */ movd %eax, %mm0 /* restore mmx reg 0 in case it's been clobbered by WRITE_BANK() */ movd %eax, %mm1 psllq $32, %mm0 por %mm1, %mm0 pushl %eax /* save eax */ testl $7, %edi /* is destination aligned on 64-bit ? */ jz clearMMX_aligned clearMMX_do_alignment: movl %edi, %eax /* we want to adjust %ecx (pairing: see andl) */ movq %mm0, (%edi) /* we clear 8 pixels */ andl $7, %eax /* we calc how may pixels we actually wanted to clear (8 - %eax) (see subl) */ andl $0xFFFFFFF8, %edi /* instruction pairing (see inc %edi) */ subl $8, %eax addl $8, %edi /* we set %edi to the next aligned memory address */ addl %eax, %ecx /* and adjust %ecx to reflect the change */ clearMMX_aligned: movl %ecx, %eax /* save for later */ shrl $5, %ecx /* divide by 32 for 4 * 8-byte memory move */ jz clearMMX_finish_line /* if there's less than 32 pixels to clear, no need for MMX */ clearMMX_continue_line: movq %mm0, (%edi) /* move 4x 8 bytes */ movq %mm0, 8(%edi) /* MMX instructions can't pair when both write to memory */ movq %mm0, 16(%edi) movq %mm0, 24(%edi) addl $32, %edi /* inserting those in the MMX copy block makes no diffrence */ decl %ecx jnz clearMMX_continue_line clearMMX_finish_line: movl %eax, %ecx /* get ecx back */ testl $31, %ecx /* check if there's any left */ jz clearMMX_no_long /* else, write trailing pixels */ testl $16, %ecx jz clearMMX_finish_line2 movq %mm0, (%edi) movq %mm0, 8(%edi) addl $16, %edi clearMMX_finish_line2: testl $8, %ecx jz clearMMX_finish_line3 movq %mm0, (%edi) addl $8, %edi clearMMX_finish_line3: andl $7, %ecx subl $8, %ecx movq %mm0, (%edi, %ecx) clearMMX_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clearMMX_loop /* and loop */ popl %eax emms /* clear FPU tag word */ jmp clear_done clearMMXseg_loop: movl %ebx, %eax WRITE_BANK() /* select bank */ movl %eax, %edi addl BMP_CL(%edx), %edi /* get line address */ popl %eax /* Get eax back */ movl %esi, %ecx /* width to clear */ movd %eax, %mm0 /* restore mmx reg 0 in case it's been clobbered by WRITE_BANK() */ movd %eax, %mm1 psllq $32, %mm0 por %mm1, %mm0 pushl %eax /* save eax */ testl $7, %edi /* is destination aligned on 64-bit ? */ jz clearMMXseg_aligned clearMMXseg_do_alignment: movl %edi, %eax /* we want to adjust %ecx (pairing: see andl) */ movq %mm0, %es:(%edi) /* we clear 8 pixels */ andl $7, %eax /* we calc how may pixels we actually wanted to clear (8 - %eax) (see subl) */ andl $0xFFFFFFF8, %edi /* instruction pairing (see inc %edi) */ subl $8, %eax addl $8, %edi /* we set %edi to the next aligned memory address */ addl %eax, %ecx /* and adjust %ecx to reflect the change */ clearMMXseg_aligned: movl %ecx, %eax /* save for later */ shrl $5, %ecx /* divide by 32 for 4 * 8-byte memory move */ jz clearMMXseg_finish_line /* if there's less than 32 pixels to clear, no need for MMX */ clearMMXseg_continue_line: movq %mm0, %es:(%edi) /* move 4x 8 bytes */ movq %mm0, %es:8(%edi) /* MMX instructions can't pair when both write to memory */ movq %mm0, %es:16(%edi) movq %mm0, %es:24(%edi) addl $32, %edi /* inserting those in the MMX copy block makes no diffrence */ decl %ecx jnz clearMMXseg_continue_line clearMMXseg_finish_line: movl %eax, %ecx /* get ecx back */ testl $31, %ecx /* check if there's any left */ jz clearMMXseg_no_long /* else, write trailing pixels */ testl $16, %ecx jz clearMMXseg_finish_line2 movq %mm0, %es:(%edi) movq %mm0, %es:8(%edi) addl $16, %edi clearMMXseg_finish_line2: testl $8, %ecx jz clearMMXseg_finish_line3 movq %mm0, %es:(%edi) addl $8, %edi clearMMXseg_finish_line3: andl $7, %ecx subl $8, %ecx movq %mm0, %es:(%edi, %ecx) clearMMXseg_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clearMMXseg_loop /* and loop */ popl %eax emms /* clear FPU tag word */ jmp clear_done #endif /* ALLEGRO_MMX */ clear_no_mmx: cld _align_ clear_loop: movl %ebx, %eax WRITE_BANK() /* select bank */ movl %eax, %edi addl BMP_CL(%edx), %edi /* get line address */ movb ARG2, %al /* duplicate color 4 times */ movb %al, %ah shll $16, %eax movb ARG2, %al movb %al, %ah movl %esi, %ecx /* width to clear */ shrl $1, %ecx /* halve for 16 bit clear */ jnc clear_no_byte stosb /* clear an odd byte */ clear_no_byte: shrl $1, %ecx /* halve again for 32 bit clear */ jnc clear_no_word stosw /* clear an odd word */ clear_no_word: jz clear_no_long _align_ clear_x_loop: rep ; stosl /* clear the line */ clear_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clear_loop /* and loop */ clear_done: popl %es UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_clear_to_color8() */ /* void _linear_blit8(BITMAP *source, BITMAP *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Normal forwards blitting routine for linear bitmaps. */ FUNC(_linear_blit8) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es cld /* for forward copy */ shrl $1, B_WIDTH /* halve counter for word copies */ jz blit_only_one_byte jnc blit_even_bytes _align_ BLIT_LOOP(words_and_byte, 1, /* word at a time, plus leftover byte */ rep ; movsw ; movsb ) jmp blit_done _align_ blit_even_bytes: shrl $1, B_WIDTH /* halve counter again, for long copies */ jz blit_only_one_word jnc blit_even_words _align_ BLIT_LOOP(longs_and_word, 1, /* long at a time, plus leftover word */ rep ; movsl ; movsw ) jmp blit_done _align_ blit_even_words: BLIT_LOOP(even_words, 1, /* copy a long at a time */ rep ; movsl ; ) jmp blit_done _align_ blit_only_one_byte: BLIT_LOOP(only_one_byte, 1, /* copy just the one byte */ movsb ) jmp blit_done _align_ blit_only_one_word: BLIT_LOOP(only_one_word, 1, /* copy just the one word */ movsw ) _align_ blit_done: popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit8() */ /* void _linear_blit_backward8(BITMAP *source, BITMAP *dest, int source_x, * int source_y, int dest_x, dest_y, int width, height); * Reverse blitting routine, for overlapping linear bitmaps. */ FUNC(_linear_blit_backward8) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_HEIGHT, %eax /* y values go from high to low */ decl %eax addl %eax, B_SOURCE_Y addl %eax, B_DEST_Y movl B_WIDTH, %eax /* x values go from high to low */ decl %eax addl %eax, B_SOURCE_X addl %eax, B_DEST_X movl B_DEST, %edx movl %ds, %ebx /* save data segment selector */ movl BMP_SEG(%edx), %eax /* load destination segment */ movl %eax, %es movl B_SOURCE_Y, %eax /* if different line -> fast dword blit */ cmpl B_DEST_Y, %eax jne blit_backwards_loop_fast movl B_SOURCE_X, %eax /* B_SOURCE_X-B_DEST_X */ subl B_DEST_X, %eax cmpl $3, %eax /* if greater than 3 -> fast dword blit */ jg blit_backwards_loop_fast _align_ blit_backwards_loop_slow: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi std /* backwards */ movl B_WIDTH, %ecx /* x loop counter */ movl BMP_SEG(%edx), %eax /* load data segment */ movl %eax, %ds rep ; movsb /* copy the line */ movl %ebx, %ds /* restore data segment */ decl B_SOURCE_Y decl B_DEST_Y decl B_HEIGHT jg blit_backwards_loop_slow /* and loop */ jmp blit_backwards_end _align_ blit_backwards_loop_fast: movl B_DEST, %edx /* destination bitmap */ movl B_DEST_Y, %eax /* line number */ movl B_DEST_X, %edi /* x offset */ WRITE_BANK() /* select bank */ addl %eax, %edi movl B_SOURCE, %edx /* source bitmap */ movl B_SOURCE_Y, %eax /* line number */ movl B_SOURCE_X, %esi /* x offset */ READ_BANK() /* select bank */ addl %eax, %esi std /* backwards */ movl B_WIDTH, %eax /* x loop counter */ movl BMP_SEG(%edx), %edx /* load data segment */ movl %edx, %ds movl %eax, %ecx andl $3, %ecx /* copy bytes */ rep ; movsb /* copy the line */ subl $3, %esi subl $3, %edi movl %eax, %ecx shrl $2, %ecx /* copy dwords */ rep ; movsl /* copy the line */ movl %ebx, %ds /* restore data segment */ decl B_SOURCE_Y decl B_DEST_Y decl B_HEIGHT jg blit_backwards_loop_fast /* and loop */ blit_backwards_end: cld /* finished */ popl %es movl B_SOURCE, %edx UNREAD_BANK() movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_blit_backward8() */ FUNC(_linear_blit8_end) ret /* void _linear_masked_blit8(BITMAP *source, *dest, int source_x, source_y, * int dest_x, dest_y, int width, height); * Masked (skipping zero pixels) blitting routine for linear bitmaps. */ FUNC(_linear_masked_blit8) pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %ebx pushl %es movl B_DEST, %edx movl %ds, %ebx movl BMP_SEG(%edx), %eax movl %eax, %es cld #ifdef ALLEGRO_SSE /* Use SSE if the compiler supports it */ /* Speed improvement on the Pentium 3 only, so we need to check for MMX+ and no 3DNow! */ movl GLOBL(cpu_capabilities), %ecx /* if MMX+ is enabled (or not disabled :) */ andl $CPU_MMXPLUS | $CPU_3DNOW, %ecx cmpl $CPU_MMXPLUS, %ecx jne masked8_no_mmx movl B_WIDTH, %ecx shrl $4, %ecx /* Are there more than 16 pixels? Otherwise, use non-MMX code */ jz masked8_no_mmx pxor %mm0, %mm0 pcmpeqd %mm4, %mm4 /* Create inverter mask */ /* Note: maskmovq is an SSE instruction! */ #define BLIT_CODE \ movd %ecx, %mm2; /* Save line length (%mm2) */ \ shrl $4, %ecx; \ \ pushl %es; /* Swap ES and DS */ \ pushl %ds; \ popl %es; \ popl %ds; \ \ _align_; \ masked8_mmx_x_loop: \ \ movq %es:(%esi), %mm1; /* Read 8 pixels */ \ movq %mm0, %mm3; \ movq %es:8(%esi), %mm5; /* Read 8 more pixels */ \ movq %mm0, %mm6; \ \ pcmpeqb %mm1, %mm3; /* Compare with mask (%mm3/%mm6) */ \ pcmpeqb %mm5, %mm6; \ pxor %mm4, %mm3; /* Turn 1->0 and 0->1 */ \ pxor %mm4, %mm6; \ addl $16, %esi; /* Update src */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ addl $8, %edi; \ maskmovq %mm6, %mm5; \ \ addl $8, %edi; /* Update dest */ \ \ decl %ecx; /* Any pixel packs left for this line? */ \ jnz masked8_mmx_x_loop; \ \ movd %mm2, %ecx; /* Restore pixel count */ \ andl $15, %ecx; \ jz masked8_mmx_loop_end; /* Nothing else to do? */ \ shrl $1, %ecx; /* 1 pixels left */ \ jnc masked8_mmx_word; \ \ movb %es:(%esi), %al; /* Read 1 pixel */ \ incl %esi; \ incl %edi; \ orb %al, %al; /* Compare with mask */ \ jz masked8_mmx_word; \ movb %al, -1(%edi); /* Write the pixel */ \ \ masked8_mmx_word: \ shrl $1, %ecx; /* 2 pixels left */ \ jnc masked8_mmx_long; \ \ movb %es:(%esi), %al; /* Read 2 pixels */ \ movb %es:1(%esi), %ah; \ addl $2, %esi; \ addl $2, %edi; \ orb %al, %al; \ jz masked8_mmx_word_2; \ movb %al, -2(%edi); /* Write pixel */ \ \ masked8_mmx_word_2: \ orb %ah, %ah; \ jz masked8_mmx_long; \ movb %ah, -1(%edi); /* Write other pixel */ \ \ _align_; \ masked8_mmx_long: \ \ shrl $1, %ecx; /* 4 pixels left */ \ jnc masked8_mmx_qword; \ \ movl %es:(%esi), %eax; /* Read 4 pixels */ \ addl $4, %esi; \ movd %eax, %mm1; \ movl $-1, %eax; \ movq %mm0, %mm3; \ movd %eax, %mm5; /* Build XOR flag */ \ \ pcmpeqb %mm1, %mm3; /* Compare with mask (%mm3/%mm6) */ \ pxor %mm5, %mm3; /* Turn 1->0 and 0->1 */ \ pand %mm5, %mm3; /* Make sure only the bottom 32 bits are used */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ addl $4, %edi; \ \ _align_; \ masked8_mmx_qword: \ shrl $1, %ecx; /* 8 pixels left */ \ jnc masked8_mmx_loop_end; \ \ movq %es:(%esi), %mm1; /* Read 8 more pixels */ \ movq %mm0, %mm3; \ \ pcmpeqw %mm1, %mm3; /* Compare with mask (%mm3) */ \ pxor %mm4, %mm3; /* Turn 1->0 and 0->1 */ \ maskmovq %mm3, %mm1; /* Write if not equal to mask. */ \ \ _align_; \ masked8_mmx_loop_end: \ \ pushl %ds; /* Swap back ES and DS */ \ popl %es; BLIT_LOOP(masked8_mmx_loop, 1, BLIT_CODE) #undef BLIT_CODE emms jmp masked8_end; #endif _align_ masked8_no_mmx: #define BLIT_CODE \ test $1, %ecx ; /* 16 bit aligned->use new code */ \ jz masked16_blit ; /* width 16 bit aligned */ \ movb (%esi), %al ; /* read a byte */ \ incl %esi ; \ orb %al, %al ; /* test it */ \ jz masked8_skip ; \ movb %al, %es:(%edi) ; /* write the pixel */ \ masked8_skip: \ incl %edi ; \ decl %ecx ; \ jng masked16_blit_end ; \ \ masked16_blit: \ test $3, %ecx ; /* 32 bit aligned->use new code */ \ jz masked16_blit_x_loop ; /* width 32 bit aligned */ \ movw (%esi), %ax ; /* read two pixels */ \ orw %ax, %ax ; \ jz masked16_blit_end2 ; \ orb %al,%al ; \ jz masked16_blit_wskip1 ; \ orb %ah,%ah ; \ jz masked16_blit_p1wskip2 ; \ movw %ax, %es:(%edi) ; /* write the pixel */ \ jmp masked16_blit_end2 ; \ _align_ ; \ masked16_blit_p1wskip2: \ movb %al, %es:(%edi) ; /* write the pixel */ \ jmp masked16_blit_end2 ; \ _align_ ; \ masked16_blit_wskip1: \ movb %ah, %es:1(%edi) ; /* write the pixel */ \ _align_ ; \ masked16_blit_end2: \ subl $2, %ecx ; \ jng masked16_blit_end ; \ addl $2, %esi ; \ addl $2, %edi ; \ \ _align_ ; \ masked16_blit_x_loop: \ movl (%esi), %eax ; /* read four pixels */ \ addl $4, %esi ; \ movl %eax, %edx ; \ shrl $16,%edx ; \ orl %eax, %eax ; \ jz masked16_blit_skip4 ; \ orw %ax, %ax ; \ jz masked16_blit_skip2 ; \ orb %al,%al ; \ jz masked16_blit_skip1 ; \ orb %ah, %ah ; \ jz masked16_put1skip2 ; \ orb %dl,%dl ; \ jz masked16_put12_skip3 ; \ orb %dh,%dh ; \ jz masked16_put123_skip4 ; \ movl %eax, %es:(%edi) ; /* write the pixel */ \ jmp masked16_blit_skip4 ; \ \ _align_ ; \ masked16_put1skip2: \ movb %al, %es:(%edi) ; /* write the pixel */ \ jmp masked16_blit_skip2 ; \ _align_ ; \ masked16_put12_skip3: \ movw %ax, %es:(%edi) ; /* write the pixel */ \ orb %dh, %dh ; \ jnz masked16_blit_skip3 ; \ jmp masked16_blit_skip4 ; \ _align_ ; \ masked16_put123_skip4: \ movw %ax, %es:(%edi) ; /* write the pixel */ \ movb %dl, %es:2(%edi) ; /* write the pixel */ \ addl $4, %edi ; \ subl $4, %ecx ; \ jg masked16_blit_x_loop ; \ jmp masked16_blit_end ; \ \ masked16_blit_skip1: \ movb %ah, %es:1(%edi) ; /* write the pixel */ \ masked16_blit_skip2: \ orw %dx, %dx ; \ jz masked16_blit_skip4 ; \ orb %dl,%dl ; \ jz masked16_blit_skip3 ; \ orb %dh, %dh ; \ jz masked16_put3skip4 ; \ movw %dx, %es:2(%edi) ; /* write the pixel */ \ jmp masked16_blit_skip4 ; \ \ _align_ ; \ masked16_put3skip4: \ movb %dl, %es:2(%edi) ; /* write the pixel */ \ addl $4, %edi ; \ subl $4, %ecx ; \ jg masked16_blit_x_loop ; \ jmp masked16_blit_end ; \ \ masked16_blit_skip3: \ movb %dh, %es:3(%edi) ; /* write the pixel */ \ masked16_blit_skip4: \ addl $4, %edi ; \ subl $4, %ecx ; \ jg masked16_blit_x_loop ; \ masked16_blit_end: BLIT_LOOP(masked16, 1, BLIT_CODE) #undef BLIT_CODE masked8_end: popl %es /* the source must be a memory bitmap, no need for * movl B_SOURCE, %edx * UNREAD_BANK() */ movl B_DEST, %edx UNWRITE_BANK() popl %ebx popl %esi popl %edi movl %ebp, %esp popl %ebp ret /* end of _linear_masked_blit8() */ #endif /* ifdef ALLEGRO_COLOR8 */ allegro-4.4.3.1/src/readsmp.c0000664000175000017500000001145413437077643014673 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Top level sample type registration routines. * * By Vincent Penquerc'h. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" typedef struct SAMPLE_TYPE_INFO { char *ext; SAMPLE *(*load)(AL_CONST char *filename); int (*save)(AL_CONST char *filename, SAMPLE *smp); struct SAMPLE_TYPE_INFO *next; } SAMPLE_TYPE_INFO; static SAMPLE_TYPE_INFO *sample_type_list = NULL; /* register_sample_file_type: * Informs Allegro of a new sample file type, telling it how to load and * save files of this format (either function may be NULL). */ void register_sample_file_type(AL_CONST char *ext, SAMPLE *(*load)(AL_CONST char *filename), int (*save)(AL_CONST char *filename, SAMPLE *smp)) { char tmp[32], *aext; SAMPLE_TYPE_INFO *iter = sample_type_list; ASSERT(ext); aext = uconvert_toascii(ext, tmp); if (strlen(aext) == 0) return; if (!iter) iter = sample_type_list = _AL_MALLOC(sizeof(struct SAMPLE_TYPE_INFO)); else { for (iter = sample_type_list; iter->next; iter = iter->next); iter = iter->next = _AL_MALLOC(sizeof(struct SAMPLE_TYPE_INFO)); } if (iter) { iter->load = load; iter->save = save; iter->ext = _al_strdup(aext); iter->next = NULL; } } /* load_sample: * Loads a sample from disk. */ SAMPLE *load_sample(AL_CONST char *filename) { char tmp[32], *aext; SAMPLE_TYPE_INFO *iter; ASSERT(filename); aext = uconvert_toascii(get_extension(filename), tmp); for (iter = sample_type_list; iter; iter = iter->next) { if (stricmp(iter->ext, aext) == 0) { if (iter->load) return iter->load(filename); return NULL; } } return NULL; } /* save_sample: * Writes a sample to disk. */ int save_sample(AL_CONST char *filename, SAMPLE *smp) { char tmp[32], *aext; SAMPLE_TYPE_INFO *iter; ASSERT(filename); ASSERT(smp); aext = uconvert_toascii(get_extension(filename), tmp); for (iter = sample_type_list; iter; iter = iter->next) { if (stricmp(iter->ext, aext) == 0) { if (iter->save) return iter->save(filename, smp); return 1; } } return 1; } /* register_sample_file_type_exit: * Free list of registered sample file types. */ static void register_sample_file_type_exit(void) { SAMPLE_TYPE_INFO *iter = sample_type_list, *next; while (iter) { next = iter->next; _AL_FREE(iter->ext); _AL_FREE(iter); iter = next; } sample_type_list = NULL; /* If we are using a destructor, then we only want to prune the list * down to valid modules. So we clean up as usual, but then reinstall * the internal modules. */ #ifdef ALLEGRO_USE_CONSTRUCTOR _register_sample_file_type_init(); #endif _remove_exit_func(register_sample_file_type_exit); } /* _register_sample_file_type_init: * Register built-in sample file types. */ void _register_sample_file_type_init(void) { char buf[32]; _add_exit_func(register_sample_file_type_exit, "register_sample_file_type_exit"); register_sample_file_type(uconvert_ascii("wav", buf), load_wav, NULL); register_sample_file_type(uconvert_ascii("voc", buf), load_voc, NULL); } #ifdef ALLEGRO_USE_CONSTRUCTOR CONSTRUCTOR_FUNCTION(static void sample_filetype_constructor(void)); DESTRUCTOR_FUNCTION(static void sample_filetype_destructor(void)); /* sample_filetype_constructor: * Register sample filetype functions if this object file is linked * in. This isn't called if the load_sample() and save_sample() * functions aren't used in a program, thus saving a little space * in statically linked programs. */ static void sample_filetype_constructor(void) { _register_sample_file_type_init(); } /* sample_filetype_destructor: * Since we only want to destroy the whole list when we *actually* * quit, not just when allegro_exit() is called, we need to use a * destructor to accomplish this. */ static void sample_filetype_destructor(void) { SAMPLE_TYPE_INFO *iter = sample_type_list, *next; while (iter) { next = iter->next; _AL_FREE(iter->ext); _AL_FREE(iter); iter = next; } sample_type_list = NULL; _remove_exit_func(register_sample_file_type_exit); } #endif allegro-4.4.3.1/src/gfx.c0000664000175000017500000010652313437077643014026 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Graphics routines: palette fading, circles, etc. * * By Shawn Hargreaves. * * Optimised line drawer by Michael Bukin. * * Bresenham arc routine by Romano Signorelli. * * Cohen-Sutherland line clipping by Jon Rafkind. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* drawing_mode: * Sets the drawing mode. This only affects routines like putpixel, * lines, rectangles, triangles, etc, not the blitting or sprite * drawing functions. */ void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor) { _drawing_mode = mode; _drawing_pattern = pattern; _drawing_x_anchor = x_anchor; _drawing_y_anchor = y_anchor; if (pattern) { _drawing_x_mask = 1; while (_drawing_x_mask < (unsigned)pattern->w) _drawing_x_mask <<= 1; /* find power of two greater than w */ if (_drawing_x_mask > (unsigned)pattern->w) { ASSERT(FALSE); _drawing_x_mask >>= 1; /* round down if required */ } _drawing_x_mask--; /* convert to AND mask */ _drawing_y_mask = 1; while (_drawing_y_mask < (unsigned)pattern->h) _drawing_y_mask <<= 1; /* find power of two greater than h */ if (_drawing_y_mask > (unsigned)pattern->h) { ASSERT(FALSE); _drawing_y_mask >>= 1; /* round down if required */ } _drawing_y_mask--; /* convert to AND mask */ } else _drawing_x_mask = _drawing_y_mask = 0; if ((gfx_driver) && (gfx_driver->drawing_mode) && (!_dispsw_status)) gfx_driver->drawing_mode(); } /* set_blender_mode: * Specifies a custom set of blender functions for interpolating between * truecolor pixels. The 24 bit blender is shared between the 24 and 32 bit * modes. Pass a NULL table for unused color depths (you must not draw * translucent graphics in modes without a handler, though!). Your blender * will be passed two 32 bit colors in the appropriate format (5.5.5, 5.6.5, * or 8.8.8), and an alpha value, should return the result of combining them. * In translucent drawing modes, the two colors are taken from the source * and destination images and the alpha is specified by this function. In * lit modes, the alpha is specified when you call the drawing routine, and * the interpolation is between the source color and the RGB values you pass * to this function. */ void set_blender_mode(BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, int r, int g, int b, int a) { _blender_func15 = b15; _blender_func16 = b16; _blender_func24 = b24; _blender_func32 = b24; _blender_func15x = _blender_black; _blender_func16x = _blender_black; _blender_func24x = _blender_black; _blender_col_15 = makecol15(r, g, b); _blender_col_16 = makecol16(r, g, b); _blender_col_24 = makecol24(r, g, b); _blender_col_32 = makecol32(r, g, b); _blender_alpha = a; } /* set_blender_mode_ex * Specifies a custom set of blender functions for interpolating between * truecolor pixels, providing a more complete set of routines, which * differentiate between 24 and 32 bit modes, and have special routines * for blending 32 bit RGBA pixels onto a destination of any format. */ void set_blender_mode_ex(BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, BLENDER_FUNC b32, BLENDER_FUNC b15x, BLENDER_FUNC b16x, BLENDER_FUNC b24x, int r, int g, int b, int a) { _blender_func15 = b15; _blender_func16 = b16; _blender_func24 = b24; _blender_func32 = b32; _blender_func15x = b15x; _blender_func16x = b16x; _blender_func24x = b24x; _blender_col_15 = makecol15(r, g, b); _blender_col_16 = makecol16(r, g, b); _blender_col_24 = makecol24(r, g, b); _blender_col_32 = makecol32(r, g, b); _blender_alpha = a; } /* xor_mode: * Shortcut function for toggling XOR mode on and off. */ void xor_mode(int on) { drawing_mode(on ? DRAW_MODE_XOR : DRAW_MODE_SOLID, NULL, 0, 0); } /* solid_mode: * Shortcut function for selecting solid drawing mode. */ void solid_mode(void) { drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); } /* clear_bitmap: * Clears the bitmap to color 0. */ void clear_bitmap(BITMAP *bitmap) { clear_to_color(bitmap, 0); } /* _bitmap_has_alpha: * Checks whether this bitmap has an alpha channel. */ int _bitmap_has_alpha(BITMAP *bmp) { int x, y, c; if (bitmap_color_depth(bmp) != 32) return FALSE; for (y = 0; y < bmp->h; y++) { for (x = 0; x < bmp->w; x++) { c = getpixel(bmp, x, y); if (geta32(c)) return TRUE; } } return FALSE; } /* vsync: * Waits for a retrace. */ void vsync(void) { ASSERT(gfx_driver); if (!_dispsw_status && gfx_driver->vsync) gfx_driver->vsync(); } /* set_color: * Sets a single palette entry. */ void set_color(int index, AL_CONST RGB *p) { ASSERT(index >= 0 && index < PAL_SIZE); set_palette_range((struct RGB *)p-index, index, index, FALSE); } /* set_palette: * Sets the entire color palette. */ void set_palette(AL_CONST PALETTE p) { set_palette_range(p, 0, PAL_SIZE-1, TRUE); } /* set_palette_range: * Sets a part of the color palette. */ void set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) { int c; ASSERT(from >= 0 && from < PAL_SIZE); ASSERT(to >= 0 && to < PAL_SIZE) for (c=from; c<=to; c++) { _current_palette[c] = p[c]; if (_color_depth != 8) palette_color[c] = makecol(_rgb_scale_6[p[c].r], _rgb_scale_6[p[c].g], _rgb_scale_6[p[c].b]); } _current_palette_changed = 0xFFFFFFFF & ~(1<<(_color_depth-1)); if (gfx_driver) { if ((screen->vtable->color_depth == 8) && (!_dispsw_status)) gfx_driver->set_palette(p, from, to, vsync); } else if ((system_driver) && (system_driver->set_palette_range)) system_driver->set_palette_range(p, from, to, vsync); } /* previous palette, so the image loaders can restore it when they are done */ int _got_prev_current_palette = FALSE; PALETTE _prev_current_palette; static int prev_palette_color[PAL_SIZE]; /* select_palette: * Sets the aspects of the palette tables that are used for converting * between different image formats, without altering the display settings. * The previous settings are copied onto a one-deep stack, from where they * can be restored by calling unselect_palette(). */ void select_palette(AL_CONST PALETTE p) { int c; for (c=0; ctruecolor. */ static int *palette_expansion_table(int bpp) { int *table; int c; switch (bpp) { case 15: table = _palette_color15; break; case 16: table = _palette_color16; break; case 24: table = _palette_color24; break; case 32: table = _palette_color32; break; default: ASSERT(FALSE); return NULL; } if (_current_palette_changed & (1<<(bpp-1))) { for (c=0; c>5)&7) * 63/7; pal[c].g = ((c>>2)&7) * 63/7; pal[c].b = (c&3) * 63/3; } pal[0].r = 63; pal[0].g = 0; pal[0].b = 63; pal[254].r = pal[254].g = pal[254].b = 0; } /* get_color: * Retrieves a single color from the palette. */ void get_color(int index, RGB *p) { ASSERT(index >= 0 && index < PAL_SIZE); ASSERT(p); get_palette_range(p-index, index, index); } /* get_palette: * Retrieves the entire color palette. */ void get_palette(PALETTE p) { get_palette_range(p, 0, PAL_SIZE-1); } /* get_palette_range: * Retrieves a part of the color palette. */ void get_palette_range(PALETTE p, int from, int to) { int c; ASSERT(from >= 0 && from < PAL_SIZE); ASSERT(to >= 0 && to < PAL_SIZE); if ((system_driver) && (system_driver->read_hardware_palette)) system_driver->read_hardware_palette(); for (c=from; c<=to; c++) p[c] = _current_palette[c]; } /* fade_interpolate: * Calculates a palette part way between source and dest, returning it * in output. The pos indicates how far between the two extremes it should * be: 0 = return source, 64 = return dest, 32 = return exactly half way. * Only affects colors between from and to (inclusive). */ void fade_interpolate(AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to) { int c; ASSERT(pos >= 0 && pos <= 64); ASSERT(from >= 0 && from < PAL_SIZE); ASSERT(to >= 0 && to < PAL_SIZE); for (c=from; c<=to; c++) { output[c].r = ((int)source[c].r * (63-pos) + (int)dest[c].r * pos) / 64; output[c].g = ((int)source[c].g * (63-pos) + (int)dest[c].g * pos) / 64; output[c].b = ((int)source[c].b * (63-pos) + (int)dest[c].b * pos) / 64; } } /* fade_from_range: * Fades from source to dest, at the specified speed (1 is the slowest, 64 * is instantaneous). Only affects colors between from and to (inclusive, * pass 0 and 255 to fade the entire palette). */ void fade_from_range(AL_CONST PALETTE source, AL_CONST PALETTE dest, int speed, int from, int to) { PALETTE temp; int c, start, last; ASSERT(speed > 0 && speed <= 64); ASSERT(from >= 0 && from < PAL_SIZE); ASSERT(to >= 0 && to < PAL_SIZE); for (c=0; c 0 && speed <= 64); ASSERT(from >= 0 && from < PAL_SIZE); ASSERT(to >= 0 && to < PAL_SIZE); fade_from_range(black_palette, p, speed, from, to); } /* fade_out_range: * Fades from the current palette to a solid black palette, at the * specified speed (1 is the slowest, 64 is instantaneous). Only affects * colors between from and to (inclusive, pass 0 and 255 to fade the * entire palette). */ void fade_out_range(int speed, int from, int to) { PALETTE temp; ASSERT(speed > 0 && speed <= 64); ASSERT(from >= 0 && from < PAL_SIZE); ASSERT(to >= 0 && to < PAL_SIZE); get_palette(temp); fade_from_range(temp, black_palette, speed, from, to); } /* fade_from: * Fades from source to dest, at the specified speed (1 is the slowest, 64 * is instantaneous). */ void fade_from(AL_CONST PALETTE source, AL_CONST PALETTE dest, int speed) { ASSERT(speed > 0 && speed <= 64); fade_from_range(source, dest, speed, 0, PAL_SIZE-1); } /* fade_in: * Fades from a solid black palette to p, at the specified speed (1 is * the slowest, 64 is instantaneous). */ void fade_in(AL_CONST PALETTE p, int speed) { ASSERT(speed > 0 && speed <= 64); fade_in_range(p, speed, 0, PAL_SIZE-1); } /* fade_out: * Fades from the current palette to a solid black palette, at the * specified speed (1 is the slowest, 64 is instantaneous). */ void fade_out(int speed) { ASSERT(speed > 0 && speed <= 64); fade_out_range(speed, 0, PAL_SIZE-1); } /* rect: * Draws an outline rectangle. */ void _soft_rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { int t; if (x2 < x1) { t = x1; x1 = x2; x2 = t; } if (y2 < y1) { t = y1; y1 = y2; y2 = t; } acquire_bitmap(bmp); hline(bmp, x1, y1, x2, color); if (y2 > y1) hline(bmp, x1, y2, x2, color); if (y2-1 >= y1+1) { vline(bmp, x1, y1+1, y2-1, color); if (x2 > x1) vline(bmp, x2, y1+1, y2-1, color); } release_bitmap(bmp); } /* _normal_rectfill: * Draws a solid filled rectangle, using hfill() to do the work. */ void _normal_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { int t; if (y1 > y2) { t = y1; y1 = y2; y2 = t; } if (bmp->clip) { if (x1 > x2) { t = x1; x1 = x2; x2 = t; } if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; bmp->clip = FALSE; t = TRUE; } else t = FALSE; acquire_bitmap(bmp); while (y1 <= y2) { bmp->vtable->hfill(bmp, x1, y1, x2, color); y1++; }; release_bitmap(bmp); bmp->clip = t; } /* do_line: * Calculates all the points along a line between x1, y1 and x2, y2, * calling the supplied function for each one. This will be passed a * copy of the bmp parameter, the x and y position, and a copy of the * d parameter (so do_line() can be used with putpixel()). */ void do_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int d, void (*proc)(BITMAP *, int, int, int)) { int dx = x2-x1; int dy = y2-y1; int i1, i2; int x, y; int dd; /* worker macro */ #define DO_LINE(pri_sign, pri_c, pri_cond, sec_sign, sec_c, sec_cond) \ { \ if (d##pri_c == 0) { \ proc(bmp, x1, y1, d); \ return; \ } \ \ i1 = 2 * d##sec_c; \ dd = i1 - (sec_sign (pri_sign d##pri_c)); \ i2 = dd - (sec_sign (pri_sign d##pri_c)); \ \ x = x1; \ y = y1; \ \ while (pri_c pri_cond pri_c##2) { \ proc(bmp, x, y, d); \ \ if (dd sec_cond 0) { \ sec_c = sec_c sec_sign 1; \ dd += i2; \ } \ else \ dd += i1; \ \ pri_c = pri_c pri_sign 1; \ } \ } if (dx >= 0) { if (dy >= 0) { if (dx >= dy) { /* (x1 <= x2) && (y1 <= y2) && (dx >= dy) */ DO_LINE(+, x, <=, +, y, >=); } else { /* (x1 <= x2) && (y1 <= y2) && (dx < dy) */ DO_LINE(+, y, <=, +, x, >=); } } else { if (dx >= -dy) { /* (x1 <= x2) && (y1 > y2) && (dx >= dy) */ DO_LINE(+, x, <=, -, y, <=); } else { /* (x1 <= x2) && (y1 > y2) && (dx < dy) */ DO_LINE(-, y, >=, +, x, >=); } } } else { if (dy >= 0) { if (-dx >= dy) { /* (x1 > x2) && (y1 <= y2) && (dx >= dy) */ DO_LINE(-, x, >=, +, y, >=); } else { /* (x1 > x2) && (y1 <= y2) && (dx < dy) */ DO_LINE(+, y, <=, -, x, <=); } } else { if (-dx >= -dy) { /* (x1 > x2) && (y1 > y2) && (dx >= dy) */ DO_LINE(-, x, >=, -, y, <=); } else { /* (x1 > x2) && (y1 > y2) && (dx < dy) */ DO_LINE(-, y, >=, -, x, <=); } } } #undef DO_LINE } /* _normal_line: * Draws a line from x1, y1 to x2, y2, using putpixel() to do the work. */ void _normal_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { int sx, sy, dx, dy, t; if (x1 == x2) { vline(bmp, x1, y1, y2, color); return; } if (y1 == y2) { hline(bmp, x1, y1, x2, color); return; } /* use a bounding box to check if the line needs clipping */ if (bmp->clip) { sx = x1; sy = y1; dx = x2; dy = y2; if (sx > dx) { t = sx; sx = dx; dx = t; } if (sy > dy) { t = sy; sy = dy; dy = t; } if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) return; if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) bmp->clip = FALSE; t = TRUE; } else t= FALSE; acquire_bitmap(bmp); do_line(bmp, x1, y1, x2, y2, color, bmp->vtable->putpixel); release_bitmap(bmp); bmp->clip = t; } /* _fast_line: * Draws a line from x1, y1 to x2, y2, using putpixel() to do the work. * This is an implementation of the Cohen-Sutherland line clipping algorithm. * Loops over the line until it can be either trivially rejected or trivially * accepted. If it is neither rejected nor accepted, subdivide it into two * segments, one of which can be rejected. */ void _fast_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { int code0, code1; int outcode; int x, y; int xmax, xmin, ymax, ymin; int done = 0, accept = 0; int clip_orig; ASSERT(bmp); if ((clip_orig = bmp->clip) != 0) { /* save clipping state */ #define TOP 0x8 #define BOTTOM 0x4 #define LEFT 0x2 #define RIGHT 0x1 #define COMPCLIP(code, x, y) \ { \ code = 0; \ if (y < ymin) \ code |= TOP; \ else if (y > ymax) \ code |= BOTTOM; \ if (x < xmin) \ code |= LEFT; \ else if (x > xmax) \ code |= RIGHT; \ } xmin = bmp->cl; xmax = bmp->cr-1; ymin = bmp->ct; ymax = bmp->cb-1; COMPCLIP(code0, x1, y1); COMPCLIP(code1, x2, y2); do { if (!(code0 | code1)) { /* Trivially accept. */ accept = done = 1; } else if (code0 & code1) { /* Trivially reject. */ done = 1; } else { /* Didn't reject or accept, so do some calculations. */ outcode = code0 ? code0 : code1; /* pick one endpoint */ if (outcode & TOP) { if (y2 == y1) x = x1; else x = x1 + (x2 - x1) * (ymin - y1) / (y2 - y1); y = ymin; } else if (outcode & BOTTOM) { if (y2 == y1) x = x1; else x = x1 + (x2 - x1) * (ymax - y1) / (y2 - y1); y = ymax; } else if (outcode & LEFT) { if (x2 == x1) y = y1; else y = y1 + (y2 - y1) * (xmin - x1) / (x2 - x1); x = xmin; } else { /* outcode & RIGHT */ if (x2 == x1) y = y1; else y = y1 + (y2 - y1) * (xmax - x1) / (x2 - x1); x = xmax; } if (outcode == code0) { x1 = x; y1 = y; COMPCLIP(code0, x1, y1); } else { x2 = x; y2 = y; COMPCLIP(code1, x2, y2); } } } while (!done); #undef COMPCLIP #undef TOP #undef BOTTOM #undef LEFT #undef RIGHT if (!accept) return; /* We have already done the clipping, no need to do it again. */ bmp->clip = FALSE; } if (x1 == x2) { bmp->vtable->vline(bmp, x1, y1, y2, color); } else if (y1 == y2) { bmp->vtable->hline(bmp, x1, y1, x2, color); } else { acquire_bitmap(bmp); do_line(bmp, x1, y1, x2, y2, color, bmp->vtable->putpixel); release_bitmap(bmp); } /* Restore original clipping state. */ bmp->clip = clip_orig; } /* do_circle: * Helper function for the circle drawing routines. Calculates the points * in a circle of radius r around point x, y, and calls the specified * routine for each one. The output proc will be passed first a copy of * the bmp parameter, then the x, y point, then a copy of the d parameter * (so putpixel() can be used as the callback). */ void do_circle(BITMAP *bmp, int x, int y, int radius, int d, void (*proc)(BITMAP *, int, int, int)) { int cx = 0; int cy = radius; int df = 1 - radius; int d_e = 3; int d_se = -2 * radius + 5; do { proc(bmp, x+cx, y+cy, d); if (cx) proc(bmp, x-cx, y+cy, d); if (cy) proc(bmp, x+cx, y-cy, d); if ((cx) && (cy)) proc(bmp, x-cx, y-cy, d); if (cx != cy) { proc(bmp, x+cy, y+cx, d); if (cx) proc(bmp, x+cy, y-cx, d); if (cy) proc(bmp, x-cy, y+cx, d); if (cx && cy) proc(bmp, x-cy, y-cx, d); } if (df < 0) { df += d_e; d_e += 2; d_se += 2; } else { df += d_se; d_e += 2; d_se += 4; cy--; } cx++; } while (cx <= cy); } /* circle: * Draws a circle. */ void _soft_circle(BITMAP *bmp, int x, int y, int radius, int color) { int clip, sx, sy, dx, dy; ASSERT(bmp); if (bmp->clip) { sx = x-radius-1; sy = y-radius-1; dx = x+radius+1; dy = y+radius+1; if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) return; if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) bmp->clip = FALSE; clip = TRUE; } else clip = FALSE; acquire_bitmap(bmp); do_circle(bmp, x, y, radius, color, bmp->vtable->putpixel); release_bitmap(bmp); bmp->clip = clip; } /* circlefill: * Draws a filled circle. */ void _soft_circlefill(BITMAP *bmp, int x, int y, int radius, int color) { int cx = 0; int cy = radius; int df = 1 - radius; int d_e = 3; int d_se = -2 * radius + 5; int clip, sx, sy, dx, dy; ASSERT(bmp); if (bmp->clip) { sx = x-radius-1; sy = y-radius-1; dx = x+radius+1; dy = y+radius+1; if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) return; if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) bmp->clip = FALSE; clip = TRUE; } else clip = FALSE; acquire_bitmap(bmp); do { bmp->vtable->hfill(bmp, x-cy, y-cx, x+cy, color); if (cx) bmp->vtable->hfill(bmp, x-cy, y+cx, x+cy, color); if (df < 0) { df += d_e; d_e += 2; d_se += 2; } else { if (cx != cy) { bmp->vtable->hfill(bmp, x-cx, y-cy, x+cx, color); if (cy) bmp->vtable->hfill(bmp, x-cx, y+cy, x+cx, color); } df += d_se; d_e += 2; d_se += 4; cy--; } cx++; } while (cx <= cy); release_bitmap(bmp); bmp->clip = clip; } /* do_ellipse: * Helper function for the ellipse drawing routines. Calculates the points * in an ellipse of radius rx and ry around point x, y, and calls the * specified routine for each one. The output proc will be passed first a * copy of the bmp parameter, then the x, y point, then a copy of the d * parameter (so putpixel() can be used as the callback). */ void do_ellipse(BITMAP *bmp, int ix, int iy, int rx0, int ry0, int d, void (*proc)(BITMAP *, int, int, int)) { int rx, ry; int x, y; float x_change; float y_change; float ellipse_error; float two_a_sq; float two_b_sq; float stopping_x; float stopping_y; int midway_x = 0; rx = MAX(rx0, 0); ry = MAX(ry0, 0); two_a_sq = 2 * rx * rx; two_b_sq = 2 * ry * ry; x = rx; y = 0; x_change = ry * ry * (1 - 2 * rx); y_change = rx * rx; ellipse_error = 0.0; /* The following two variables decide when to stop. It's easier than * solving for this explicitly. */ stopping_x = two_b_sq * rx; stopping_y = 0.0; /* First set of points. */ while (y <= ry) { proc(bmp, ix + x, iy + y, d); if (x != 0) { proc(bmp, ix - x, iy + y, d); } if (y != 0) { proc(bmp, ix + x, iy - y, d); if (x != 0) { proc(bmp, ix - x, iy - y, d); } } y++; stopping_y += two_a_sq; ellipse_error += y_change; y_change += two_a_sq; midway_x = x; if (stopping_x < stopping_y && x > 1) { break; } if ((2.0f * ellipse_error + x_change) > 0.0) { if (x) { x--; stopping_x -= two_b_sq; ellipse_error += x_change; x_change += two_b_sq; } } } /* To do the other half of the ellipse we reset to the top of it, and * iterate in the opposite direction. */ x = 0; y = ry; x_change = ry * ry; y_change = rx * rx * (1 - 2 * ry); ellipse_error = 0.0; while (x < midway_x) { proc(bmp, ix + x, iy + y, d); if (x != 0) { proc(bmp, ix - x, iy + y, d); } if (y != 0) { proc(bmp, ix + x, iy - y, d); if (x != 0) { proc(bmp, ix - x, iy - y, d); } } x++; ellipse_error += x_change; x_change += two_b_sq; if ((2.0f * ellipse_error + y_change) > 0.0) { if (y) { y--; ellipse_error += y_change; y_change += two_a_sq; } } } } /* _soft_ellipse: * Draws an ellipse. */ void _soft_ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color) { int clip, sx, sy, dx, dy; ASSERT(bmp); if (bmp->clip) { sx = x-rx-1; sy = y-ry-1; dx = x+rx+1; dy = y+ry+1; if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) return; if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) bmp->clip = FALSE; clip = TRUE; } else clip = FALSE; acquire_bitmap(bmp); do_ellipse(bmp, x, y, rx, ry, color, bmp->vtable->putpixel); release_bitmap(bmp); bmp->clip = clip; } /* _soft_ellipsefill: * Draws a filled ellipse. */ void _soft_ellipsefill(BITMAP *bmp, int ix, int iy, int rx0, int ry0, int color) { int rx, ry; int x, y; float x_change; float y_change; float ellipse_error; float two_a_sq; float two_b_sq; float stopping_x; float stopping_y; int clip, sx, sy, dx, dy; int last_drawn_y; int old_y; int midway_x = 0; ASSERT(bmp); rx = MAX(rx0, 0); ry = MAX(ry0, 0); if (bmp->clip) { sx = ix - rx - 1; sy = iy - ry - 1; dx = ix + rx + 1; dy = iy + ry + 1; if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) return; if ((sx >= bmp->cl) && (sy >= bmp->ct) && (dx < bmp->cr) && (dy < bmp->cb)) bmp->clip = FALSE; clip = TRUE; } else clip = FALSE; acquire_bitmap(bmp); two_a_sq = 2 * rx * rx; two_b_sq = 2 * ry * ry; x = rx; y = 0; x_change = ry * ry * (1 - 2 * rx); y_change = rx * rx; ellipse_error = 0.0; /* The following two variables decide when to stop. It's easier than * solving for this explicitly. */ stopping_x = two_b_sq * rx; stopping_y = 0.0; /* First set of points */ while (y <= ry) { bmp->vtable->hfill(bmp, ix - x, iy + y, ix + x, color); if (y) { bmp->vtable->hfill(bmp, ix - x, iy - y, ix + x, color); } y++; stopping_y += two_a_sq; ellipse_error += y_change; y_change += two_a_sq; midway_x = x; if (stopping_x < stopping_y && x > 1) { break; } if ((2.0f * ellipse_error + x_change) > 0.0) { if (x) { x--; stopping_x -= two_b_sq; ellipse_error += x_change; x_change += two_b_sq; } } } last_drawn_y = y - 1; /* To do the other half of the ellipse we reset to the top of it, and * iterate in the opposite direction until we reach the place we stopped at * last time. */ x = 0; y = ry; x_change = ry * ry; y_change = rx * rx * (1 - 2 * ry); ellipse_error = 0.0; old_y = y; while (x < midway_x) { if (old_y != y) { bmp->vtable->hfill(bmp, ix - x + 1, iy + old_y, ix + x - 1, color); if (old_y) { bmp->vtable->hfill(bmp, ix - x + 1, iy - old_y, ix + x - 1, color); } } x++; ellipse_error += x_change; x_change += two_b_sq; old_y = y; if ((2.0f * ellipse_error + y_change) > 0.0) { if (y) { y--; ellipse_error += y_change; y_change += two_a_sq; } } } /* On occasion, a gap appears between the middle and upper halves. * This 'afterthought' fills it in. */ if (old_y != last_drawn_y) { bmp->vtable->hfill(bmp, ix - x + 1, iy + old_y, ix + x - 1, color); if (old_y) { bmp->vtable->hfill(bmp, ix - x + 1, iy - old_y, ix + x - 1, color); } } release_bitmap(bmp); bmp->clip = clip; } /* get_point_on_arc: * Helper function for the do_arc() function, converting from (radius, angle) * to (x, y). */ static INLINE void get_point_on_arc(int r, fixed a, int *out_x, int *out_y, int *out_q) { double s, c; double double_a = (a&0xffffff) * (AL_PI * 2 / (1 << 24)); s = sin(double_a); c = cos(double_a); s = -s * r; c = c * r; *out_x = (int)((c < 0) ? (c - 0.5) : (c + 0.5)); *out_y = (int)((s < 0) ? (s - 0.5) : (s + 0.5)); if (c >= 0) { if (s <= 0) *out_q = 0; /* quadrant 0 */ else *out_q = 3; /* quadrant 3 */ } else { if (s <= 0) *out_q = 1; /* quadrant 1 */ else *out_q = 2; /* quadrant 2 */ } } /* do_arc: * Helper function for the arc function. Calculates the points in an arc * of radius r around point x, y, going anticlockwise from fixed point * binary angle ang1 to ang2, and calls the specified routine for each one. * The output proc will be passed first a copy of the bmp parameter, then * the x, y point, then a copy of the d parameter (so putpixel() can be * used as the callback). */ void do_arc(BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int d, void (*proc)(BITMAP *, int, int, int)) { /* start position */ int sx, sy; /* current position */ int px, py; /* end position */ int ex, ey; /* square of radius of circle */ long rr; /* difference between main radius squared and radius squared of three potential next points */ long rr1, rr2, rr3; /* square of x and of y */ unsigned long xx, yy, xx_new, yy_new; /* start quadrant, current quadrant and end quadrant */ int sq, q, qe; /* direction of movement */ int dx, dy; /* temporary variable for determining if we have reached end point */ int det; /* Calculate the start point and the end point. */ /* We have to flip y because bitmaps count y coordinates downwards. */ get_point_on_arc(r, ang1, &sx, &sy, &q); px = sx; py = sy; get_point_on_arc(r, ang2, &ex, &ey, &qe); rr = r*r; xx = px*px; yy = py*py - rr; sq = q; if (q > qe) { /* qe must come after q. */ qe += 4; } else if (q == qe) { /* If q==qe but the beginning comes after the end, make qe be * strictly after q. */ if (((ang2&0xffffff) < (ang1&0xffffff)) || (((ang1&0xffffff) < 0x400000) && ((ang2&0xffffff) >= 0xc00000))) qe += 4; } /* initial direction of movement */ if (((q+1)&2) == 0) dy = -1; else dy = 1; if ((q&2) == 0) dx = -1; else dx = 1; while (TRUE) { /* Change quadrant when needed. * dx and dy determine the possible directions to go in this * quadrant, so they must be updated when we change quadrant. */ if ((q&1) == 0) { if (px == 0) { if (qe == q) break; q++; dy = -dy; } } else { if (py == 0) { if (qe == q) break; q++; dx = -dx; } } /* Are we in the final quadrant? */ if (qe == q) { /* Have we reached (or passed) the end point both in x and y? */ det = 0; if (dy > 0) { if (py >= ey) det++; } else { if (py <= ey) det++; } if (dx > 0) { if (px >= ex) det++; } else { if (px <= ex) det++; } if (det == 2) break; } proc(bmp, x+px, y+py, d); /* From here, we have only 3 possible directions of movement, eg. * for the first quadrant: * * ......... * ......... * ......21. * ......3*. * * These are reached by adding dx to px and/or adding dy to py. * We need to find which of these points gives the best * approximation of the (square of the) radius. */ xx_new = (px+dx) * (px+dx); yy_new = (py+dy) * (py+dy) - rr; rr1 = xx_new + yy; rr2 = xx_new + yy_new; rr3 = xx + yy_new; /* Set rr1, rr2, rr3 to be the difference from the main radius of the * three points. */ if (rr1 < 0) rr1 = -rr1; if (rr2 < 0) rr2 = -rr2; if (rr3 < 0) rr3 = -rr3; if (rr3 >= MIN(rr1, rr2)) { px += dx; xx = xx_new; } if (rr1 > MIN(rr2, rr3)) { py += dy; yy = yy_new; } } /* Only draw last point if it doesn't overlap with first one. */ if ((px != sx) || (py != sy) || (sq == qe)) proc(bmp, x+px, y+py, d); } /* arc: * Draws an arc. */ void _soft_arc(BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color) { ASSERT(bmp); acquire_bitmap(bmp); do_arc(bmp, x, y, ang1, ang2, r, color, bmp->vtable->putpixel); release_bitmap(bmp); } allegro-4.4.3.1/src/dither.c0000664000175000017500000000423313437077643014514 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Hicolor dithering routines. * * By Ivan Baldo. * * See readme.txt for copyright information. */ #include "allegro.h" static unsigned char dither_table[8] = { 0, 16, 68, 146, 170, 109, 187, 239 }; static unsigned char dither_ytable[8] = { 1, 5, 2, 7, 4, 0, 6, 3 }; /* makecol15_dither: * Calculates a dithered 15 bit pixel value. */ int makecol15_dither(int r, int g, int b, int x, int y) { int returned_r, returned_g, returned_b; int bpos; returned_r = r>>3; returned_g = g>>3; returned_b = b>>3; y = dither_ytable[y&7]; bpos = (x+y)&7; returned_r += (dither_table[r&7] >> bpos) & 1; bpos = (bpos+3)&7; returned_b += (dither_table[b&7] >> bpos) & 1; bpos = (bpos+7)&7; returned_g += (dither_table[g&7] >> bpos) & 1; returned_r -= returned_r>>5; returned_g -= returned_g>>5; returned_b -= returned_b>>5; return (returned_r<<_rgb_r_shift_15) | (returned_g<<_rgb_g_shift_15) | (returned_b<<_rgb_b_shift_15); } /* makecol16_dither: * Calculates a dithered 16 bit pixel value. */ int makecol16_dither(int r, int g, int b, int x, int y) { int returned_r, returned_g, returned_b; int bpos; returned_r = r>>3; returned_g = g>>2; returned_b = b>>3; y = dither_ytable[y&7]; bpos = (x+y)&7; returned_r += (dither_table[r&7] >> bpos) & 1; bpos = (bpos+3)&7; returned_b += (dither_table[b&7] >> bpos) & 1; bpos = (bpos+7)&7; returned_g += (dither_table[(g&3)*2] >> bpos) & 1; returned_r -= returned_r>>5; returned_g -= returned_g>>6; returned_b -= returned_b>>5; return (returned_r<<_rgb_r_shift_16) | (returned_g<<_rgb_g_shift_16) | (returned_b<<_rgb_b_shift_16); } allegro-4.4.3.1/src/digmid.c0000664000175000017500000006112713437077643014477 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Digitized sample driver for the MIDI player. * * By Shawn Hargreaves, based on code by Tom Novelli. * Chris Robinson added some optimizations and the digmid_set_pan method. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" /* external interface to the Digmid driver */ static int digmid_detect(int input); static int digmid_init(int input, int voices); static void digmid_exit(int input); static int digmid_load_patches(AL_CONST char *patches, AL_CONST char *drums); static void digmid_key_on(int inst, int note, int bend, int vol, int pan); static void digmid_key_off(int voice); static void digmid_set_volume(int voice, int vol); static void digmid_set_pitch(int voice, int note, int bend); static void digmid_set_pan(int voice, int pan); MIDI_DRIVER midi_digmid = { MIDI_DIGMID, empty_string, empty_string, "DIGMID", 0, 0, -1, 24, -1, -1, digmid_detect, digmid_init, digmid_exit, NULL, NULL, NULL, digmid_load_patches, _dummy_adjust_patches, digmid_key_on, digmid_key_off, digmid_set_volume, digmid_set_pitch, digmid_set_pan, _dummy_noop2 }; #define MAX_LAYERS 64 typedef struct PATCH_EXTRA /* additional data for a Gravis PATCH */ { int low_note; int high_note; int base_note; int play_mode; int decay_time; int release_time; int sustain_level; int scale_freq; int scale_factor; int pan; } PATCH_EXTRA; typedef struct PATCH /* Gravis PATCH structure */ { int samples; /* number of samples in this instrument */ SAMPLE *sample[MAX_LAYERS]; /* the waveform data */ PATCH_EXTRA *extra[MAX_LAYERS]; /* additional waveform information */ int master_vol; /* overall volume level */ } PATCH; /* our instruments */ static PATCH *patch[256]; /* frequency table (generated by digmid_init) */ static long ftbl[130]; /* stored information about active voices */ typedef struct DIGMID_VOICE { SAMPLE *s; PATCH_EXTRA *e; int inst; int vol; } DIGMID_VOICE; static DIGMID_VOICE digmid_voice[MIDI_VOICES]; /* destroy_patch: * Frees a PATCH struct and all samples it contains. */ static void destroy_patch(PATCH *pat) { int i; if (pat) { for (i=0; i < pat->samples; i++) { destroy_sample(pat->sample[i]); UNLOCK_DATA(pat->extra[i], sizeof(PATCH_EXTRA)); _AL_FREE(pat->extra[i]); } UNLOCK_DATA(pat, sizeof(PATCH)); _AL_FREE(pat); } } /* scale64: * Evalulates a*b/c using 64 bit arithmetic. This is used in an interrupt * context, so we have to do it ourselves rather than relying on compiler * support or floating point (it is impossible to reliably lock the * compiler helpers that implement a 64 bit divide, and it isn't safe to * use the i386 FPU stack in an interrupt context). Multithreaded systems * are not bound by this restriction however, so we use the FPU there. */ #if !(defined ALLEGRO_MULTITHREADED) static INLINE unsigned long scale64(unsigned long a, unsigned long b, unsigned long c) { unsigned long al = a & 0xFFFF; unsigned long ah = a >> 16; unsigned long bl = b & 0xFFFF; unsigned long bh = b >> 16; unsigned long rl, rh, r, s, t, o; /* 64 bit multiply */ rl = al*bl; rh = ah*bh; t = al*bh; o = rl; rh += (t >> 16); rl += (t << 16); if (rl < o) rh++; t = ah*bl; o = rl; rh += (t >> 16); rl += (t << 16); if (rl < o) rh++; /* 64 bit divide */ s = 0x80000000; t = rh; r = 0; while (s) { o = t; t -= c; if (t > o) t = o; else r |= s; t <<= 1; if (rl & s) t |= 1; s >>= 1; } return r << 1; } #else static INLINE unsigned long scale64(unsigned long a, unsigned long b, unsigned long c) { double scale = b / (double)c; return (unsigned long)a * scale; } #endif /* load_patch: * Reads a GUS format patch file from disk. */ static PATCH *load_patch(PACKFILE *f, int drum) { PATCH *p = NULL; char buf[256]; char mode; int env_rate[6]; int env_offset[6]; int i, j; int diff; int odd_len; pack_fread(buf, 22, f); /* ID tag */ if (memcmp(buf, "GF1PATCH110\0", 12) || memcmp(buf+12, "ID#000002\0", 10)) { *allegro_errno = EINVAL; goto getout; } p = _AL_MALLOC(sizeof(PATCH)); if (!p) { *allegro_errno = ENOMEM; goto getout; } pack_fread(buf, 65, f); /* description */ p->master_vol = pack_igetw(f); /* volume */ pack_fread(buf, 109, f); /* skip */ p->samples = pack_getc(f); /* number of samples */ pack_fread(buf, 40, f); /* skip */ if (p->samples > MAX_LAYERS) p->samples = MAX_LAYERS; for (i=0; isamples; i++) { /* for each sample... */ p->sample[i] = _AL_MALLOC(sizeof(SAMPLE)); if (!p->sample[i]) { p->samples = i; destroy_patch(p); p = NULL; *allegro_errno = ENOMEM; goto getout; } p->extra[i] = _AL_MALLOC_ATOMIC(sizeof(PATCH_EXTRA)); if (!p->extra[i]) { _AL_FREE(p->sample[i]); p->samples = i; destroy_patch(p); p = NULL; *allegro_errno = ENOMEM; goto getout; } pack_fread(buf, 8, f); /* layer name */ p->sample[i]->len = pack_igetl(f); /* sample length */ p->sample[i]->loop_start = pack_igetl(f); /* loop start */ p->sample[i]->loop_end = pack_igetl(f); /* loop end */ p->sample[i]->freq = pack_igetw(f); /* sample frequency */ p->extra[i]->low_note = pack_igetl(f); /* key min */ p->extra[i]->high_note = pack_igetl(f); /* key max */ p->extra[i]->base_note = pack_igetl(f); /* base key */ pack_igetw(f); /* skip finetune */ p->extra[i]->pan = pack_getc(f) * 255/15; /* pan position */ for (j=0; j<6; j++) /* envelope rate */ env_rate[j] = pack_getc(f); for (j=0; j<6; j++) /* envelope value */ env_offset[j] = pack_getc(f); pack_fread(buf, 6, f); /* skip trem and vib */ mode = pack_getc(f); /* sample flags */ p->sample[i]->bits = (mode & 1) ? 16 : 8; /* how many bits? */ p->sample[i]->stereo = FALSE; p->extra[i]->play_mode = 0; /* sort out loop flags */ if (mode & 4) p->extra[i]->play_mode |= PLAYMODE_LOOP; if (mode & 8) p->extra[i]->play_mode |= (PLAYMODE_BIDIR | PLAYMODE_LOOP); if (mode & 16) p->extra[i]->play_mode |= (PLAYMODE_BACKWARD | PLAYMODE_LOOP); /* convert envelope rates (GUS uses a 2.6 floating point format) */ for (j=0; j<6; j++) { static int vexp[4] = { 1, 8, 64, 512 }; int e = (env_rate[j] >> 6); int m = (env_rate[j] & 0x3F); env_rate[j] = ((65536 * vexp[e] / ((m) ? m : 1)) >> 12); } if ((mode & 32) && (!drum)) { /* sustained volume envelope */ p->extra[i]->sustain_level = env_offset[2]; p->extra[i]->decay_time = 0; diff = env_offset[0]; p->extra[i]->decay_time += env_rate[0] * diff / 256; diff = ABS(env_offset[1] - env_offset[0]); p->extra[i]->decay_time += env_rate[1] * diff / 256; diff = ABS(env_offset[2] - env_offset[1]); p->extra[i]->decay_time += env_rate[2] * diff / 256; j = 3; } else { /* one-shot volume envelope */ p->extra[i]->decay_time = 0; p->extra[i]->sustain_level = 0; for (j=0; j<6; j++) { diff = ABS(env_offset[j] - ((j) ? env_offset[j-1] : 0)); p->extra[i]->decay_time += env_rate[j] * diff / 256; if (env_offset[j] < 16) { j++; break; } } } /* measure release time */ p->extra[i]->release_time = 0; while (j < 6) { diff = ABS(env_offset[j] - env_offset[j-1]); p->extra[i]->release_time += env_rate[j] * diff / 256; if (env_offset[j] < 16) break; j++; } /* clamp very large/small sustain levels to zero or maximum */ if (p->extra[i]->sustain_level < 16) p->extra[i]->sustain_level = 0; else if (p->extra[i]->sustain_level > 192) p->extra[i]->sustain_level = 255; if (p->extra[i]->release_time < 10) p->extra[i]->release_time = 0; if ((p->extra[i]->sustain_level == 0) && (p->extra[i]->decay_time == 0)) { p->extra[i]->sustain_level = 255; p->extra[i]->play_mode &= ~PLAYMODE_LOOP; } p->extra[i]->scale_freq = pack_igetw(f); /* scale values */ p->extra[i]->scale_factor = pack_igetw(f); /* drums use a fixed frequency */ if(drum) { unsigned long freq = scale64(ftbl[drum-1], p->sample[i]->freq, p->extra[i]->base_note); /* frequency scaling */ if (p->extra[i]->scale_factor != 1024) { unsigned long f1 = scale64(p->sample[i]->freq, p->extra[i]->scale_freq, 60); freq -= f1; freq = scale64(freq, p->extra[i]->scale_factor, 1024); freq += f1; } /* lower by an octave if we are going to overflow */ while (freq >= (1<<19)-1) freq /= 2; p->sample[i]->freq = freq; } pack_fread(buf, 36, f); /* skip reserved */ if (p->sample[i]->bits == 16) { /* adjust 16 bit loops */ odd_len = (p->sample[i]->len & 1); p->sample[i]->len /= 2; p->sample[i]->loop_start /= 2; p->sample[i]->loop_end /= 2; } else odd_len = FALSE; p->sample[i]->priority = 128; /* set some defaults */ p->sample[i]->param = 0; p->sample[i]->data = _AL_MALLOC_ATOMIC(p->sample[i]->len*((p->sample[i]->bits==8) ? 1 : sizeof(short))); if (!p->sample[i]->data) { _AL_FREE(p->sample[i]); _AL_FREE(p->extra[i]); p->samples = i; destroy_patch(p); p = NULL; *allegro_errno = ENOMEM; goto getout; } if (p->sample[i]->bits == 8) { /* read 8 bit sample data */ pack_fread(p->sample[i]->data, p->sample[i]->len, f); if (!(mode & 2)) { /* signed data - convert to unsigned */ for (j=0; j<(int)p->sample[i]->len; j++) ((unsigned char *)p->sample[i]->data)[j] ^= 0x80; } } else { /* read 16 bit sample data */ for (j=0; j<(int)p->sample[i]->len; j++) { ((unsigned short *)p->sample[i]->data)[j] = pack_igetw(f); } if (!(mode & 2)) { /* signed data - convert to unsigned */ for (j=0; j<(int)p->sample[i]->len; j++) ((unsigned short *)p->sample[i]->data)[j] ^= 0x8000; } if (odd_len) pack_getc(f); } } getout: /* lock the data into physical memory */ if (p) { LOCK_DATA(p, sizeof(PATCH)); for (i=0; isamples; i++) { lock_sample(p->sample[i]); LOCK_DATA(p->extra[i], sizeof(PATCH_EXTRA)); } } return p; } /* _digmid_find_patches: * Tries to locate the GUS patch set directory and index file (default.cfg). */ int _digmid_find_patches(char *dir, int dir_size, char *file, int file_size) { char filename[1024], tmp1[64], tmp2[64], tmp3[64], tmp4[64]; AL_CONST char *name; char *datafile, *objectname, *envvar, *subdir, *s; name = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("patches", tmp2), NULL); datafile = uconvert_ascii("patches.dat", tmp1); objectname = uconvert_ascii("default.cfg", tmp2); envvar = uconvert_ascii("ULTRADIR", tmp3); subdir = uconvert_ascii("midi", tmp4); if (find_allegro_resource(filename, name, NULL, datafile, objectname, envvar, subdir, sizeof(filename)) != 0) return FALSE; if (dir && file) { s = ustrrchr(filename, '#'); if(s == NULL) s = get_filename(filename); else s += ustrlen("#"); ustrzcpy(file, file_size, s); usetc(s, 0); ustrzcpy(dir, dir_size, filename); } return TRUE; } /* parse_string: * Splits a string into component parts, storing them in the argv pointers. * Returns the number of components. */ static int parse_string(char *buf, char *argv[]) { int c = 0; while (ugetc(buf) && (c<16)) { while ((ugetc(buf) == ' ') || (ugetc(buf) == '\t') || (ugetc(buf) == '=')) buf += uwidth(buf); if (ugetc(buf) == '#') return c; if (ugetc(buf)) argv[c++] = buf; while (ugetc(buf) && (ugetc(buf) != ' ') && (ugetc(buf) != '\t') && (ugetc(buf) != '=')) buf += uwidth(buf); if (ugetc(buf)) buf += usetc(buf, 0); } return c; } /* digmid_load_patches: * Reads the patches that are required by a particular song. */ static int digmid_load_patches(AL_CONST char *patches, AL_CONST char *drums) { PACKFILE *f; char dir[1024], file[1024], buf[1024], filename[1024]; char todo[256][1024]; char *argv[16], *p; char tmp[128]; int argc; int patchnum, flag_num; int drum_mode = FALSE; int override_mode = FALSE; int drum_start = 0; int type, size; int i, j, c; if (!_digmid_find_patches(dir, sizeof(dir), file, sizeof(file))) return -1; for (i=0; i<256; i++) usetc(todo[i], 0); ustrzcpy(buf, sizeof(buf), dir); ustrzcat(buf, sizeof(buf), file); f = pack_fopen(buf, F_READ); if (!f) return -1; while (pack_fgets(buf, sizeof(buf), f) != 0) { argc = parse_string(buf, argv); if (argc > 0) { /* is first word all digits? */ flag_num = TRUE; p = argv[0]; while ((c = ugetx(&p)) != 0) { if ((!uisdigit(c)) && (c != '-')) { flag_num = FALSE; break; } } if ((flag_num) && (argc >= 2)) { if (ustricmp(argv[1], uconvert_ascii("begin_multipatch", tmp)) == 0) { /* start the block of percussion instruments */ drum_start = ustrtol(argv[0], NULL, 10) - 1; drum_mode = TRUE; } else if (ustricmp(argv[1], uconvert_ascii("override_patch", tmp)) == 0) { /* ignore patch overrides */ override_mode = TRUE; } else if (!override_mode) { /* must be a patch number */ patchnum = ustrtol(argv[0], NULL, 10); if (!drum_mode) patchnum--; if ((patchnum >= 0) && (patchnum < 128) && (((drum_mode) && (drums[patchnum])) || ((!drum_mode) && (patches[patchnum])))) { if (drum_mode) patchnum += drum_start; if (!patch[patchnum]) { /* need to load this sample */ ustrzcpy(todo[patchnum], sizeof(todo[patchnum]), argv[1]); } } } } else { /* handle other keywords */ if (ustricmp(argv[0], uconvert_ascii("end_multipatch", tmp)) == 0) { drum_mode = FALSE; override_mode = FALSE; } } } } pack_fclose(f); if (ustrchr(dir, '#')) { /* read from a datafile */ if ((ustrlen(dir) > 1) && (ugetat(dir, -1) == '#')) usetat(dir, -1, 0); f = pack_fopen(dir, F_READ_PACKED); if (!f) return -1; if (((ugetc(dir) == '#') && (ustrlen(dir) == 1)) || (!ustrchr(dir, '#'))) { type = pack_mgetl(f); if (type != DAT_MAGIC) { pack_fclose(f); return -1; } } pack_mgetl(f); usetc(filename, 0); /* scan through the file */ while (!pack_feof(f)) { type = pack_mgetl(f); if (type == DAT_PROPERTY) { type = pack_mgetl(f); size = pack_mgetl(f); if (type == DAT_ID('N','A','M','E')) { /* store name property */ pack_fread(buf, size, f); buf[size] = 0; do_uconvert(buf, U_ASCII, filename, U_CURRENT, sizeof(filename)); } else { /* skip other properties */ pack_fseek(f, size); } } else if (type == DAT_PATCH) { /* do we want this patch? */ for (i=0; i<256; i++) if (ugetc(todo[i]) && (ustricmp(filename, todo[i]) == 0)) break; if (i < 256) { /* load this patch */ f = pack_fopen_chunk(f, FALSE); patch[i] = load_patch(f, ((i > 127) ? (i - 127) : 0)); f = pack_fclose_chunk(f); for (j=i+1; j<256; j++) { /* share multiple copies of the instrument */ if (ustricmp(todo[i], todo[j]) == 0) { patch[j] = patch[i]; usetc(todo[j], 0); } } usetc(todo[i], 0); } else { /* skip unwanted patch */ size = pack_mgetl(f); pack_fseek(f, size+4); } } else { /* skip unwanted object */ size = pack_mgetl(f); pack_fseek(f, size+4); } } } else { /* read from regular disk files */ for (i=0; i<256; i++) { if (ugetc(todo[i])) { if (is_relative_filename(todo[i])) { ustrzcpy(filename, sizeof(filename), dir); ustrzcat(filename, sizeof(filename), todo[i]); } else ustrzcpy(filename, sizeof(filename), todo[i]); if (ugetc(get_extension(filename)) == 0) ustrzcat(filename, sizeof(filename), uconvert_ascii(".pat", tmp)); f = pack_fopen(filename, F_READ); if (f) { patch[i] = load_patch(f, ((i > 127) ? (i - 127) : 0)); pack_fclose(f); } for (j=i+1; j<256; j++) { /* share multiple copies of the instrument */ if (ustricmp(todo[i], todo[j]) == 0) { patch[j] = patch[i]; usetc(todo[j], 0); } } } } } return 0; } /* digmid_freq: * Helper for converting note numbers to sample frequencies. */ static int digmid_freq(int inst, SAMPLE *s, PATCH_EXTRA *e, int note, int bend) { unsigned long freq, f1, f2, sfreq, base_note; sfreq = s->freq; base_note = e->base_note; /* calculate frequency */ if(bend) { f1 = scale64(ftbl[note], sfreq, base_note); f2 = scale64(ftbl[note+1], sfreq, base_note); /* quick pitch bend method - ~.035% error - acceptable? */ freq = ((f1*(4096-bend)) + (f2*bend)) / 4096; } else freq = scale64(ftbl[note], sfreq, base_note); /* frequency scaling */ if (e->scale_factor != 1024) { f1 = scale64(sfreq, e->scale_freq, 60); freq -= f1; freq = scale64(freq, e->scale_factor, 1024); freq += f1; } /* lower by an octave if we are going to overflow */ while (freq >= (1<<19)-1) freq /= 2; return freq; } END_OF_STATIC_FUNCTION(digmid_freq); /* digmid_trigger: * Helper for activating a specific sample layer. */ static void digmid_trigger(int inst, int snum, int note, int bend, int vol, int pan) { int freq, voice; DIGMID_VOICE *info; PATCH_EXTRA *e; SAMPLE *s; voice = _midi_allocate_voice(-1, -1); if (voice < 0) return; s = patch[inst]->sample[snum]; e = patch[inst]->extra[snum]; if (inst > 127) { pan = e->pan; freq = s->freq; } else freq = digmid_freq(inst, s, e, note, bend); /* store note information for later use */ info = &digmid_voice[voice - midi_digmid.basevoice]; info->s = s; info->e = e; info->inst = inst; info->vol = vol; /* play the note */ reallocate_voice(voice, s); voice_set_playmode(voice, e->play_mode); voice_set_volume(voice, vol); voice_set_frequency(voice, freq); voice_set_pan(voice, pan); if (e->sustain_level < 255) voice_ramp_volume(voice, e->decay_time, e->sustain_level*vol/255); voice_start(voice); } END_OF_STATIC_FUNCTION(digmid_trigger); /* digmid_key_on: * Triggers the specified voice. The instrument is specified as a GM * patch number, pitch as a midi note number, and volume from 0-127. * The bend parameter is _not_ expressed as a midi pitch bend value. * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp). * Drum sounds are indicated by passing an instrument number greater than * 128, in which case the sound is GM percussion key #(inst-128). */ static void digmid_key_on(int inst, int note, int bend, int vol, int pan) { PATCH_EXTRA *e; long freq; int best, best_diff; int diff; int i, c; /* quit if instrument is not available */ if ((!patch[inst]) || (patch[inst]->samples < 1)) return; /* adjust volume and pan ranges */ vol *= 2; pan *= 2; if (patch[inst]->samples == 1) { /* only one sample to choose from */ digmid_trigger(inst, 0, note, bend, vol, pan); } else { /* find the sample(s) with best frequency range */ best = -1; best_diff = INT_MAX; c = 0; for (i=0; isamples; i++) { freq = ftbl[note]; e = patch[inst]->extra[i]; if ((freq >= e->low_note) && (freq <= e->high_note)) { digmid_trigger(inst, i, note, bend, vol, pan); c++; if (c > 4) break; } else { diff = MIN(ABS(freq - e->low_note), ABS(freq - e->high_note)); if (diff < best_diff) { best_diff = diff; best = i; } } } if ((c <= 0) && (best >= 0)) digmid_trigger(inst, best, note, bend, vol, pan); } } END_OF_STATIC_FUNCTION(digmid_key_on); /* digmid_key_off: * Hey, guess what this does :-) */ static void digmid_key_off(int voice) { DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; if (info->inst > 127) return; if (info->e->release_time > 0) voice_ramp_volume(voice, info->e->release_time, 0); else voice_stop(voice); } END_OF_STATIC_FUNCTION(digmid_key_off); /* digmid_set_volume: * Sets the volume of the specified voice (vol range 0-127). */ static void digmid_set_volume(int voice, int vol) { DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; int v; if (info->inst > 127) return; vol *= 2; if (info->e->sustain_level < 255) { /* adjust for volume ramping */ int current = voice_get_volume(voice); int target = info->e->sustain_level*info->vol/255; int start = info->vol; if (ABS(current - target) < 8) { /* ramp has finished */ voice_set_volume(voice, vol*info->e->sustain_level/255); } else { /* in the middle of a ramp */ int mu; if (start > target) mu = CLAMP(0, (current-target) * 256 / (start-target), 256); else mu = 0; v = mu+info->e->sustain_level*(256-mu)/256; v = CLAMP(0, vol*v/255, 255); voice_set_volume(voice, v); voice_ramp_volume(voice, info->e->decay_time*mu/256, info->e->sustain_level*vol/255); } } else { /* no ramp */ voice_set_volume(voice, vol); } info->vol = vol; } END_OF_STATIC_FUNCTION(digmid_set_volume); /* digmid_set_pitch: * Sets the pitch of the specified voice. */ static void digmid_set_pitch(int voice, int note, int bend) { DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; int freq; if (info->inst > 127) return; freq = digmid_freq(info->inst, info->s, info->e, note, bend); voice_set_frequency(voice, freq); } END_OF_STATIC_FUNCTION(digmid_set_pitch); static void digmid_set_pan(int voice, int pan) { DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice]; if (info->inst > 127) return; pan *= 2; voice_set_pan(voice, pan); } END_OF_STATIC_FUNCTION(digmid_set_pan); /* digmid_detect: * Have we got a sensible looking patch set? */ static int digmid_detect(int input) { if (input) return FALSE; if (!_digmid_find_patches(NULL, 0, NULL, 0)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("DIGMID patch set not found")); return FALSE; } return TRUE; } /* digmid_init: * Setup the digmid driver. */ static int digmid_init(int input, int voices) { float f; int i; midi_digmid.desc = get_config_text("Software wavetable synth"); for (i=0; i<256; i++) patch[i] = NULL; midi_digmid.voices = voices; /* A10 = 14080.000 hz */ ftbl[129] = 14080000; f = ftbl[129]; /* create frequency table */ for (i=128; i>=0; i--) { f /= pow(2.0, 1.0/12.0); ftbl[i] = f; } LOCK_VARIABLE(midi_digmid); LOCK_VARIABLE(patch); LOCK_VARIABLE(ftbl); LOCK_VARIABLE(digmid_voice); LOCK_FUNCTION(digmid_freq); LOCK_FUNCTION(digmid_trigger); LOCK_FUNCTION(digmid_key_on); LOCK_FUNCTION(digmid_key_off); LOCK_FUNCTION(digmid_set_volume); LOCK_FUNCTION(digmid_set_pitch); LOCK_FUNCTION(digmid_set_pan); return 0; } /* digmid_exit: * Cleanup when we are finished. */ static void digmid_exit(int input) { int i, j; for (i=0; i<256; i++) { if (patch[i]) { for (j=i+1; j<256; j++) { if (patch[j] == patch[i]) patch[j] = NULL; } destroy_patch(patch[i]); patch[i] = NULL; } } } allegro-4.4.3.1/src/quantize.c0000664000175000017500000003175213437077643015103 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Optimised palette generation routines. * * By Michal Mertl. * * Portability improvements and bugfixes by Michael Bukin. * * See readme.txt for copyright information. * * The algorithm used here is my own, because the ones I found * on the net seemed too complex for me :-) First I just count the * number of pixels of the same color (the number of different colors * is for 24/32bpp significantly reduced by using only 4(5) bits per * RGB). Than I sort the list with the most used colors first. Most * of the palette is just copy of this list and the rest (very * important in fact) is generated by comparing colors one by one * with each other inserting to the palette the most different ones. * * The vast majority of the time spent in the routine is in initial * counting (looking up items in hashtable), so the smaller the number * of colors the faster the result. For example on my computer (P100) * with 800/600 32bpp image and 4 bits per RGB it takes about 590ms * and with 5 bits per RGB about 5100ms. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #define DEFAULT_PREC 4 #define DEFAULT_FRACTION 5 #define DEFAULT_MAXSWAPS 16 #define DEFAULT_MINDIFF 9 /* the number of lists, prime number */ #define HASHTABLESIZE 1031 typedef struct NODE { struct NODE *next; int color, count; } NODE; typedef struct { int color, key; } ITEM; static int distinct; static NODE *hash_table; static void delete_list(NODE *list) { NODE *node, *next; for (node = list; node != NULL; node = next) { next = node->next; _AL_FREE (node); } } static void insert_node(int color) { NODE *p; p = &hash_table[color % HASHTABLESIZE]; for (;;) { if (p->color == color) { /* this node (e.g. the color was already filled) */ p->count++; return; } if (p->next) p = p->next; else break; } /* new color */ if (p->count) { p->next = _AL_MALLOC(sizeof(NODE)); p = p->next; } if (p != NULL) { p->color = color; p->count = 1; p->next = NULL; distinct++; } } /* helper function for builtin qsort function */ static int qsort_helper_ITEM(AL_CONST void *e1, AL_CONST void *e2) { return ((ITEM *)e2)->key - ((ITEM *)e1)->key; } /* compare two color values */ static INLINE int compare_cols(int col1, int col2) { int b = ((col1 >> 16) & 0xFF) - ((col2 >> 16) & 0xFF); int g = ((col1 >> 8) & 0xFF) - ((col2 >> 8) & 0xFF); int r = ((col1 & 0xFF) - (col2 & 0xFF)); return (((r < 0) ? -r : r) + ((g < 0) ? -g : g) + ((b < 0) ? -b : b)); } /* Searches the array from 'item'th field comparing any pair of items. * Fills 'key' field of all items >= 'item'th with the difference * value (the smallest difference between the checked color and all * already used). Than only the last added item has to be compared with * all other not yet added colors, what is performed afterwards. */ static void optimize_colors(ITEM *array, int item, int palsize, int length, int mindiff) { int i, j, best, curbest, bestpos, t; /* iterate through the array comparing any item behind 'item' */ for (i=item; i best) { best = array[j].key; bestpos = j; } } } } } /* searches the array of length for the color */ static INLINE int no_such_color(ITEM *array, int length, int color, int mask) { int i; for (i=0; ir = (color & 0xFF); rgb->g = (color >> 8) & 0xFF; rgb->b = (color >> 16) & 0xFF; } /* generate_optimized_palette_ex: * Calculates a suitable palette for color reducing the specified truecolor * image. If the rsvdcols parameter is not NULL, it contains an array of * 256 flags. If rsvdcols[n] > 0 the palette entry is assumed to be already * set so I count with it. If rsvdcols[n] < 0 I mustn't assume anything about * the entry. If rsvdcols[n] == 0 the entry is free for me to change. * * Variable fraction controls, how big part of the palette should be * filled with 'different colors', maxswaps gives upper boundary for * number of swaps and mindiff chooses when to stop replacing values */ static int generate_optimized_palette_ex(BITMAP *image, PALETTE pal, AL_CONST signed char *rsvdcols, int bitsperrgb, int fraction, int maxswaps, int mindiff) { int i, j, x, y, imgdepth, numcols, palsize, rsvdcnt=0, rsvduse=0; unsigned int prec_mask, prec_mask2, bitmask15, bitmask16, bitmask24; signed char tmprsvd[256]; int rshift, gshift, bshift; ITEM *colors; switch (bitsperrgb) { case 4: prec_mask = 0x3C3C3C; prec_mask2 = 0; bitmask15 = 0x7BDE; /* 0111 1011 1101 1110 */ bitmask16 = 0xF79E; /* 1111 0111 1001 1110 */ bitmask24 = 0xF0F0F0; break; case 5: prec_mask = 0x3E3E3E; prec_mask2 = 0x3C3C3C; bitmask15 = 0x7FFF; /* 0111 1111 1111 1111 */ bitmask16 = 0xFFDF; /* 1111 1111 1101 1111 */ bitmask24 = 0xF8F8F8; break; default: return -1; } distinct = 0; imgdepth = bitmap_color_depth(image); if (imgdepth == 8) return 0; hash_table = _AL_MALLOC(HASHTABLESIZE * sizeof(NODE)); if (hash_table == NULL) return 0; for (i = 0; i < HASHTABLESIZE; i++) { hash_table[i].next = NULL; hash_table[i].color = -1; hash_table[i].count = 0; } /* count the number of colors we shouldn't modify */ if (rsvdcols) { for (i=0; i<256; i++) { if (rsvdcols[i]) { rsvdcnt++; if (rsvdcols[i] > 0) rsvduse++; } } } else { pal[0].r = 63; pal[0].g = 0; pal[0].b = 63; tmprsvd[0] = 1; rsvdcnt++; rsvduse++; for (i=1; i<256; i++) tmprsvd[i] = 0; rsvdcols = tmprsvd; } /* fix palette */ for (i = 0; i < 256; i++) { pal[i].r &= 0x3F; pal[i].g &= 0x3F; pal[i].b &= 0x3F; } /* fill the 'hash_table' with 4bit per RGB color values */ bmp_select(image); switch (imgdepth) { case 32: for (y=0; yh; y++) for (x=0; xw; x++) insert_node(bmp_read32((uintptr_t)image->line[y]+x*sizeof(int32_t)) & bitmask24); break; case 24: for (y=0; yh; y++) for (x=0; xw; x++) insert_node(bmp_read24((uintptr_t)image->line[y]+x*3) & bitmask24); break; case 16: for (y=0; yh; y++) for (x=0; xw; x++) insert_node(bmp_read16((uintptr_t)image->line[y]+x*sizeof(short)) & bitmask16); break; case 15: for (y=0; yh; y++) for (x=0; xw; x++) insert_node(bmp_read15((uintptr_t)image->line[y]+x*sizeof(short)) & bitmask15); break; default: return -1; } /* convert the 'hash_table' to array 'colors' */ colors = _AL_MALLOC((rsvduse + distinct) * sizeof(ITEM)); if (colors == NULL) { _AL_FREE(hash_table); return 0; } for (i = 0, j = rsvduse; icolor; colors[j++].key = node->count; node = node->next; } while (node != NULL); if (hash_table[i].next) delete_list(hash_table[i].next); } } _AL_FREE(hash_table); /* sort the list with biggest count first */ qsort(colors + rsvduse, distinct, sizeof(ITEM), qsort_helper_ITEM); /* we don't want to deal anymore with colors that are seldomly(?) used */ numcols = rsvduse + distinct; palsize = 256 - rsvdcnt + rsvduse; /* change the format of the color information to some faster one * (in fact to the 00BBBB?0 00GGGG?0 00RRRR?0). */ switch (imgdepth) { case 32: rshift = _rgb_r_shift_32 + 3; gshift = _rgb_g_shift_32 + 3; bshift = _rgb_b_shift_32 + 3; break; case 24: rshift = _rgb_r_shift_24 + 3; gshift = _rgb_g_shift_24 + 3; bshift = _rgb_b_shift_24 + 3; break; case 16: rshift = _rgb_r_shift_16; gshift = _rgb_g_shift_16 + 1; bshift = _rgb_b_shift_16; break; case 15: rshift = _rgb_r_shift_15; gshift = _rgb_g_shift_15; bshift = _rgb_b_shift_15; break; default: return -1; } for (i = rsvduse; i < numcols; i++) { int r = (colors[i].color >> rshift) & 0x1F; int g = (colors[i].color >> gshift) & 0x1F; int b = (colors[i].color >> bshift) & 0x1F; colors[i].color = ((r << 1) | (g << 9) | (b << 17)); } do { int start, k; /* there may be only small number of numcols colors, so we don't need * any optimization */ if (numcols <= palsize) break; if (rsvduse > 0) { /* copy 'rsvd' to the 'colors' */ for (i = 0, j = 0; i < rsvduse; j++) if (rsvdcols[j] > 0) colors[i++].color = (pal[j].r | (pal[j].g << 8) | (pal[j].b << 16)); /* reduce 'colors' skipping colors contained in 'rsvd' palette */ for (i = rsvduse, j = i; i < numcols; i++) if (no_such_color(colors, rsvduse, colors[i].color, prec_mask)) colors[j++].color = colors[i].color; /* now there are j colors in 'common' */ numcols = j; /* now there might be enough free cells in palette */ if (numcols <= palsize) break; } /* from 'start' will start swapping colors */ start = palsize - palsize / fraction; /* it may be slow, so don't let replace too many colors */ if (start < (palsize - maxswaps)) start = palsize - maxswaps; /* swap not less than 10 colors */ if (start > (palsize - 10)) start = rsvduse; /* don't swap reserved colors */ if (start < rsvduse) start = rsvduse; if (bitsperrgb == 5) { /* do second pass on the colors we'll possibly use to replace (lower bits per pixel to 4) - this would effectively lower the maximum number of different colors to some 4000 (from 32000) */ for (i = start, k = i; i < numcols; i++) { for (j = 0; j < k; j++) { if ((colors[j].color & prec_mask2) == (colors[i].color & prec_mask2)) { j = -1; break; } } /* add this color if there is not similar one */ if (j != -1) colors[k++].color = colors[i].color; } /* now there are k colors in 'common' */ numcols = k; /* now there might be enough free cells in palette */ if (numcols <= palsize) break; } /* start finding the most different colors */ optimize_colors(colors, start, palsize, numcols, mindiff); numcols = palsize; } while (0); /* copy used colors to 'pal', skipping 'rsvd' */ for (i = rsvduse, j = 0; i < numcols; j++) if (!rsvdcols[j]) copy_color(&pal[j], colors[i++].color); _AL_FREE(colors); return distinct; } int generate_optimized_palette(BITMAP *image, PALETTE pal, AL_CONST signed char rsvdcols[PAL_SIZE]) { ASSERT(image); return generate_optimized_palette_ex(image, pal, rsvdcols, DEFAULT_PREC, DEFAULT_FRACTION, DEFAULT_MAXSWAPS, DEFAULT_MINDIFF); } allegro-4.4.3.1/src/poly3d.c0000664000175000017500000015022513437077643014452 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The 3d polygon rasteriser. * * By Shawn Hargreaves. * * Hicolor support added by Przemek Podsiadly. Complete support for * all drawing modes in every color depth MMX optimisations and z-buffer * added by Calin Andrian. Subpixel and subtexel accuracy, triangle * functions and speed enhancements added by Bertrand Coconnier. * Functions adapted to handle two coincident vertices by Ben Davis. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #if defined ALLEGRO_ASMCAPA_HEADER && !defined ALLEGRO_NO_ASM #include ALLEGRO_ASMCAPA_HEADER #endif #ifdef ALLEGRO_MMX /* for use by iscan.s */ uint32_t _mask_mmx_15[] = { 0x03E0001F, 0x007C }; uint32_t _mask_mmx_16[] = { 0x07E0001F, 0x00F8 }; #endif void _poly_scanline_dummy(uintptr_t addr, int w, POLYGON_SEGMENT *info) { } ZBUFFER *_zbuffer = NULL; SCANLINE_FILLER _optim_alternative_drawer; /* _fill_3d_edge_structure: * Polygon helper function: initialises an edge structure for the 3d * rasterising code, using fixed point vertex structures. Returns 1 on * success, or 0 if the edge is horizontal or clipped out of existence. */ int _fill_3d_edge_structure(POLYGON_EDGE *edge, AL_CONST V3D *v1, AL_CONST V3D *v2, int flags, BITMAP *bmp) { int r1, r2, g1, g2, b1, b2; fixed h, step; /* swap vertices if they are the wrong way up */ if (v2->y < v1->y) { AL_CONST V3D *vt; vt = v1; v1 = v2; v2 = vt; } /* set up screen rasterising parameters */ edge->top = fixceil(v1->y); edge->bottom = fixceil(v2->y) - 1; if (edge->bottom < edge->top) return 0; h = v2->y - v1->y; step = (edge->top << 16) - v1->y; edge->dx = fixdiv(v2->x - v1->x, h); edge->x = v1->x + fixmul(step, edge->dx); edge->prev = NULL; edge->next = NULL; edge->w = 0; if (flags & INTERP_Z) { float h1 = 65536. / h; float step_f = fixtof(step); /* Z (depth) interpolation */ float z1 = 65536. / v1->z; float z2 = 65536. / v2->z; edge->dat.dz = (z2 - z1) * h1; edge->dat.z = z1 + edge->dat.dz * step_f; if (flags & INTERP_FLOAT_UV) { /* floating point (perspective correct) texture interpolation */ float fu1 = v1->u * z1; float fv1 = v1->v * z1; float fu2 = v2->u * z2; float fv2 = v2->v * z2; edge->dat.dfu = (fu2 - fu1) * h1; edge->dat.dfv = (fv2 - fv1) * h1; edge->dat.fu = fu1 + edge->dat.dfu * step_f; edge->dat.fv = fv1 + edge->dat.dfv * step_f; } } if (flags & INTERP_FLAT) { /* if clipping is enabled then clip edge */ if (bmp->clip) { if (edge->top < bmp->ct) { edge->x += (bmp->ct - edge->top) * edge->dx; edge->top = bmp->ct; } if (edge->bottom >= bmp->cb) edge->bottom = bmp->cb - 1; } return (edge->bottom >= edge->top); } if (flags & INTERP_1COL) { /* single color shading interpolation */ edge->dat.dc = fixdiv(itofix(v2->c - v1->c), h); edge->dat.c = itofix(v1->c) + fixmul(step, edge->dat.dc); } if (flags & INTERP_3COL) { /* RGB shading interpolation */ if (flags & COLOR_TO_RGB) { AL_CONST int coldepth = bitmap_color_depth(bmp); r1 = getr_depth(coldepth, v1->c); r2 = getr_depth(coldepth, v2->c); g1 = getg_depth(coldepth, v1->c); g2 = getg_depth(coldepth, v2->c); b1 = getb_depth(coldepth, v1->c); b2 = getb_depth(coldepth, v2->c); } else { r1 = (v1->c >> 16) & 0xFF; r2 = (v2->c >> 16) & 0xFF; g1 = (v1->c >> 8) & 0xFF; g2 = (v2->c >> 8) & 0xFF; b1 = v1->c & 0xFF; b2 = v2->c & 0xFF; } edge->dat.dr = fixdiv(itofix(r2 - r1), h); edge->dat.dg = fixdiv(itofix(g2 - g1), h); edge->dat.db = fixdiv(itofix(b2 - b1), h); edge->dat.r = itofix(r1) + fixmul(step, edge->dat.dr); edge->dat.g = itofix(g1) + fixmul(step, edge->dat.dg); edge->dat.b = itofix(b1) + fixmul(step, edge->dat.db); } if (flags & INTERP_FIX_UV) { /* fixed point (affine) texture interpolation */ edge->dat.du = fixdiv(v2->u - v1->u, h); edge->dat.dv = fixdiv(v2->v - v1->v, h); edge->dat.u = v1->u + fixmul(step, edge->dat.du); edge->dat.v = v1->v + fixmul(step, edge->dat.dv); } /* if clipping is enabled then clip edge */ if (bmp->clip) { if (edge->top < bmp->ct) { int gap = bmp->ct - edge->top; edge->top = bmp->ct; edge->x += gap * edge->dx; _clip_polygon_segment(&(edge->dat), itofix(gap), flags); } if (edge->bottom >= bmp->cb) edge->bottom = bmp->cb - 1; } return (edge->bottom >= edge->top); } /* _fill_3d_edge_structure_f: * Polygon helper function: initialises an edge structure for the 3d * rasterising code, using floating point vertex structures. Returns 1 on * success, or 0 if the edge is horizontal or clipped out of existence. */ int _fill_3d_edge_structure_f(POLYGON_EDGE *edge, AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, int flags, BITMAP *bmp) { int r1, r2, g1, g2, b1, b2; fixed h, step; float h1; /* swap vertices if they are the wrong way up */ if (v2->y < v1->y) { AL_CONST V3D_f *vt; vt = v1; v1 = v2; v2 = vt; } /* set up screen rasterising parameters */ edge->top = fixceil(ftofix(v1->y)); edge->bottom = fixceil(ftofix(v2->y)) - 1; if (edge->bottom < edge->top) return 0; h1 = 1.0 / (v2->y - v1->y); h = ftofix(v2->y - v1->y); step = (edge->top << 16) - ftofix(v1->y); edge->dx = ftofix((v2->x - v1->x) * h1); edge->x = ftofix(v1->x) + fixmul(step, edge->dx); edge->prev = NULL; edge->next = NULL; edge->w = 0; if (flags & INTERP_Z) { float step_f = fixtof(step); /* Z (depth) interpolation */ float z1 = 1. / v1->z; float z2 = 1. / v2->z; edge->dat.dz = (z2 - z1) * h1; edge->dat.z = z1 + edge->dat.dz * step_f; if (flags & INTERP_FLOAT_UV) { /* floating point (perspective correct) texture interpolation */ float fu1 = v1->u * z1 * 65536.; float fv1 = v1->v * z1 * 65536.; float fu2 = v2->u * z2 * 65536.; float fv2 = v2->v * z2 * 65536.; edge->dat.dfu = (fu2 - fu1) * h1; edge->dat.dfv = (fv2 - fv1) * h1; edge->dat.fu = fu1 + edge->dat.dfu * step_f; edge->dat.fv = fv1 + edge->dat.dfv * step_f; } } if (flags & INTERP_FLAT) { /* if clipping is enabled then clip edge */ if (bmp->clip) { if (edge->top < bmp->ct) { edge->x += (bmp->ct - edge->top) * edge->dx; edge->top = bmp->ct; } if (edge->bottom >= bmp->cb) edge->bottom = bmp->cb - 1; } return (edge->bottom >= edge->top); } if (flags & INTERP_1COL) { /* single color shading interpolation */ edge->dat.dc = fixdiv(itofix(v2->c - v1->c), h); edge->dat.c = itofix(v1->c) + fixmul(step, edge->dat.dc); } if (flags & INTERP_3COL) { /* RGB shading interpolation */ if (flags & COLOR_TO_RGB) { AL_CONST int coldepth = bitmap_color_depth(bmp); r1 = getr_depth(coldepth, v1->c); r2 = getr_depth(coldepth, v2->c); g1 = getg_depth(coldepth, v1->c); g2 = getg_depth(coldepth, v2->c); b1 = getb_depth(coldepth, v1->c); b2 = getb_depth(coldepth, v2->c); } else { r1 = (v1->c >> 16) & 0xFF; r2 = (v2->c >> 16) & 0xFF; g1 = (v1->c >> 8) & 0xFF; g2 = (v2->c >> 8) & 0xFF; b1 = v1->c & 0xFF; b2 = v2->c & 0xFF; } edge->dat.dr = fixdiv(itofix(r2 - r1), h); edge->dat.dg = fixdiv(itofix(g2 - g1), h); edge->dat.db = fixdiv(itofix(b2 - b1), h); edge->dat.r = itofix(r1) + fixmul(step, edge->dat.dr); edge->dat.g = itofix(g1) + fixmul(step, edge->dat.dg); edge->dat.b = itofix(b1) + fixmul(step, edge->dat.db); } if (flags & INTERP_FIX_UV) { /* fixed point (affine) texture interpolation */ edge->dat.du = ftofix((v2->u - v1->u) * h1); edge->dat.dv = ftofix((v2->v - v1->v) * h1); edge->dat.u = ftofix(v1->u) + fixmul(step, edge->dat.du); edge->dat.v = ftofix(v1->v) + fixmul(step, edge->dat.dv); } /* if clipping is enabled then clip edge */ if (bmp->clip) { if (edge->top < bmp->ct) { int gap = bmp->ct - edge->top; edge->top = bmp->ct; edge->x += gap * edge->dx; _clip_polygon_segment_f(&(edge->dat), gap, flags); } if (edge->bottom >= bmp->cb) edge->bottom = bmp->cb - 1; } return (edge->bottom >= edge->top); } /* _get_scanline_filler: * Helper function for deciding which rasterisation function and * interpolation flags we should use for a specific polygon type. */ SCANLINE_FILLER _get_scanline_filler(int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp) { typedef struct POLYTYPE_INFO { SCANLINE_FILLER filler; SCANLINE_FILLER alternative; } POLYTYPE_INFO; static int polytype_interp_pal[] = { INTERP_FLAT, INTERP_1COL, INTERP_3COL, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV | INTERP_1COL, INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV | INTERP_1COL, INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX }; static int polytype_interp_tc[] = { INTERP_FLAT, INTERP_3COL | COLOR_TO_RGB, INTERP_3COL, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV | INTERP_1COL, INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV | INTERP_1COL, INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX, INTERP_FIX_UV, INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX }; #ifdef ALLEGRO_COLOR8 static POLYTYPE_INFO polytype_info8[] = { { _poly_scanline_dummy, NULL }, { _poly_scanline_gcol8, NULL }, { _poly_scanline_grgb8, NULL }, { _poly_scanline_atex8, NULL }, { _poly_scanline_ptex8, _poly_scanline_atex8 }, { _poly_scanline_atex_mask8, NULL }, { _poly_scanline_ptex_mask8, _poly_scanline_atex_mask8 }, { _poly_scanline_atex_lit8, NULL }, { _poly_scanline_ptex_lit8, _poly_scanline_atex_lit8 }, { _poly_scanline_atex_mask_lit8, NULL }, { _poly_scanline_ptex_mask_lit8, _poly_scanline_atex_mask_lit8 }, { _poly_scanline_atex_trans8, NULL }, { _poly_scanline_ptex_trans8, _poly_scanline_atex_trans8 }, { _poly_scanline_atex_mask_trans8, NULL }, { _poly_scanline_ptex_mask_trans8, _poly_scanline_atex_mask_trans8 } }; #ifdef ALLEGRO_MMX static POLYTYPE_INFO polytype_info8x[] = { { NULL, NULL }, { NULL, NULL }, { _poly_scanline_grgb8x, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; static POLYTYPE_INFO polytype_info8d[] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; #endif #endif #ifdef ALLEGRO_COLOR16 static POLYTYPE_INFO polytype_info15[] = { { _poly_scanline_dummy, NULL }, { _poly_scanline_grgb15, NULL }, { _poly_scanline_grgb15, NULL }, { _poly_scanline_atex16, NULL }, { _poly_scanline_ptex16, _poly_scanline_atex16 }, { _poly_scanline_atex_mask15, NULL }, { _poly_scanline_ptex_mask15, _poly_scanline_atex_mask15 }, { _poly_scanline_atex_lit15, NULL }, { _poly_scanline_ptex_lit15, _poly_scanline_atex_lit15 }, { _poly_scanline_atex_mask_lit15, NULL }, { _poly_scanline_ptex_mask_lit15, _poly_scanline_atex_mask_lit15 }, { _poly_scanline_atex_trans15, NULL }, { _poly_scanline_ptex_trans15, _poly_scanline_atex_trans15 }, { _poly_scanline_atex_mask_trans15, NULL }, { _poly_scanline_ptex_mask_trans15, _poly_scanline_atex_mask_trans15 } }; #ifdef ALLEGRO_MMX static POLYTYPE_INFO polytype_info15x[] = { { NULL, NULL }, { _poly_scanline_grgb15x, NULL }, { _poly_scanline_grgb15x, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_atex_lit15x, NULL }, { _poly_scanline_ptex_lit15x, _poly_scanline_atex_lit15x }, { _poly_scanline_atex_mask_lit15x, NULL }, { _poly_scanline_ptex_mask_lit15x, _poly_scanline_atex_mask_lit15x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; static POLYTYPE_INFO polytype_info15d[] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_ptex_lit15d, _poly_scanline_atex_lit15x }, { NULL, NULL }, { _poly_scanline_ptex_mask_lit15d, _poly_scanline_atex_mask_lit15x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; #endif static POLYTYPE_INFO polytype_info16[] = { { _poly_scanline_dummy, NULL }, { _poly_scanline_grgb16, NULL }, { _poly_scanline_grgb16, NULL }, { _poly_scanline_atex16, NULL }, { _poly_scanline_ptex16, _poly_scanline_atex16 }, { _poly_scanline_atex_mask16, NULL }, { _poly_scanline_ptex_mask16, _poly_scanline_atex_mask16 }, { _poly_scanline_atex_lit16, NULL }, { _poly_scanline_ptex_lit16, _poly_scanline_atex_lit16 }, { _poly_scanline_atex_mask_lit16, NULL }, { _poly_scanline_ptex_mask_lit16, _poly_scanline_atex_mask_lit16 }, { _poly_scanline_atex_trans16, NULL }, { _poly_scanline_ptex_trans16, _poly_scanline_atex_trans16 }, { _poly_scanline_atex_mask_trans16, NULL }, { _poly_scanline_ptex_mask_trans16, _poly_scanline_atex_mask_trans16 } }; #ifdef ALLEGRO_MMX static POLYTYPE_INFO polytype_info16x[] = { { NULL, NULL }, { _poly_scanline_grgb16x, NULL }, { _poly_scanline_grgb16x, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_atex_lit16x, NULL }, { _poly_scanline_ptex_lit16x, _poly_scanline_atex_lit16x }, { _poly_scanline_atex_mask_lit16x, NULL }, { _poly_scanline_ptex_mask_lit16x, _poly_scanline_atex_mask_lit16x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; static POLYTYPE_INFO polytype_info16d[] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_ptex_lit16d, _poly_scanline_atex_lit16x }, { NULL, NULL }, { _poly_scanline_ptex_mask_lit16d, _poly_scanline_atex_mask_lit16x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; #endif #endif #ifdef ALLEGRO_COLOR24 static POLYTYPE_INFO polytype_info24[] = { { _poly_scanline_dummy, NULL }, { _poly_scanline_grgb24, NULL }, { _poly_scanline_grgb24, NULL }, { _poly_scanline_atex24, NULL }, { _poly_scanline_ptex24, _poly_scanline_atex24 }, { _poly_scanline_atex_mask24, NULL }, { _poly_scanline_ptex_mask24, _poly_scanline_atex_mask24 }, { _poly_scanline_atex_lit24, NULL }, { _poly_scanline_ptex_lit24, _poly_scanline_atex_lit24 }, { _poly_scanline_atex_mask_lit24, NULL }, { _poly_scanline_ptex_mask_lit24, _poly_scanline_atex_mask_lit24 }, { _poly_scanline_atex_trans24, NULL }, { _poly_scanline_ptex_trans24, _poly_scanline_atex_trans24 }, { _poly_scanline_atex_mask_trans24, NULL }, { _poly_scanline_ptex_mask_trans24, _poly_scanline_atex_mask_trans24 } }; #ifdef ALLEGRO_MMX static POLYTYPE_INFO polytype_info24x[] = { { NULL, NULL }, { _poly_scanline_grgb24x, NULL }, { _poly_scanline_grgb24x, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_atex_lit24x, NULL }, { _poly_scanline_ptex_lit24x, _poly_scanline_atex_lit24x }, { _poly_scanline_atex_mask_lit24x, NULL }, { _poly_scanline_ptex_mask_lit24x, _poly_scanline_atex_mask_lit24x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; static POLYTYPE_INFO polytype_info24d[] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_ptex_lit24d, _poly_scanline_atex_lit24x }, { NULL, NULL }, { _poly_scanline_ptex_mask_lit24d, _poly_scanline_atex_mask_lit24x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; #endif #endif #ifdef ALLEGRO_COLOR32 static POLYTYPE_INFO polytype_info32[] = { { _poly_scanline_dummy, NULL }, { _poly_scanline_grgb32, NULL }, { _poly_scanline_grgb32, NULL }, { _poly_scanline_atex32, NULL }, { _poly_scanline_ptex32, _poly_scanline_atex32 }, { _poly_scanline_atex_mask32, NULL }, { _poly_scanline_ptex_mask32, _poly_scanline_atex_mask32 }, { _poly_scanline_atex_lit32, NULL }, { _poly_scanline_ptex_lit32, _poly_scanline_atex_lit32 }, { _poly_scanline_atex_mask_lit32, NULL }, { _poly_scanline_ptex_mask_lit32, _poly_scanline_atex_mask_lit32 }, { _poly_scanline_atex_trans32, NULL }, { _poly_scanline_ptex_trans32, _poly_scanline_atex_trans32 }, { _poly_scanline_atex_mask_trans32, NULL }, { _poly_scanline_ptex_mask_trans32, _poly_scanline_atex_mask_trans32 } }; #ifdef ALLEGRO_MMX static POLYTYPE_INFO polytype_info32x[] = { { NULL, NULL }, { _poly_scanline_grgb32x, NULL }, { _poly_scanline_grgb32x, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_atex_lit32x, NULL }, { _poly_scanline_ptex_lit32x, _poly_scanline_atex_lit32x }, { _poly_scanline_atex_mask_lit32x, NULL }, { _poly_scanline_ptex_mask_lit32x, _poly_scanline_atex_mask_lit32x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; static POLYTYPE_INFO polytype_info32d[] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { _poly_scanline_ptex_lit32d, _poly_scanline_atex_lit32x }, { NULL, NULL }, { _poly_scanline_ptex_mask_lit32d, _poly_scanline_atex_mask_lit32x }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; #endif #endif #ifdef ALLEGRO_COLOR8 static POLYTYPE_INFO polytype_info8z[] = { { _poly_zbuf_flat8, NULL }, { _poly_zbuf_gcol8, NULL }, { _poly_zbuf_grgb8, NULL }, { _poly_zbuf_atex8, NULL }, { _poly_zbuf_ptex8, _poly_zbuf_atex8 }, { _poly_zbuf_atex_mask8, NULL }, { _poly_zbuf_ptex_mask8, _poly_zbuf_atex_mask8 }, { _poly_zbuf_atex_lit8, NULL }, { _poly_zbuf_ptex_lit8, _poly_zbuf_atex_lit8 }, { _poly_zbuf_atex_mask_lit8, NULL }, { _poly_zbuf_ptex_mask_lit8, _poly_zbuf_atex_mask_lit8 }, { _poly_zbuf_atex_trans8, NULL }, { _poly_zbuf_ptex_trans8, _poly_zbuf_atex_trans8 }, { _poly_zbuf_atex_mask_trans8, NULL }, { _poly_zbuf_ptex_mask_trans8, _poly_zbuf_atex_mask_trans8 } }; #endif #ifdef ALLEGRO_COLOR16 static POLYTYPE_INFO polytype_info15z[] = { { _poly_zbuf_flat16, NULL }, { _poly_zbuf_grgb15, NULL }, { _poly_zbuf_grgb15, NULL }, { _poly_zbuf_atex16, NULL }, { _poly_zbuf_ptex16, _poly_zbuf_atex16 }, { _poly_zbuf_atex_mask15, NULL }, { _poly_zbuf_ptex_mask15, _poly_zbuf_atex_mask15 }, { _poly_zbuf_atex_lit15, NULL }, { _poly_zbuf_ptex_lit15, _poly_zbuf_atex_lit15 }, { _poly_zbuf_atex_mask_lit15, NULL }, { _poly_zbuf_ptex_mask_lit15, _poly_zbuf_atex_mask_lit15 }, { _poly_zbuf_atex_trans15, NULL }, { _poly_zbuf_ptex_trans15, _poly_zbuf_atex_trans15 }, { _poly_zbuf_atex_mask_trans15, NULL }, { _poly_zbuf_ptex_mask_trans15, _poly_zbuf_atex_mask_trans15 } }; static POLYTYPE_INFO polytype_info16z[] = { { _poly_zbuf_flat16, NULL }, { _poly_zbuf_grgb16, NULL }, { _poly_zbuf_grgb16, NULL }, { _poly_zbuf_atex16, NULL }, { _poly_zbuf_ptex16, _poly_zbuf_atex16 }, { _poly_zbuf_atex_mask16, NULL }, { _poly_zbuf_ptex_mask16, _poly_zbuf_atex_mask16 }, { _poly_zbuf_atex_lit16, NULL }, { _poly_zbuf_ptex_lit16, _poly_zbuf_atex_lit16 }, { _poly_zbuf_atex_mask_lit16, NULL }, { _poly_zbuf_ptex_mask_lit16, _poly_zbuf_atex_mask_lit16 }, { _poly_zbuf_atex_trans16, NULL }, { _poly_zbuf_ptex_trans16, _poly_zbuf_atex_trans16 }, { _poly_zbuf_atex_mask_trans16, NULL }, { _poly_zbuf_ptex_mask_trans16, _poly_zbuf_atex_mask_trans16 } }; #endif #ifdef ALLEGRO_COLOR24 static POLYTYPE_INFO polytype_info24z[] = { { _poly_zbuf_flat24, NULL }, { _poly_zbuf_grgb24, NULL }, { _poly_zbuf_grgb24, NULL }, { _poly_zbuf_atex24, NULL }, { _poly_zbuf_ptex24, _poly_zbuf_atex24 }, { _poly_zbuf_atex_mask24, NULL }, { _poly_zbuf_ptex_mask24, _poly_zbuf_atex_mask24 }, { _poly_zbuf_atex_lit24, NULL }, { _poly_zbuf_ptex_lit24, _poly_zbuf_atex_lit24 }, { _poly_zbuf_atex_mask_lit24, NULL }, { _poly_zbuf_ptex_mask_lit24, _poly_zbuf_atex_mask_lit24 }, { _poly_zbuf_atex_trans24, NULL }, { _poly_zbuf_ptex_trans24, _poly_zbuf_atex_trans24 }, { _poly_zbuf_atex_mask_trans24, NULL }, { _poly_zbuf_ptex_mask_trans24, _poly_zbuf_atex_mask_trans24 } }; #endif #ifdef ALLEGRO_COLOR32 static POLYTYPE_INFO polytype_info32z[] = { { _poly_zbuf_flat32, NULL }, { _poly_zbuf_grgb32, NULL }, { _poly_zbuf_grgb32, NULL }, { _poly_zbuf_atex32, NULL }, { _poly_zbuf_ptex32, _poly_zbuf_atex32 }, { _poly_zbuf_atex_mask32, NULL }, { _poly_zbuf_ptex_mask32, _poly_zbuf_atex_mask32 }, { _poly_zbuf_atex_lit32, NULL }, { _poly_zbuf_ptex_lit32, _poly_zbuf_atex_lit32 }, { _poly_zbuf_atex_mask_lit32, NULL }, { _poly_zbuf_ptex_mask_lit32, _poly_zbuf_atex_mask_lit32 }, { _poly_zbuf_atex_trans32, NULL }, { _poly_zbuf_ptex_trans32, _poly_zbuf_atex_trans32 }, { _poly_zbuf_atex_mask_trans32, NULL }, { _poly_zbuf_ptex_mask_trans32, _poly_zbuf_atex_mask_trans32 } }; #endif int zbuf = type & POLYTYPE_ZBUF; int *interpinfo; POLYTYPE_INFO *typeinfo, *typeinfo_zbuf; #ifdef ALLEGRO_MMX POLYTYPE_INFO *typeinfo_mmx, *typeinfo_3d; #endif switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: interpinfo = polytype_interp_pal; typeinfo = polytype_info8; #ifdef ALLEGRO_MMX typeinfo_mmx = polytype_info8x; typeinfo_3d = polytype_info8d; #endif typeinfo_zbuf = polytype_info8z; break; #endif #ifdef ALLEGRO_COLOR16 case 15: interpinfo = polytype_interp_tc; typeinfo = polytype_info15; #ifdef ALLEGRO_MMX typeinfo_mmx = polytype_info15x; typeinfo_3d = polytype_info15d; #endif typeinfo_zbuf = polytype_info15z; break; case 16: interpinfo = polytype_interp_tc; typeinfo = polytype_info16; #ifdef ALLEGRO_MMX typeinfo_mmx = polytype_info16x; typeinfo_3d = polytype_info16d; #endif typeinfo_zbuf = polytype_info16z; break; #endif #ifdef ALLEGRO_COLOR24 case 24: interpinfo = polytype_interp_tc; typeinfo = polytype_info24; #ifdef ALLEGRO_MMX typeinfo_mmx = polytype_info24x; typeinfo_3d = polytype_info24d; #endif typeinfo_zbuf = polytype_info24z; break; #endif #ifdef ALLEGRO_COLOR32 case 32: interpinfo = polytype_interp_tc; typeinfo = polytype_info32; #ifdef ALLEGRO_MMX typeinfo_mmx = polytype_info32x; typeinfo_3d = polytype_info32d; #endif typeinfo_zbuf = polytype_info32z; break; #endif default: return NULL; } type = CLAMP(0, type & ~POLYTYPE_ZBUF, POLYTYPE_MAX-1); *flags = interpinfo[type]; if (texture) { info->texture = texture->line[0]; info->umask = texture->w - 1; info->vmask = texture->h - 1; info->vshift = 0; while ((1 << info->vshift) < texture->w) info->vshift++; } else { info->texture = NULL; info->umask = info->vmask = info->vshift = 0; } info->seg = bmp->seg; bmp_select(bmp); if (zbuf) { *flags |= INTERP_Z + INTERP_ZBUF; _optim_alternative_drawer = typeinfo_zbuf[type].alternative; return typeinfo_zbuf[type].filler; } #ifdef ALLEGRO_MMX if ((cpu_capabilities & CPU_MMX) && (typeinfo_mmx[type].filler)) { if ((cpu_capabilities & CPU_3DNOW) && (typeinfo_3d[type].filler)) { _optim_alternative_drawer = typeinfo_3d[type].alternative; return typeinfo_3d[type].filler; } _optim_alternative_drawer = typeinfo_mmx[type].alternative; return typeinfo_mmx[type].filler; } #endif _optim_alternative_drawer = typeinfo[type].alternative; return typeinfo[type].filler; } /* _clip_polygon_segment_f: * Updates interpolation state values when skipping several places, eg. * clipping the first part of a scanline. */ void _clip_polygon_segment_f(POLYGON_SEGMENT *info, int gap, int flags) { if (flags & INTERP_1COL) info->c += info->dc * gap; if (flags & INTERP_3COL) { info->r += info->dr * gap; info->g += info->dg * gap; info->b += info->db * gap; } if (flags & INTERP_FIX_UV) { info->u += info->du * gap; info->v += info->dv * gap; } if (flags & INTERP_Z) { info->z += info->dz * gap; if (flags & INTERP_FLOAT_UV) { info->fu += info->dfu * gap; info->fv += info->dfv * gap; } } } /* draw_polygon_segment: * Polygon helper function to fill a scanline. Calculates deltas for * whichever values need interpolating, clips the segment, and then calls * the lowlevel scanline filler. */ static void draw_polygon_segment(BITMAP *bmp, int ytop, int ybottom, POLYGON_EDGE *e1, POLYGON_EDGE *e2, SCANLINE_FILLER drawer, int flags, int color, POLYGON_SEGMENT *info) { int x, y, w, gap; fixed step, width; POLYGON_SEGMENT *s1, *s2; AL_CONST SCANLINE_FILLER save_drawer = drawer; /* ensure that e1 is the left edge and e2 is the right edge */ if ((e2->x < e1->x) || ((e1->x == e2->x) && (e2->dx < e1->dx))) { POLYGON_EDGE *et = e1; e1 = e2; e2 = et; } s1 = &(e1->dat); s2 = &(e2->dat); if (flags & INTERP_FLAT) info->c = color; /* for each scanline in the polygon... */ for (y=ytop; y<=ybottom; y++) { x = fixceil(e1->x); w = fixceil(e2->x) - x; drawer = save_drawer; if (drawer == _poly_scanline_dummy) { if (w > 0) bmp->vtable->hfill(bmp, x, y, x+w-1, color); } else { step = (x << 16) - e1->x; width = e2->x - e1->x; /* * Nasty trick : * In order to avoid divisions by zero, width is set to -1. This way s1 and s2 * are still being updated but the scanline is not drawn since w == 0. */ if (width == 0) width = -1 << 16; /* * End of nasty trick. */ if (flags & INTERP_1COL) { info->dc = fixdiv(s2->c - s1->c, width); info->c = s1->c + fixmul(step, info->dc); s1->c += s1->dc; s2->c += s2->dc; } if (flags & INTERP_3COL) { info->dr = fixdiv(s2->r - s1->r, width); info->dg = fixdiv(s2->g - s1->g, width); info->db = fixdiv(s2->b - s1->b, width); info->r = s1->r + fixmul(step, info->dr); info->g = s1->g + fixmul(step, info->dg); info->b = s1->b + fixmul(step, info->db); s1->r += s1->dr; s2->r += s2->dr; s1->g += s1->dg; s2->g += s2->dg; s1->b += s1->db; s2->b += s2->db; } if (flags & INTERP_FIX_UV) { info->du = fixdiv(s2->u - s1->u, width); info->dv = fixdiv(s2->v - s1->v, width); info->u = s1->u + fixmul(step, info->du); info->v = s1->v + fixmul(step, info->dv); s1->u += s1->du; s2->u += s2->du; s1->v += s1->dv; s2->v += s2->dv; } if (flags & INTERP_Z) { float step_f = fixtof(step); float w1 = 65536. / width; info->dz = (s2->z - s1->z) * w1; info->z = s1->z + info->dz * step_f; s1->z += s1->dz; s2->z += s2->dz; if (flags & INTERP_FLOAT_UV) { info->dfu = (s2->fu - s1->fu) * w1; info->dfv = (s2->fv - s1->fv) * w1; info->fu = s1->fu + info->dfu * step_f; info->fv = s1->fv + info->dfv * step_f; s1->fu += s1->dfu; s2->fu += s2->dfu; s1->fv += s1->dfv; s2->fv += s2->dfv; } } /* if clipping is enabled then clip the segment */ if (bmp->clip) { if (x < bmp->cl) { gap = bmp->cl - x; x = bmp->cl; w -= gap; _clip_polygon_segment_f(info, gap, flags); } if (x+w > bmp->cr) w = bmp->cr - x; } if (w > 0) { int dx = x * BYTES_PER_PIXEL(bitmap_color_depth(bmp)); if ((flags & OPT_FLOAT_UV_TO_FIX) && (info->dz == 0)) { float z1 = 1. / info->z; info->u = info->fu * z1; info->v = info->fv * z1; info->du = info->dfu * z1; info->dv = info->dfv * z1; drawer = _optim_alternative_drawer; } if (flags & INTERP_ZBUF) info->zbuf_addr = bmp_write_line(_zbuffer, y) + x * sizeof(float); info->read_addr = bmp_read_line(bmp, y) + dx; drawer(bmp_write_line(bmp, y) + dx, w, info); } } e1->x += e1->dx; e2->x += e2->dx; } } /* do_polygon3d: * Helper function for rendering 3d polygon, used by both the fixed point * and floating point drawing functions. */ static void do_polygon3d(BITMAP *bmp, int top, int bottom, POLYGON_EDGE *left_edge, SCANLINE_FILLER drawer, int flags, int color, POLYGON_SEGMENT *info) { int ytop, ybottom; #ifdef ALLEGRO_DOS int old87 = 0; #endif POLYGON_EDGE *right_edge; ASSERT(bmp); /* set fpu to single-precision, truncate mode */ #ifdef ALLEGRO_DOS if (flags & (INTERP_Z | INTERP_FLOAT_UV)) old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC); #endif acquire_bitmap(bmp); if ((left_edge->prev != left_edge->next) && (left_edge->prev->top == top)) left_edge = left_edge->prev; right_edge = left_edge->next; ytop = top; for (;;) { if (right_edge->bottom <= left_edge->bottom) ybottom = right_edge->bottom; else ybottom = left_edge->bottom; /* fill the scanline */ draw_polygon_segment(bmp, ytop, ybottom, left_edge, right_edge, drawer, flags, color, info); if (ybottom >= bottom) break; /* update edges */ if (ybottom >= left_edge->bottom) left_edge = left_edge->prev; if (ybottom >= right_edge->bottom) right_edge = right_edge->next; ytop = ybottom + 1; } bmp_unwrite_line(bmp); release_bitmap(bmp); /* reset fpu mode */ #ifdef ALLEGRO_DOS if (flags & (INTERP_Z | INTERP_FLOAT_UV)) _control87(old87, MCW_PC | MCW_RC); #endif } /* polygon3d: * Draws a 3d polygon in the specified mode. The vertices parameter should * be followed by that many pointers to V3D structures, which describe each * vertex of the polygon. */ void _soft_polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]) { int c; int flags; int top = INT_MAX; int bottom = INT_MIN; V3D *v1, *v2; POLYGON_EDGE *edge, *edge0, *start_edge; POLYGON_EDGE *list_edges = NULL; POLYGON_SEGMENT info; SCANLINE_FILLER drawer; ASSERT(bmp); if (vc < 3) return; /* set up the drawing mode */ drawer = _get_scanline_filler(type, &flags, &info, texture, bmp); if (!drawer) return; /* allocate some space for the active edge table */ _grow_scratch_mem(sizeof(POLYGON_EDGE) * vc); start_edge = edge0 = edge = (POLYGON_EDGE *)_scratch_mem; /* fill the double-linked list of edges (order unimportant) */ v2 = vtx[vc-1]; for (c=0; ctop < top) { top = edge->top; start_edge = edge; } if (edge->bottom > bottom) bottom = edge->bottom; if (list_edges) { list_edges->next = edge; edge->prev = list_edges; } list_edges = edge; edge++; } } if (list_edges) { /* close the double-linked list */ edge0->prev = --edge; edge->next = edge0; /* render the polygon */ do_polygon3d(bmp, top, bottom, start_edge, drawer, flags, vtx[0]->c, &info); } } /* polygon3d_f: * Floating point version of polygon3d(). */ void _soft_polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]) { int c; int flags; int top = INT_MAX; int bottom = INT_MIN; V3D_f *v1, *v2; POLYGON_EDGE *edge, *edge0, *start_edge; POLYGON_EDGE *list_edges = NULL; POLYGON_SEGMENT info; SCANLINE_FILLER drawer; ASSERT(bmp); if (vc < 3) return; /* set up the drawing mode */ drawer = _get_scanline_filler(type, &flags, &info, texture, bmp); if (!drawer) return; /* allocate some space for the active edge table */ _grow_scratch_mem(sizeof(POLYGON_EDGE) * vc); start_edge = edge0 = edge = (POLYGON_EDGE *)_scratch_mem; /* fill the double-linked list of edges in clockwise order */ v2 = vtx[vc-1]; for (c=0; ctop < top) { top = edge->top; start_edge = edge; } if (edge->bottom > bottom) bottom = edge->bottom; if (list_edges) { list_edges->next = edge; edge->prev = list_edges; } list_edges = edge; edge++; } } if (list_edges) { /* close the double-linked list */ edge0->prev = --edge; edge->next = edge0; /* render the polygon */ do_polygon3d(bmp, top, bottom, start_edge, drawer, flags, vtx[0]->c, &info); } } /* draw_triangle_part: * Triangle helper function to fill a triangle part. Computes interpolation, * clips the segment, and then calls the lowlevel scanline filler. */ static void draw_triangle_part(BITMAP *bmp, int ytop, int ybottom, POLYGON_EDGE *left_edge, POLYGON_EDGE *right_edge, SCANLINE_FILLER drawer, int flags, int color, POLYGON_SEGMENT *info) { int x, y, w; int gap; AL_CONST int test_optim = (flags & OPT_FLOAT_UV_TO_FIX) && (info->dz == 0); fixed step; POLYGON_SEGMENT *s1; /* ensure that left_edge and right_edge are the right way round */ if ((right_edge->x < left_edge->x) || ((left_edge->x == right_edge->x) && (right_edge->dx < left_edge->dx))) { POLYGON_EDGE *other_edge = left_edge; left_edge = right_edge; right_edge = other_edge; } s1 = &(left_edge->dat); if (flags & INTERP_FLAT) info->c = color; for (y=ytop; y<=ybottom; y++) { x = fixceil(left_edge->x); w = fixceil(right_edge->x) - x; step = (x << 16) - left_edge->x; if (drawer == _poly_scanline_dummy) { if (w > 0) bmp->vtable->hfill(bmp, x, y, x+w-1, color); } else { if (flags & INTERP_1COL) { info->c = s1->c + fixmul(step, info->dc); s1->c += s1->dc; } if (flags & INTERP_3COL) { info->r = s1->r + fixmul(step, info->dr); info->g = s1->g + fixmul(step, info->dg); info->b = s1->b + fixmul(step, info->db); s1->r += s1->dr; s1->g += s1->dg; s1->b += s1->db; } if (flags & INTERP_FIX_UV) { info->u = s1->u + fixmul(step, info->du); info->v = s1->v + fixmul(step, info->dv); s1->u += s1->du; s1->v += s1->dv; } if (flags & INTERP_Z) { float step_f = fixtof(step); info->z = s1->z + info->dz * step_f; s1->z += s1->dz; if (flags & INTERP_FLOAT_UV) { info->fu = s1->fu + info->dfu * step_f; info->fv = s1->fv + info->dfv * step_f; s1->fu += s1->dfu; s1->fv += s1->dfv; } } /* if clipping is enabled then clip the segment */ if (bmp->clip) { if (x < bmp->cl) { gap = bmp->cl - x; x = bmp->cl; w -= gap; _clip_polygon_segment_f(info, gap, flags); } if (x+w > bmp->cr) w = bmp->cr - x; } if (w > 0) { int dx = x * BYTES_PER_PIXEL(bitmap_color_depth(bmp)); if (test_optim) { float z1 = 1. / info->z; info->u = info->fu * z1; info->v = info->fv * z1; info->du = info->dfu * z1; info->dv = info->dfv * z1; drawer = _optim_alternative_drawer; } if (flags & INTERP_ZBUF) info->zbuf_addr = bmp_write_line(_zbuffer, y) + x * sizeof(float); info->read_addr = bmp_read_line(bmp, y) + dx; drawer(bmp_write_line(bmp, y) + dx, w, info); } } left_edge->x += left_edge->dx; right_edge->x += right_edge->dx; } } /* _triangle_deltas: * Triangle3d helper function to calculate the deltas. (For triangles, * deltas are constant over the whole triangle). */ static void _triangle_deltas(BITMAP *bmp, fixed w, POLYGON_SEGMENT *s1, POLYGON_SEGMENT *info, AL_CONST V3D *v, int flags) { if (flags & INTERP_1COL) info->dc = fixdiv(s1->c - itofix(v->c), w); if (flags & INTERP_3COL) { int r, g, b; if (flags & COLOR_TO_RGB) { AL_CONST int coldepth = bitmap_color_depth(bmp); r = getr_depth(coldepth, v->c); g = getg_depth(coldepth, v->c); b = getb_depth(coldepth, v->c); } else { r = (v->c >> 16) & 0xFF; g = (v->c >> 8) & 0xFF; b = v->c & 0xFF; } info->dr = fixdiv(s1->r - itofix(r), w); info->dg = fixdiv(s1->g - itofix(g), w); info->db = fixdiv(s1->b - itofix(b), w); } if (flags & INTERP_FIX_UV) { info->du = fixdiv(s1->u - v->u, w); info->dv = fixdiv(s1->v - v->v, w); } if (flags & INTERP_Z) { float w1 = 65536. / w; /* Z (depth) interpolation */ float z1 = 65536. / v->z; info->dz = (s1->z - z1) * w1; if (flags & INTERP_FLOAT_UV) { /* floating point (perspective correct) texture interpolation */ float fu1 = v->u * z1; float fv1 = v->v * z1; info->dfu = (s1->fu - fu1) * w1; info->dfv = (s1->fv - fv1) * w1; } } } /* _triangle_deltas_f: * Floating point version of _triangle_deltas(). */ static void _triangle_deltas_f(BITMAP *bmp, fixed w, POLYGON_SEGMENT *s1, POLYGON_SEGMENT *info, AL_CONST V3D_f *v, int flags) { if (flags & INTERP_1COL) info->dc = fixdiv(s1->c - itofix(v->c), w); if (flags & INTERP_3COL) { int r, g, b; if (flags & COLOR_TO_RGB) { AL_CONST int coldepth = bitmap_color_depth(bmp); r = getr_depth(coldepth, v->c); g = getg_depth(coldepth, v->c); b = getb_depth(coldepth, v->c); } else { r = (v->c >> 16) & 0xFF; g = (v->c >> 8) & 0xFF; b = v->c & 0xFF; } info->dr = fixdiv(s1->r - itofix(r), w); info->dg = fixdiv(s1->g - itofix(g), w); info->db = fixdiv(s1->b - itofix(b), w); } if (flags & INTERP_FIX_UV) { info->du = fixdiv(s1->u - ftofix(v->u), w); info->dv = fixdiv(s1->v - ftofix(v->v), w); } if (flags & INTERP_Z) { float w1 = 65536. / w; /* Z (depth) interpolation */ float z1 = 1. / v->z; info->dz = (s1->z - z1) * w1; if (flags & INTERP_FLOAT_UV) { /* floating point (perspective correct) texture interpolation */ float fu1 = v->u * z1 * 65536.; float fv1 = v->v * z1 * 65536.; info->dfu = (s1->fu - fu1) * w1; info->dfv = (s1->fv - fv1) * w1; } } } /* _clip_polygon_segment: * Fixed point version of _clip_polygon_segment_f(). */ void _clip_polygon_segment(POLYGON_SEGMENT *info, fixed gap, int flags) { if (flags & INTERP_1COL) info->c += fixmul(info->dc, gap); if (flags & INTERP_3COL) { info->r += fixmul(info->dr, gap); info->g += fixmul(info->dg, gap); info->b += fixmul(info->db, gap); } if (flags & INTERP_FIX_UV) { info->u += fixmul(info->du, gap); info->v += fixmul(info->dv, gap); } if (flags & INTERP_Z) { float gap_f = fixtof(gap); info->z += info->dz * gap_f; if (flags & INTERP_FLOAT_UV) { info->fu += info->dfu * gap_f; info->fv += info->dfv * gap_f; } } } /* triangle3d: * Draws a 3d triangle. */ void _soft_triangle3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3) { int flags; #ifdef ALLEGRO_DOS int old87 = 0; #endif int color = v1->c; V3D *vt1, *vt2, *vt3; POLYGON_EDGE edge1, edge2; POLYGON_SEGMENT info; SCANLINE_FILLER drawer; ASSERT(bmp); /* set up the drawing mode */ drawer = _get_scanline_filler(type, &flags, &info, texture, bmp); if (!drawer) return; /* sort the vertices so that vt1->y <= vt2->y <= vt3->y */ if (v1->y > v2->y) { vt1 = v2; vt2 = v1; } else { vt1 = v1; vt2 = v2; } if (vt1->y > v3->y) { vt3 = vt1; vt1 = v3; } else vt3 = v3; if (vt2->y > vt3->y) { V3D* vtemp = vt2; vt2 = vt3; vt3 = vtemp; } /* set fpu to single-precision, truncate mode */ #ifdef ALLEGRO_DOS if (flags & (INTERP_Z | INTERP_FLOAT_UV)) old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC); #endif /* do 3D triangle*/ if (_fill_3d_edge_structure(&edge1, vt1, vt3, flags, bmp)) { acquire_bitmap(bmp); /* calculate deltas */ if (drawer != _poly_scanline_dummy) { fixed w, h; POLYGON_SEGMENT s1 = edge1.dat; h = vt2->y - (edge1.top << 16); _clip_polygon_segment(&s1, h, flags); w = edge1.x + fixmul(h, edge1.dx) - vt2->x; if (w) _triangle_deltas(bmp, w, &s1, &info, vt2, flags); } /* draws part between y1 and y2 */ if (_fill_3d_edge_structure(&edge2, vt1, vt2, flags, bmp)) draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info); /* draws part between y2 and y3 */ if (_fill_3d_edge_structure(&edge2, vt2, vt3, flags, bmp)) draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info); bmp_unwrite_line(bmp); release_bitmap(bmp); } /* reset fpu mode */ #ifdef ALLEGRO_DOS if (flags & (INTERP_Z | INTERP_FLOAT_UV)) _control87(old87, MCW_PC | MCW_RC); #endif } /* triangle3d_f: * Draws a 3d triangle. */ void _soft_triangle3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3) { int flags; #ifdef ALLEGRO_DOS int old87 = 0; #endif int color = v1->c; V3D_f *vt1, *vt2, *vt3; POLYGON_EDGE edge1, edge2; POLYGON_SEGMENT info; SCANLINE_FILLER drawer; ASSERT(bmp); /* set up the drawing mode */ drawer = _get_scanline_filler(type, &flags, &info, texture, bmp); if (!drawer) return; /* sort the vertices so that vt1->y <= vt2->y <= vt3->y */ if (v1->y > v2->y) { vt1 = v2; vt2 = v1; } else { vt1 = v1; vt2 = v2; } if (vt1->y > v3->y) { vt3 = vt1; vt1 = v3; } else vt3 = v3; if (vt2->y > vt3->y) { V3D_f* vtemp = vt2; vt2 = vt3; vt3 = vtemp; } /* set fpu to single-precision, truncate mode */ #ifdef ALLEGRO_DOS if (flags & (INTERP_Z | INTERP_FLOAT_UV)) old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC); #endif /* do 3D triangle*/ if (_fill_3d_edge_structure_f(&edge1, vt1, vt3, flags, bmp)) { acquire_bitmap(bmp); /* calculate deltas */ if (drawer != _poly_scanline_dummy) { fixed w, h; POLYGON_SEGMENT s1 = edge1.dat; h = ftofix(vt2->y) - (edge1.top << 16); _clip_polygon_segment(&s1, h, flags); w = edge1.x + fixmul(h, edge1.dx) - ftofix(vt2->x); if (w) _triangle_deltas_f(bmp, w, &s1, &info, vt2, flags); } /* draws part between y1 and y2 */ if (_fill_3d_edge_structure_f(&edge2, vt1, vt2, flags, bmp)) draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info); /* draws part between y2 and y3 */ if (_fill_3d_edge_structure_f(&edge2, vt2, vt3, flags, bmp)) draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info); bmp_unwrite_line(bmp); release_bitmap(bmp); } /* reset fpu mode */ #ifdef ALLEGRO_DOS if (flags & (INTERP_Z | INTERP_FLOAT_UV)) _control87(old87, MCW_PC | MCW_RC); #endif } /* quad3d: * Draws a 3d quad. */ void _soft_quad3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) { #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) ASSERT(bmp); /* dodgy assumption alert! See comments for triangle() */ polygon3d(bmp, type, texture, 4, &v1); #else V3D *vertex[4]; ASSERT(bmp); vertex[0] = v1; vertex[1] = v2; vertex[2] = v3; vertex[3] = v4; polygon3d(bmp, type, texture, 4, vertex); #endif } /* quad3d_f: * Draws a 3d quad. */ void _soft_quad3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) { #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) ASSERT(bmp); /* dodgy assumption alert! See comments for triangle() */ polygon3d_f(bmp, type, texture, 4, &v1); #else V3D_f *vertex[4]; ASSERT(bmp); vertex[0] = v1; vertex[1] = v2; vertex[2] = v3; vertex[3] = v4; polygon3d_f(bmp, type, texture, 4, vertex); #endif } /* create_zbuffer: * Creates a new Z-buffer the size of the given bitmap. */ ZBUFFER *create_zbuffer(BITMAP *bmp) { ASSERT(bmp); return create_bitmap_ex(32, bmp->w, bmp->h); } /* clear_zbuffer: * Clears the given z-buffer, z is the value written in the z-buffer * - it is 1/(z coordinate), z=0 meaning far away. */ void clear_zbuffer(ZBUFFER *zbuf, float z) { union { float zf; long zi; } _zbuf_clip; ASSERT(zbuf); _zbuf_clip.zf = z; clear_to_color(zbuf, _zbuf_clip.zi); } /* destroy_zbuffer: * Destroys the given z-buffer. */ void destroy_zbuffer(ZBUFFER *zbuf) { if (zbuf) { if (zbuf == _zbuffer) _zbuffer = NULL; destroy_bitmap(zbuf); } } /* set_zbuffer: * Makes polygon drawing routines use the given BITMAP as z-buffer. */ void set_zbuffer(ZBUFFER *zbuf) { ASSERT(zbuf); _zbuffer = zbuf; } /* create_sub_zbuffer: * Creates a new sub-z-buffer of the given z-buffer. A sub-z-buffer is * exactly like a sub-bitmap, buf for z-buffers. */ ZBUFFER *create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height) { ASSERT(parent); /* For now, just use the code for BITMAPs. */ return create_sub_bitmap(parent, x, y, width, height); } allegro-4.4.3.1/src/rotate.c0000664000175000017500000007117713437077643014546 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sprite rotation routines. * * By Shawn Hargreaves. * * Flipping routines by Andrew Geers. * * Optimized by Sven Sandberg. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include /* * Scanline drawers. */ #define SCANLINE_DRAWER_GENERIC(name, INIT, PUTPIXEL) \ static void draw_scanline_##name(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ int mask_color; \ \ INIT; \ mask_color = bmp->vtable->mask_color; \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ for (; l_bmp_x <= r_bmp_x; l_bmp_x++) { \ c = getpixel(spr, l_spr_x>>16, l_spr_y>>16); \ if (c != mask_color) \ PUTPIXEL; \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } SCANLINE_DRAWER_GENERIC(generic_convert , int bmp_depth; int spr_depth; bmp_depth = bitmap_color_depth(bmp); spr_depth = bitmap_color_depth(spr); , putpixel(bmp, l_bmp_x, bmp_y_i, makecol_depth(bmp_depth, getr_depth(spr_depth, c), getg_depth(spr_depth, c), getb_depth(spr_depth, c)))) SCANLINE_DRAWER_GENERIC(generic , ; /* nop */ , putpixel(bmp, l_bmp_x, bmp_y_i, c)) #define SCANLINE_DRAWER(bits_pp, GETPIXEL) \ static void draw_scanline_##bits_pp(BITMAP *bmp, BITMAP *spr, \ fixed l_bmp_x, int bmp_y_i, \ fixed r_bmp_x, \ fixed l_spr_x, fixed l_spr_y, \ fixed spr_dx, fixed spr_dy) \ { \ int c; \ uintptr_t addr, end_addr; \ unsigned char **spr_line = spr->line; \ \ r_bmp_x >>= 16; \ l_bmp_x >>= 16; \ bmp_select(bmp); \ addr = bmp_write_line(bmp, bmp_y_i); \ end_addr = addr + r_bmp_x * ((bits_pp + 7) / 8); \ addr += l_bmp_x * ((bits_pp + 7) / 8); \ for (; addr <= end_addr; addr += ((bits_pp + 7) / 8)) { \ GETPIXEL; \ if (c != MASK_COLOR_##bits_pp) \ bmp_write##bits_pp(addr, c); \ l_spr_x += spr_dx; \ l_spr_y += spr_dy; \ } \ } #ifdef ALLEGRO_COLOR8 SCANLINE_DRAWER(8, c = spr_line[l_spr_y>>16][l_spr_x>>16]); #endif #ifdef ALLEGRO_COLOR16 SCANLINE_DRAWER(15, c = ((unsigned short *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) SCANLINE_DRAWER(16, c = ((unsigned short *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) #endif #ifdef ALLEGRO_COLOR24 #ifdef ALLEGRO_LITTLE_ENDIAN SCANLINE_DRAWER(24, { unsigned char *p = spr_line[l_spr_y>>16] + (l_spr_x>>16) * 3; c = p[0]; c |= (int)p[1] << 8; c |= (int)p[2] << 16; }) #else SCANLINE_DRAWER(24, { unsigned char *p = spr_line[l_spr_y>>16] + (l_spr_x>>16) * 3; c = (int)p[0] << 16; c |= (int)p[1] << 8; c |= p[2]; }) #endif #endif #ifdef ALLEGRO_COLOR32 SCANLINE_DRAWER(32, c = ((uint32_t *)spr_line[l_spr_y>>16]) [l_spr_x>>16]) #endif #ifdef ALLEGRO_GFX_HAS_VGA static void draw_scanline_modex( BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y_i, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy) { int c; uintptr_t start_addr, addr, end_addr; unsigned char **spr_line = spr->line; int plane; fixed spr_x, spr_y; r_bmp_x >>= 16; l_bmp_x >>= 16; start_addr = (uintptr_t)bmp->line[bmp_y_i]; spr_dx <<= 2; spr_dy <<= 2; for (plane = 0; plane < 4; plane++) { addr = start_addr + ((l_bmp_x + plane) >> 2); end_addr = addr + ((r_bmp_x - l_bmp_x - plane) >> 2); outportw(0x3C4, (0x100 << ((l_bmp_x + plane) & 3)) | 2); spr_x = l_spr_x; spr_y = l_spr_y; for (; addr < end_addr; addr++) { c = spr_line[spr_y >> 16][spr_x >> 16]; if (c != MASK_COLOR_8) _farnspokeb(addr, c); spr_x += spr_dx; spr_y += spr_dy; } l_spr_x += spr_dx >> 2; l_spr_y += spr_dy >> 2; } } #endif /* _parallelogram_map: * Worker routine for drawing rotated and/or scaled and/or flipped sprites: * It actually maps the sprite to any parallelogram-shaped area of the * bitmap. The top left corner is mapped to (xs[0], ys[0]), the top right to * (xs[1], ys[1]), the bottom right to x (xs[2], ys[2]), and the bottom left * to (xs[3], ys[3]). The corners are assumed to form a perfect * parallelogram, i.e. xs[0]+xs[2] = xs[1]+xs[3]. The corners are given in * fixed point format, so xs[] and ys[] are coordinates of the outer corners * of corner pixels in clockwise order beginning with top left. * All coordinates begin with 0 in top left corner of pixel (0, 0). So a * rotation by 0 degrees of a sprite to the top left of a bitmap can be * specified with coordinates (0, 0) for the top left pixel in source * bitmap. With the default scanline drawer, a pixel in the destination * bitmap is drawn if and only if its center is covered by any pixel in the * sprite. The color of this covering sprite pixel is used to draw. * If sub_pixel_accuracy=FALSE, then the scanline drawer will be called with * *_bmp_x being a fixed point representation of the integers representing * the x coordinate of the first and last point in bmp whose centre is * covered by the sprite. If sub_pixel_accuracy=TRUE, then the scanline * drawer will be called with the exact fixed point position of the first * and last point in which the horizontal line passing through the centre is * at least partly covered by the sprite. This is useful for doing * anti-aliased blending. */ void _parallelogram_map(BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy), int sub_pixel_accuracy) { /* Index in xs[] and ys[] to topmost point. */ int top_index; /* Rightmost point has index (top_index+right_index) int xs[] and ys[]. */ int right_index; /* Loop variables. */ int index, i; /* Coordinates in bmp ordered as top-right-bottom-left. */ fixed corner_bmp_x[4], corner_bmp_y[4]; /* Coordinates in spr ordered as top-right-bottom-left. */ fixed corner_spr_x[4], corner_spr_y[4]; /* y coordinate of bottom point, left point and right point. */ int clip_bottom_i, l_bmp_y_bottom_i, r_bmp_y_bottom_i; /* Left and right clipping. */ fixed clip_left, clip_right; /* Temporary variable. */ fixed extra_scanline_fraction; /* * Variables used in the loop */ /* Coordinates of sprite and bmp points in beginning of scanline. */ fixed l_spr_x, l_spr_y, l_bmp_x, l_bmp_dx; /* Increment of left sprite point as we move a scanline down. */ fixed l_spr_dx, l_spr_dy; /* Coordinates of sprite and bmp points in end of scanline. */ fixed r_bmp_x, r_bmp_dx; #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE fixed r_spr_x, r_spr_y; /* Increment of right sprite point as we move a scanline down. */ fixed r_spr_dx, r_spr_dy; #endif /* Increment of sprite point as we move right inside a scanline. */ fixed spr_dx, spr_dy; /* Positions of beginning of scanline after rounding to integer coordinate in bmp. */ fixed l_spr_x_rounded, l_spr_y_rounded, l_bmp_x_rounded; fixed r_bmp_x_rounded; /* Current scanline. */ int bmp_y_i; /* Right edge of scanline. */ int right_edge_test; /* Get index of topmost point. */ top_index = 0; if (ys[1] < ys[0]) top_index = 1; if (ys[2] < ys[top_index]) top_index = 2; if (ys[3] < ys[top_index]) top_index = 3; /* Get direction of points: clockwise or anti-clockwise. */ right_index = (double)(xs[(top_index+1) & 3] - xs[top_index]) * (double)(ys[(top_index-1) & 3] - ys[top_index]) > (double)(xs[(top_index-1) & 3] - xs[top_index]) * (double)(ys[(top_index+1) & 3] - ys[top_index]) ? 1 : -1; //FIXME: why does fixmul overflow below? /*if (fixmul(xs[(top_index+1) & 3] - xs[top_index], ys[(top_index-1) & 3] - ys[top_index]) > fixmul(xs[(top_index-1) & 3] - xs[top_index], ys[(top_index+1) & 3] - ys[top_index])) right_index = 1; else right_index = -1;*/ /* * Get coordinates of the corners. */ /* corner_*[0] is top, [1] is right, [2] is bottom, [3] is left. */ index = top_index; for (i = 0; i < 4; i++) { corner_bmp_x[i] = xs[index]; corner_bmp_y[i] = ys[index]; if (index < 2) corner_spr_y[i] = 0; else /* Need `- 1' since otherwise it would be outside sprite. */ corner_spr_y[i] = (spr->h << 16) - 1; if ((index == 0) || (index == 3)) corner_spr_x[i] = 0; else corner_spr_x[i] = (spr->w << 16) - 1; index = (index + right_index) & 3; } /* * Get scanline starts, ends and deltas, and clipping coordinates. */ #define top_bmp_y corner_bmp_y[0] #define right_bmp_y corner_bmp_y[1] #define bottom_bmp_y corner_bmp_y[2] #define left_bmp_y corner_bmp_y[3] #define top_bmp_x corner_bmp_x[0] #define right_bmp_x corner_bmp_x[1] #define bottom_bmp_x corner_bmp_x[2] #define left_bmp_x corner_bmp_x[3] #define top_spr_y corner_spr_y[0] #define right_spr_y corner_spr_y[1] #define bottom_spr_y corner_spr_y[2] #define left_spr_y corner_spr_y[3] #define top_spr_x corner_spr_x[0] #define right_spr_x corner_spr_x[1] #define bottom_spr_x corner_spr_x[2] #define left_spr_x corner_spr_x[3] /* Calculate left and right clipping. */ if (bmp->clip) { clip_left = bmp->cl << 16; clip_right = (bmp->cr << 16) - 1; } else { ASSERT(left_bmp_x >= 0 && top_bmp_x >= 0 && bottom_bmp_x >= 0 && right_bmp_x < (bmp->w << 16) && top_bmp_x < (bmp->w << 16) && bottom_bmp_x < (bmp->w << 16)); clip_left = 0; clip_right = (bmp->w << 16) - 1; } /* Quit if we're totally outside. */ if ((left_bmp_x > clip_right) && (top_bmp_x > clip_right) && (bottom_bmp_x > clip_right)) return; if ((right_bmp_x < clip_left) && (top_bmp_x < clip_left) && (bottom_bmp_x < clip_left)) return; /* Bottom clipping. */ if (sub_pixel_accuracy) clip_bottom_i = (bottom_bmp_y + 0xffff) >> 16; else clip_bottom_i = (bottom_bmp_y + 0x8000) >> 16; if (bmp->clip) { if (clip_bottom_i > bmp->cb) clip_bottom_i = bmp->cb; } else { ASSERT(clip_bottom_i <= bmp->h); } /* Calculate y coordinate of first scanline. */ if (sub_pixel_accuracy) bmp_y_i = top_bmp_y >> 16; else bmp_y_i = (top_bmp_y + 0x8000) >> 16; if (bmp->clip) { if (bmp_y_i < bmp->ct) bmp_y_i = bmp->ct; } else { ASSERT(bmp_y_i >= 0); } /* Sprite is above or below bottom clipping area. */ if (bmp_y_i >= clip_bottom_i) return; /* Vertical gap between top corner and centre of topmost scanline. */ extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - top_bmp_y; /* Calculate x coordinate of beginning of scanline in bmp. */ l_bmp_dx = fixdiv(left_bmp_x - top_bmp_x, left_bmp_y - top_bmp_y); l_bmp_x = top_bmp_x + fixmul(extra_scanline_fraction, l_bmp_dx); /* Calculate x coordinate of beginning of scanline in spr. */ /* note: all these are rounded down which is probably a Good Thing (tm) */ l_spr_dx = fixdiv(left_spr_x - top_spr_x, left_bmp_y - top_bmp_y); l_spr_x = top_spr_x + fixmul(extra_scanline_fraction, l_spr_dx); /* Calculate y coordinate of beginning of scanline in spr. */ l_spr_dy = fixdiv(left_spr_y - top_spr_y, left_bmp_y - top_bmp_y); l_spr_y = top_spr_y + fixmul(extra_scanline_fraction, l_spr_dy); /* Calculate left loop bound. */ l_bmp_y_bottom_i = (left_bmp_y + 0x8000) >> 16; if (l_bmp_y_bottom_i > clip_bottom_i) l_bmp_y_bottom_i = clip_bottom_i; /* Calculate x coordinate of end of scanline in bmp. */ r_bmp_dx = fixdiv(right_bmp_x - top_bmp_x, right_bmp_y - top_bmp_y); r_bmp_x = top_bmp_x + fixmul(extra_scanline_fraction, r_bmp_dx); #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE /* Calculate x coordinate of end of scanline in spr. */ r_spr_dx = fixdiv(right_spr_x - top_spr_x, right_bmp_y - top_bmp_y); r_spr_x = top_spr_x + fixmul(extra_scanline_fraction, r_spr_dx); /* Calculate y coordinate of end of scanline in spr. */ r_spr_dy = fixdiv(right_spr_y - top_spr_y, right_bmp_y - top_bmp_y); r_spr_y = top_spr_y + fixmul(extra_scanline_fraction, r_spr_dy); #endif /* Calculate right loop bound. */ r_bmp_y_bottom_i = (right_bmp_y + 0x8000) >> 16; /* Get dx and dy, the offsets to add to the source coordinates as we move one pixel rightwards along a scanline. This formula can be derived by considering the 2x2 matrix that transforms the sprite to the parallelogram. We'd better use double to get this as exact as possible, since any errors will be accumulated along the scanline. */ spr_dx = (fixed)((ys[3] - ys[0]) * 65536.0 * (65536.0 * spr->w) / ((xs[1] - xs[0]) * (double)(ys[3] - ys[0]) - (xs[3] - xs[0]) * (double)(ys[1] - ys[0]))); spr_dy = (fixed)((ys[1] - ys[0]) * 65536.0 * (65536.0 * spr->h) / ((xs[3] - xs[0]) * (double)(ys[1] - ys[0]) - (xs[1] - xs[0]) * (double)(ys[3] - ys[0]))); /* * Loop through scanlines. */ while (1) { /* Has beginning of scanline passed a corner? */ if (bmp_y_i >= l_bmp_y_bottom_i) { /* Are we done? */ if (bmp_y_i >= clip_bottom_i) break; /* Vertical gap between left corner and centre of scanline. */ extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - left_bmp_y; /* Update x coordinate of beginning of scanline in bmp. */ l_bmp_dx = fixdiv(bottom_bmp_x - left_bmp_x, bottom_bmp_y - left_bmp_y); l_bmp_x = left_bmp_x + fixmul(extra_scanline_fraction, l_bmp_dx); /* Update x coordinate of beginning of scanline in spr. */ l_spr_dx = fixdiv(bottom_spr_x - left_spr_x, bottom_bmp_y - left_bmp_y); l_spr_x = left_spr_x + fixmul(extra_scanline_fraction, l_spr_dx); /* Update y coordinate of beginning of scanline in spr. */ l_spr_dy = fixdiv(bottom_spr_y - left_spr_y, bottom_bmp_y - left_bmp_y); l_spr_y = left_spr_y + fixmul(extra_scanline_fraction, l_spr_dy); /* Update loop bound. */ if (sub_pixel_accuracy) l_bmp_y_bottom_i = (bottom_bmp_y + 0xffff) >> 16; else l_bmp_y_bottom_i = (bottom_bmp_y + 0x8000) >> 16; if (l_bmp_y_bottom_i > clip_bottom_i) l_bmp_y_bottom_i = clip_bottom_i; } /* Has end of scanline passed a corner? */ if (bmp_y_i >= r_bmp_y_bottom_i) { /* Vertical gap between right corner and centre of scanline. */ extra_scanline_fraction = (bmp_y_i << 16) + 0x8000 - right_bmp_y; /* Update x coordinate of end of scanline in bmp. */ r_bmp_dx = fixdiv(bottom_bmp_x - right_bmp_x, bottom_bmp_y - right_bmp_y); r_bmp_x = right_bmp_x + fixmul(extra_scanline_fraction, r_bmp_dx); #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE /* Update x coordinate of beginning of scanline in spr. */ r_spr_dx = fixdiv(bottom_spr_x - right_spr_x, bottom_bmp_y - right_bmp_y); r_spr_x = right_spr_x + fixmul(extra_scanline_fraction, r_spr_dx); /* Update y coordinate of beginning of scanline in spr. */ r_spr_dy = fixdiv(bottom_spr_y - right_spr_y, bottom_bmp_y - right_bmp_y); r_spr_y = right_spr_y + fixmul(extra_scanline_fraction, r_spr_dy); #endif /* Update loop bound: We aren't supposed to use this any more, so just set it to some big enough value. */ r_bmp_y_bottom_i = clip_bottom_i; } /* Make left bmp coordinate be an integer and clip it. */ if (sub_pixel_accuracy) l_bmp_x_rounded = l_bmp_x; else l_bmp_x_rounded = (l_bmp_x + 0x8000) & ~0xffff; if (l_bmp_x_rounded < clip_left) l_bmp_x_rounded = clip_left; /* ... and move starting point in sprite accordingly. */ if (sub_pixel_accuracy) { l_spr_x_rounded = l_spr_x + fixmul((l_bmp_x_rounded - l_bmp_x), spr_dx); l_spr_y_rounded = l_spr_y + fixmul((l_bmp_x_rounded - l_bmp_x), spr_dy); } else { l_spr_x_rounded = l_spr_x + fixmul(l_bmp_x_rounded + 0x7fff - l_bmp_x, spr_dx); l_spr_y_rounded = l_spr_y + fixmul(l_bmp_x_rounded + 0x7fff - l_bmp_x, spr_dy); } /* Make right bmp coordinate be an integer and clip it. */ if (sub_pixel_accuracy) r_bmp_x_rounded = r_bmp_x; else r_bmp_x_rounded = (r_bmp_x - 0x8000) & ~0xffff; if (r_bmp_x_rounded > clip_right) r_bmp_x_rounded = clip_right; /* Draw! */ if (l_bmp_x_rounded <= r_bmp_x_rounded) { if (!sub_pixel_accuracy) { /* The bodies of these ifs are only reached extremely seldom, it's an ugly hack to avoid reading outside the sprite when the rounding errors are accumulated the wrong way. It would be nicer if we could ensure that this never happens by making all multiplications and divisions be rounded up or down at the correct places. I did try another approach: recalculate the edges of the scanline from scratch each scanline rather than incrementally. Drawing a sprite with that routine took about 25% longer time though. */ if ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->w) { if (((l_spr_x_rounded < 0) && (spr_dx <= 0)) || ((l_spr_x_rounded > 0) && (spr_dx >= 0))) { /* This can happen. */ goto skip_draw; } else { /* I don't think this can happen, but I can't prove it. */ do { l_spr_x_rounded += spr_dx; l_bmp_x_rounded += 65536; if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->w); } } right_edge_test = l_spr_x_rounded + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * spr_dx; if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->w) { if (((right_edge_test < 0) && (spr_dx <= 0)) || ((right_edge_test > 0) && (spr_dx >= 0))) { /* This can happen. */ do { r_bmp_x_rounded -= 65536; right_edge_test -= spr_dx; if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->w); } else { /* I don't think this can happen, but I can't prove it. */ goto skip_draw; } } if ((unsigned)(l_spr_y_rounded >> 16) >= (unsigned)spr->h) { if (((l_spr_y_rounded < 0) && (spr_dy <= 0)) || ((l_spr_y_rounded > 0) && (spr_dy >= 0))) { /* This can happen. */ goto skip_draw; } else { /* I don't think this can happen, but I can't prove it. */ do { l_spr_y_rounded += spr_dy; l_bmp_x_rounded += 65536; if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while (((unsigned)l_spr_y_rounded >> 16) >= (unsigned)spr->h); } } right_edge_test = l_spr_y_rounded + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * spr_dy; if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->h) { if (((right_edge_test < 0) && (spr_dy <= 0)) || ((right_edge_test > 0) && (spr_dy >= 0))) { /* This can happen. */ do { r_bmp_x_rounded -= 65536; right_edge_test -= spr_dy; if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->h); } else { /* I don't think this can happen, but I can't prove it. */ goto skip_draw; } } } draw_scanline(bmp, spr, l_bmp_x_rounded, bmp_y_i, r_bmp_x_rounded, l_spr_x_rounded, l_spr_y_rounded, spr_dx, spr_dy); } /* I'm not going to apoligize for this label and its gotos: to get rid of it would just make the code look worse. */ skip_draw: /* Jump to next scanline. */ bmp_y_i++; /* Update beginning of scanline. */ l_bmp_x += l_bmp_dx; l_spr_x += l_spr_dx; l_spr_y += l_spr_dy; /* Update end of scanline. */ r_bmp_x += r_bmp_dx; #ifdef KEEP_TRACK_OF_RIGHT_SPRITE_SCANLINE r_spr_x += r_spr_dx; r_spr_y += r_spr_dy; #endif } bmp_unwrite_line(bmp); } /* _parallelogram_map_standard: * Helper function for calling _parallelogram_map() with the appropriate * scanline drawer. I didn't want to include this in the * _parallelogram_map() function since then you can bypass it and define * your own scanline drawer, eg. for anti-aliased rotations. */ void _parallelogram_map_standard(BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4]) { int old_drawing_mode; if (bitmap_color_depth(bmp) != bitmap_color_depth(sprite)) { /* These scanline drawers use putpixel() so we must set solid mode. */ old_drawing_mode = _drawing_mode; drawing_mode(DRAW_MODE_SOLID, _drawing_pattern, _drawing_x_anchor, _drawing_y_anchor); _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_generic_convert, FALSE); drawing_mode(old_drawing_mode, _drawing_pattern, _drawing_x_anchor, _drawing_y_anchor); } else if (!is_memory_bitmap(sprite)) { old_drawing_mode = _drawing_mode; drawing_mode(DRAW_MODE_SOLID, _drawing_pattern, _drawing_x_anchor, _drawing_y_anchor); _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_generic, FALSE); drawing_mode(old_drawing_mode, _drawing_pattern, _drawing_x_anchor, _drawing_y_anchor); } else if (is_linear_bitmap(bmp)) { switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_8, FALSE); break; #endif #ifdef ALLEGRO_COLOR16 case 15: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_15, FALSE); break; case 16: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_16, FALSE); break; #endif #ifdef ALLEGRO_COLOR24 case 24: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_24, FALSE); break; #endif #ifdef ALLEGRO_COLOR32 case 32: _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_32, FALSE); break; #endif default: /* NOTREACHED */ ASSERT(0); } } #ifdef ALLEGRO_GFX_HAS_VGA else { _parallelogram_map(bmp, sprite, xs, ys, draw_scanline_modex, FALSE); } #endif } /* _rotate_scale_flip_coordinates: * Calculates the coordinates for the rotated, scaled and flipped sprite, * and passes them on to the given function. */ void _rotate_scale_flip_coordinates(fixed w, fixed h, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale_x, fixed scale_y, int h_flip, int v_flip, fixed xs[4], fixed ys[4]) { fixed fix_cos, fix_sin; int tl = 0, tr = 1, bl = 3, br = 2; int tmp; double cos_angle, sin_angle; fixed xofs, yofs; /* Setting angle to the range -180...180 degrees makes sin & cos more numerically stable. (Yes, this does have an effect for big angles!) Note that using "real" sin() and cos() gives much better precision than fixsin() and fixcos(). */ angle = angle & 0xffffff; if (angle >= 0x800000) angle -= 0x1000000; _AL_SINCOS(angle * (AL_PI / (double)0x800000), sin_angle, cos_angle); if (cos_angle >= 0) fix_cos = (int)(cos_angle * 0x10000 + 0.5); else fix_cos = (int)(cos_angle * 0x10000 - 0.5); if (sin_angle >= 0) fix_sin = (int)(sin_angle * 0x10000 + 0.5); else fix_sin = (int)(sin_angle * 0x10000 - 0.5); /* Decide what order to take corners in. */ if (v_flip) { tl = 3; tr = 2; bl = 0; br = 1; } else { tl = 0; tr = 1; bl = 3; br = 2; } if (h_flip) { tmp = tl; tl = tr; tr = tmp; tmp = bl; bl = br; br = tmp; } /* Calculate new coordinates of all corners. */ w = fixmul(w, scale_x); h = fixmul(h, scale_y); cx = fixmul(cx, scale_x); cy = fixmul(cy, scale_y); xofs = x - fixmul(cx, fix_cos) + fixmul(cy, fix_sin); yofs = y - fixmul(cx, fix_sin) - fixmul(cy, fix_cos); xs[tl] = xofs; ys[tl] = yofs; xs[tr] = xofs + fixmul(w, fix_cos); ys[tr] = yofs + fixmul(w, fix_sin); xs[bl] = xofs - fixmul(h, fix_sin); ys[bl] = yofs + fixmul(h, fix_cos); xs[br] = xs[tr] + xs[bl] - xs[tl]; ys[br] = ys[tr] + ys[bl] - ys[tl]; } /* _pivot_scaled_sprite_flip: * The most generic routine to which you specify the position with angles, * scales, etc. */ void _pivot_scaled_sprite_flip(BITMAP *bmp, BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip) { fixed xs[4], ys[4]; _rotate_scale_flip_coordinates(sprite->w << 16, sprite->h << 16, x, y, cx, cy, angle, scale, scale, FALSE, v_flip, xs, ys); _parallelogram_map_standard(bmp, sprite, xs, ys); } /* * rotate_*() */ /* _rotate_scaled_sprite_flip: (template) * Rotates and scales a sprite, optionally flipping it about either axis. * Coordinates are given in fixed point format. */ #if 0 static void _rotate_scaled_sprite_flip(BITMAP *bmp, BITMAP *sprite, fixed x, fixed y, fixed angle, fixed scale, int v_flip) { _pivot_scaled_sprite_flip(bmp, sprite, x + (sprite->w * scale) / 2, y + (sprite->h * scale) / 2, sprite->w << 15, sprite->h << 15, angle, scale, v_flip); } #endif /* rotate_sprite: (inlined) * Draws a sprite image onto a bitmap at the specified position, rotating * it by the specified angle. The angle is a fixed point 16.16 number in * the same format used by the fixed point trig routines, with 256 equal * to a full circle, 64 a right angle, etc. This function can draw between * any two bitmaps. */ /* rotate_sprite_v_flip: (inlined) * Similar to rotate_sprite(), except flips the sprite vertically first. */ /* rotate_scaled_sprite: (inlined) * Draws a sprite image onto a bitmap at the specified position, rotating * it by the specified angle. The angle is a fixed point 16.16 number in * the same format used by the fixed point trig routines, with 256 equal * to a full circle, 64 a right angle, etc. This function can draw between * any two bitmaps. */ /* rotate_scaled_sprite_v_flip: (inlined) * Similar to rotate_scaled_sprite(), except flips the sprite vertically first. */ /* * pivot_*() */ /* pivot_sprite: (inlined) * Rotates a sprite around the specified pivot centre point. */ /* pivot_sprite_v_flip: (inlined) * Similar to pivot_sprite(), except flips the sprite vertically first. */ /* pivot_scaled_sprite: (inlined) * Rotates and scales a sprite around the specified pivot centre point. */ /* pivot_scaled_sprite_v_flip: (inlined) * Similar to pivot_scaled_sprite(), except flips the sprite vertically first. */ allegro-4.4.3.1/src/clip3d.c0000664000175000017500000001603313437077643014414 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fixed point version of the 3D polygon clipper. * * By Chris Robinson. * * See readme.txt for copyright information. */ #include "allegro.h" #define INT_NONE 0 #define INT_1COL 1 #define INT_3COL 2 #define INT_3COLP 4 #define INT_UV 8 /* point_inside: * Copies a vertex to the output table. */ #define point_inside(vv) \ { \ v3->x = v2->x; v3->y = v2->y; v3->z = v2->z; \ v3->u = v2->u; v3->v = v2->v; v3->c = v2->c; \ vv++; \ } /* point_interp: * Interpolates between v1 and v2, with slope "t", resulting vertex v3. */ #define point_interp(vv) \ { \ v3->x = fixmul(v2->x - v1->x, t) + v1->x; \ v3->y = fixmul(v2->y - v1->y, t) + v1->y; \ v3->z = fixmul(v2->z - v1->z, t) + v1->z; \ \ if (flags & INT_1COL) { \ v3->c = (v2->c - v1->c) * fixtoi(t) + v1->c; \ } \ else if (flags & INT_3COLP) { \ int bpp = bitmap_color_depth(screen); \ int r = (int)((getr_depth(bpp, v2->c) - getr_depth(bpp, v1->c)) * fixtoi(t) + getr_depth(bpp, v1->c)); \ int g = (int)((getg_depth(bpp, v2->c) - getg_depth(bpp, v1->c)) * fixtoi(t) + getg_depth(bpp, v1->c)); \ int b = (int)((getb_depth(bpp, v2->c) - getb_depth(bpp, v1->c)) * fixtoi(t) + getb_depth(bpp, v1->c)); \ v3->c = makecol_depth(bpp, r&255, g&255, b&255); \ } \ else if (flags & INT_3COL) { \ int r = ((v2->c & 0xFF0000) - (v1->c & 0xFF0000)) * fixtoi(t) + (v1->c & 0xFF0000); \ int g = ((v2->c & 0x00FF00) - (v1->c & 0x00FF00)) * fixtoi(t) + (v1->c & 0x00FF00); \ int b = ((v2->c & 0x0000FF) - (v1->c & 0x0000FF)) * fixtoi(t) + (v1->c & 0x0000FF); \ v3->c = (r & 0xFF0000) | (g & 0x00FF00) | (b & 0x0000FF); \ } \ if (flags & INT_UV) { \ v3->u = fixmul(v2->u - v1->u, t) + v1->u; \ v3->v = fixmul(v2->v - v1->v, t) + v1->v; \ } \ vv++; \ } /* clip3d: * A fixed point version of clip3d_f. Works suprisingly well. */ int clip3d(int type, fixed min_z, fixed max_z, int vc, AL_CONST V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]) { int i, j, vo, vt, flags; fixed t; V3D *v3; AL_CONST V3D *v1, *v2, **vin; static int flag_table[] = { INT_NONE, /* flat */ INT_3COLP, /* gcol */ INT_3COL, /* grgb */ INT_UV, /* atex */ INT_UV, /* ptex */ INT_UV, /* atex mask */ INT_UV, /* ptex mask */ INT_UV + INT_1COL, /* atex lit */ INT_UV + INT_1COL, /* ptex lit */ INT_UV + INT_1COL, /* atex mask lit */ INT_UV + INT_1COL, /* ptex mask lit */ INT_UV, /* atex trans */ INT_UV, /* ptex trans */ INT_UV, /* atex mask trans */ INT_UV /* ptex mask trans */ }; type &= ~POLYTYPE_ZBUF; flags = flag_table[type]; if (max_z > min_z) { vt = 0; for (i=0; iz > max_z); for (i=0, j=vc-1; iz, v2->z - v1->z); point_interp(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vin = (AL_CONST V3D**)vtmp; } else { vt = vc; vin = vtx; } vo = 0; for (i=0; iz < min_z); for (i=0, j=vt-1; iz, v2->z - v1->z); point_interp(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } vt = 0; for (i=0; ix < -vout[i]->z); for (i=0, j=vo-1; iz - v1->x, v2->x - v1->x + v2->z - v1->z); point_interp(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vo = 0; for (i=0; ix > vtmp[i]->z); for (i=0, j=vt-1; iz - v1->x, v2->x - v1->x - v2->z + v1->z); point_interp(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } vt = 0; for (i=0; iy < -vout[i]->z); for (i=0, j=vo-1; iz - v1->y, v2->y - v1->y + v2->z - v1->z); point_interp(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vo = 0; for (i=0; iy > vtmp[i]->z); for (i=0, j=vt-1; iz - v1->y, v2->y - v1->y - v2->z + v1->z); point_interp(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } if (type == POLYTYPE_FLAT) vout[0]->c = vtx[0]->c; return vo; } allegro-4.4.3.1/src/glyph.c0000664000175000017500000002055513437077643014365 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Monochrome character drawing routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* helper macro for drawing glyphs in each color depth */ #define DRAW_GLYPH(bits, size) \ { \ AL_CONST unsigned char *data = glyph->dat; \ unsigned long addr; \ int w = glyph->w; \ int h = glyph->h; \ int stride = (w+7)/8; \ int lgap = 0; \ int d, i, j; \ \ if (bmp->clip) { \ /* clip the top */ \ if (y < bmp->ct) { \ d = bmp->ct - y; \ \ h -= d; \ if (h <= 0) \ return; \ \ data += d*stride; \ y = bmp->ct; \ } \ \ /* clip the bottom */ \ if (y+h >= bmp->cb) { \ h = bmp->cb - y; \ if (h <= 0) \ return; \ } \ \ /* clip the left */ \ if (x < bmp->cl) { \ d = bmp->cl - x; \ \ w -= d; \ if (w <= 0) \ return; \ \ data += d/8; \ lgap = d&7; \ x = bmp->cl; \ } \ \ /* clip the right */ \ if (x+w >= bmp->cr) { \ w = bmp->cr - x; \ if (w <= 0) \ return; \ } \ } \ \ stride -= (lgap+w+7)/8; \ \ /* draw it */ \ bmp_select(bmp); \ \ while (h--) { \ addr = bmp_write_line(bmp, y++) + x*size; \ \ j = 0; \ i = 0x80 >> lgap; \ d = *(data++); \ \ if (bg >= 0) { \ /* opaque mode drawing loop */ \ for (;;) { \ if (d & i) \ bmp_write##bits(addr, color); \ else \ bmp_write##bits(addr, bg); \ \ j++; \ if (j == w) \ break; \ \ i >>= 1; \ if (!i) { \ i = 0x80; \ d = *(data++); \ } \ \ addr += size; \ } \ } \ else { \ /* masked mode drawing loop */ \ for (;;) { \ if (d & i) \ bmp_write##bits(addr, color); \ \ j++; \ if (j == w) \ break; \ \ i >>= 1; \ if (!i) { \ i = 0x80; \ d = *(data++); \ } \ \ addr += size; \ } \ } \ \ data += stride; \ } \ \ bmp_unwrite_line(bmp); \ } #ifdef ALLEGRO_COLOR8 /* _linear_draw_glyph8: * Draws a glyph onto an 8 bit bitmap. */ void _linear_draw_glyph8(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg) { DRAW_GLYPH(8, 1); } #endif #ifdef ALLEGRO_COLOR16 /* _linear_draw_glyph16: * Draws a glyph onto a 16 bit bitmap. */ void _linear_draw_glyph16(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg) { DRAW_GLYPH(16, sizeof(int16_t)); } #endif #ifdef ALLEGRO_COLOR24 /* _linear_draw_glyph24: * Draws a glyph onto a 24 bit bitmap. */ void _linear_draw_glyph24(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg) { DRAW_GLYPH(24, 3); } #endif #ifdef ALLEGRO_COLOR32 /* _linear_draw_glyph32: * Draws a glyph onto a 32 bit bitmap. */ void _linear_draw_glyph32(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg) { DRAW_GLYPH(32, sizeof(int32_t)); } #endif allegro-4.4.3.1/src/polygon.c0000664000175000017500000001472413437077643014732 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The 2d polygon rasteriser. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* fill_edge_structure: * Polygon helper function: initialises an edge structure for the 2d * rasteriser. */ static void fill_edge_structure(POLYGON_EDGE *edge, AL_CONST int *i1, AL_CONST int *i2) { if (i2[1] < i1[1]) { AL_CONST int *it; it = i1; i1 = i2; i2 = it; } edge->top = i1[1]; edge->bottom = i2[1]; edge->x = (i1[0] << POLYGON_FIX_SHIFT) + (1 << (POLYGON_FIX_SHIFT-1)); if (i2[1] != i1[1]) { edge->dx = ((i2[0] - i1[0]) << POLYGON_FIX_SHIFT) / (i2[1] - i1[1]); } else { edge->dx = ((i2[0] - i1[0]) << POLYGON_FIX_SHIFT) << 1; } edge->w = MAX(ABS(edge->dx)-1, 0); edge->prev = NULL; edge->next = NULL; if (edge->dx < 0) edge->x += edge->dx/2 ; } /* _add_edge: * Adds an edge structure to a linked list, returning the new head pointer. */ POLYGON_EDGE *_add_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x) { POLYGON_EDGE *pos = list; POLYGON_EDGE *prev = NULL; if (sort_by_x) { while ((pos) && (pos->x < edge->x)) { prev = pos; pos = pos->next; } } else { while ((pos) && (pos->top < edge->top)) { prev = pos; pos = pos->next; } } edge->next = pos; edge->prev = prev; if (pos) pos->prev = edge; if (prev) { prev->next = edge; return list; } else return edge; } /* _remove_edge: * Removes an edge structure from a list, returning the new head pointer. */ POLYGON_EDGE *_remove_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge) { if (edge->next) edge->next->prev = edge->prev; if (edge->prev) { edge->prev->next = edge->next; return list; } else return edge->next; } /* polygon: * Draws a filled polygon with an arbitrary number of corners. Pass the * number of vertices, then an array containing a series of x, y points * (a total of vertices*2 values). */ void _soft_polygon(BITMAP *bmp, int vertices, AL_CONST int *points, int color) { int c; int top = INT_MAX; int bottom = INT_MIN; AL_CONST int *i1, *i2; POLYGON_EDGE *edge, *next_edge; POLYGON_EDGE *active_edges = NULL; POLYGON_EDGE *inactive_edges = NULL; ASSERT(bmp); /* allocate some space and fill the edge table */ _grow_scratch_mem(sizeof(POLYGON_EDGE) * vertices); edge = (POLYGON_EDGE *)_scratch_mem; i1 = points; i2 = points + (vertices-1) * 2; for (c=0; cbottom >= edge->top) { if (edge->top < top) top = edge->top; if (edge->bottom > bottom) bottom = edge->bottom; inactive_edges = _add_edge(inactive_edges, edge, FALSE); edge++; } i2 = i1; i1 += 2; } if (bottom >= bmp->cb) bottom = bmp->cb-1; acquire_bitmap(bmp); /* for each scanline in the polygon... */ for (c=top; c<=bottom; c++) { int hid = 0; int b1 = 0; int e1 = 0; int up = 0; int draw = 0; int e; /* check for newly active edges */ edge = inactive_edges; while ((edge) && (edge->top == c)) { next_edge = edge->next; inactive_edges = _remove_edge(inactive_edges, edge); active_edges = _add_edge(active_edges, edge, TRUE); edge = next_edge; } /* draw horizontal line segments */ edge = active_edges; while (edge) { e = edge->w; if (edge->bottom != c) { up = 1 - up; } else { e = edge->w >> 1; } if (edge->top == c) { e = edge->w >> 1; } if ((draw < 1) && (up >= 1)) { b1 = (edge->x + e) >> POLYGON_FIX_SHIFT; } else if (draw >= 1) { /* filling the polygon */ e1 = edge->x >> POLYGON_FIX_SHIFT; hid = MAX(hid, b1 + 1); if (hid <= e1-1) { bmp->vtable->hfill(bmp, hid, c, e1-1, color); } b1 = (edge->x + e) >> POLYGON_FIX_SHIFT; } /* drawing the edge */ hid = MAX(hid, edge->x >> POLYGON_FIX_SHIFT); if (hid <= ((edge->x + e) >> POLYGON_FIX_SHIFT)) { bmp->vtable->hfill(bmp, hid, c, (edge->x + e) >> POLYGON_FIX_SHIFT, color); hid = 1 + ((edge->x + e) >> POLYGON_FIX_SHIFT); } edge = edge->next; draw = up; } /* update edges, sorting and removing dead ones */ edge = active_edges; while (edge) { next_edge = edge->next; if (c >= edge->bottom) { active_edges = _remove_edge(active_edges, edge); } else { edge->x += edge->dx; if ((edge->top == c) && (edge->dx > 0)) { edge->x -= edge->dx/2; } if ((edge->bottom == c+1) && (edge->dx < 0)) { edge->x -= edge->dx/2; } while ((edge->prev) && (edge->x < edge->prev->x)) { if (edge->next) edge->next->prev = edge->prev; edge->prev->next = edge->next; edge->next = edge->prev; edge->prev = edge->prev->prev; edge->next->prev = edge; if (edge->prev) edge->prev->next = edge; else active_edges = edge; } } edge = next_edge; } } release_bitmap(bmp); } /* triangle: * Draws a filled triangle between the three points. */ void _soft_triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) { ASSERT(bmp); #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) /* note: this depends on a dodgy assumption about parameter passing * conventions. I assume that the point coordinates are all on the * stack in consecutive locations, so I can pass that block of stack * memory as the array for polygon() without bothering to copy the * data to a temporary location. */ polygon(bmp, 3, &x1, color); #else { /* portable version for other platforms */ int point[6]; point[0] = x1; point[1] = y1; point[2] = x2; point[3] = y2; point[4] = x3; point[5] = y3; polygon(bmp, 3, point, color); } #endif } allegro-4.4.3.1/src/lzss.c0000664000175000017500000003326413437077643014236 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * LZSS compression routines. * * By Shawn Hargreaves. * * Original code by Haruhiko Okumura. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* This compression algorithm is based on the ideas of Lempel and Ziv, with the modifications suggested by Storer and Szymanski. The algorithm is based on the use of a ring buffer, which initially contains zeros. We read several characters from the file into the buffer, and then search the buffer for the longest string that matches the characters just read, and output the length and position of the match in the buffer. With a buffer size of 4096 bytes, the position can be encoded in 12 bits. If we represent the match length in four bits, the pair is two bytes long. If the longest match is no more than two characters, then we send just one character without encoding, and restart the process with the next letter. We must send one extra bit each time to tell the decoder whether we are sending a pair or an unencoded character, and these flags are stored as an eight bit mask every eight items. This implementation uses binary trees to speed up the search for the longest match. Original code by Haruhiko Okumura, 4/6/1989. 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, Japan. Modified for use in the Allegro filesystem by Shawn Hargreaves. Use, distribute, and modify this code freely. */ #define N 4096 /* 4k buffers for LZ compression */ #define F 18 /* upper limit for LZ match length */ #define THRESHOLD 2 /* LZ encode string into pos and length if match size is greater than this */ struct LZSS_PACK_DATA /* stuff for doing LZ compression */ { int state; /* where have we got to in the pack? */ int i, c, len, r, s; int last_match_length, code_buf_ptr; unsigned char mask; char code_buf[17]; int match_position; int match_length; int lson[N+1]; /* left children, */ int rson[N+257]; /* right children, */ int dad[N+1]; /* and parents, = binary search trees */ unsigned char text_buf[N+F-1]; /* ring buffer, with F-1 extra bytes for string comparison */ }; struct LZSS_UNPACK_DATA /* for reading LZ files */ { int state; /* where have we got to? */ int i, j, k, r, c; int flags; unsigned char text_buf[N+F-1]; /* ring buffer, with F-1 extra bytes for string comparison */ }; /*** Compression (writing) ***/ /* create_lzss_pack_data: * Creates a PACK_DATA structure. */ LZSS_PACK_DATA *create_lzss_pack_data(void) { LZSS_PACK_DATA *dat; int c; if ((dat = _AL_MALLOC_ATOMIC(sizeof(LZSS_PACK_DATA))) == NULL) { *allegro_errno = ENOMEM; return NULL; } for (c=0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; return dat; } /* free_lzss_pack_data: * Frees an LZSS_PACK_DATA structure. */ void free_lzss_pack_data(LZSS_PACK_DATA *dat) { ASSERT(dat); _AL_FREE(dat); } /* lzss_inittree: * For i = 0 to N-1, rson[i] and lson[i] will be the right and left * children of node i. These nodes need not be initialized. Also, dad[i] * is the parent of node i. These are initialized to N, which stands for * 'not used.' For i = 0 to 255, rson[N+i+1] is the root of the tree for * strings that begin with character i. These are initialized to N. Note * there are 256 trees. */ static void lzss_inittree(LZSS_PACK_DATA *dat) { int i; for (i=N+1; i<=N+256; i++) dat->rson[i] = N; for (i=0; idad[i] = N; } /* lzss_insertnode: * Inserts a string of length F, text_buf[r..r+F-1], into one of the trees * (text_buf[r]'th tree) and returns the longest-match position and length * via match_position and match_length. If match_length = F, then removes * the old node in favor of the new one, because the old one will be * deleted sooner. Note r plays double role, as tree node and position in * the buffer. */ static void lzss_insertnode(int r, LZSS_PACK_DATA *dat) { int i, p, cmp; unsigned char *key; unsigned char *text_buf = dat->text_buf; cmp = 1; key = &text_buf[r]; p = N + 1 + key[0]; dat->rson[r] = dat->lson[r] = N; dat->match_length = 0; for (;;) { if (cmp >= 0) { if (dat->rson[p] != N) p = dat->rson[p]; else { dat->rson[p] = r; dat->dad[r] = p; return; } } else { if (dat->lson[p] != N) p = dat->lson[p]; else { dat->lson[p] = r; dat->dad[r] = p; return; } } for (i = 1; i < F; i++) if ((cmp = key[i] - text_buf[p + i]) != 0) break; if (i > dat->match_length) { dat->match_position = p; if ((dat->match_length = i) >= F) break; } } dat->dad[r] = dat->dad[p]; dat->lson[r] = dat->lson[p]; dat->rson[r] = dat->rson[p]; dat->dad[dat->lson[p]] = r; dat->dad[dat->rson[p]] = r; if (dat->rson[dat->dad[p]] == p) dat->rson[dat->dad[p]] = r; else dat->lson[dat->dad[p]] = r; dat->dad[p] = N; /* remove p */ } /* lzss_deletenode: * Removes a node from a tree. */ static void lzss_deletenode(int p, LZSS_PACK_DATA *dat) { int q; if (dat->dad[p] == N) return; /* not in tree */ if (dat->rson[p] == N) q = dat->lson[p]; else if (dat->lson[p] == N) q = dat->rson[p]; else { q = dat->lson[p]; if (dat->rson[q] != N) { do { q = dat->rson[q]; } while (dat->rson[q] != N); dat->rson[dat->dad[q]] = dat->lson[q]; dat->dad[dat->lson[q]] = dat->dad[q]; dat->lson[q] = dat->lson[p]; dat->dad[dat->lson[p]] = q; } dat->rson[q] = dat->rson[p]; dat->dad[dat->rson[p]] = q; } dat->dad[q] = dat->dad[p]; if (dat->rson[dat->dad[p]] == p) dat->rson[dat->dad[p]] = q; else dat->lson[dat->dad[p]] = q; dat->dad[p] = N; } /* lzss_write: * Packs size bytes from buf, using the pack information contained in dat. * Returns 0 on success. */ int lzss_write(PACKFILE *file, LZSS_PACK_DATA *dat, int size, unsigned char *buf, int last) { int i = dat->i; int c = dat->c; int len = dat->len; int r = dat->r; int s = dat->s; int last_match_length = dat->last_match_length; int code_buf_ptr = dat->code_buf_ptr; unsigned char mask = dat->mask; int ret = 0; if (dat->state==2) goto pos2; else if (dat->state==1) goto pos1; dat->code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and code_buf[0] works as eight flags, "1" representing that the unit is an unencoded letter (1 byte), "0" a position-and-length pair (2 bytes). Thus, eight units require at most 16 bytes of code. */ code_buf_ptr = mask = 1; s = 0; r = N - F; lzss_inittree(dat); for (len=0; (len < F) && (size > 0); len++) { dat->text_buf[r+len] = *(buf++); if (--size == 0) { if (!last) { dat->state = 1; goto getout; } } pos1: ; } if (len == 0) goto getout; for (i=1; i <= F; i++) lzss_insertnode(r-i,dat); /* Insert the F strings, each of which begins with one or more 'space' characters. Note the order in which these strings are inserted. This way, degenerate trees will be less likely to occur. */ lzss_insertnode(r,dat); /* Finally, insert the whole string just read. match_length and match_position are set. */ do { if (dat->match_length > len) dat->match_length = len; /* match_length may be long near the end */ if (dat->match_length <= THRESHOLD) { dat->match_length = 1; /* not long enough match: send one byte */ dat->code_buf[0] |= mask; /* 'send one byte' flag */ dat->code_buf[code_buf_ptr++] = dat->text_buf[r]; /* send uncoded */ } else { /* send position and length pair. Note match_length > THRESHOLD */ dat->code_buf[code_buf_ptr++] = (unsigned char) dat->match_position; dat->code_buf[code_buf_ptr++] = (unsigned char) (((dat->match_position >> 4) & 0xF0) | (dat->match_length - (THRESHOLD + 1))); } if ((mask <<= 1) == 0) { /* shift mask left one bit */ if ((file->is_normal_packfile) && (file->normal.passpos) && (file->normal.flags & PACKFILE_FLAG_OLD_CRYPT)) { dat->code_buf[0] ^= *file->normal.passpos; file->normal.passpos++; if (!*file->normal.passpos) file->normal.passpos = file->normal.passdata; } for (i=0; icode_buf[i], file); /* code together */ if (pack_ferror(file)) { ret = EOF; goto getout; } dat->code_buf[0] = 0; code_buf_ptr = mask = 1; } last_match_length = dat->match_length; for (i=0; (i < last_match_length) && (size > 0); i++) { c = *(buf++); if (--size == 0) { if (!last) { dat->state = 2; goto getout; } } pos2: lzss_deletenode(s,dat); /* delete old strings and */ dat->text_buf[s] = c; /* read new bytes */ if (s < F-1) dat->text_buf[s+N] = c; /* if the position is near the end of buffer, extend the buffer to make string comparison easier */ s = (s+1) & (N-1); r = (r+1) & (N-1); /* since this is a ring buffer, increment the position modulo N */ lzss_insertnode(r,dat); /* register the string in text_buf[r..r+F-1] */ } while (i++ < last_match_length) { /* after the end of text, */ lzss_deletenode(s,dat); /* no need to read, but */ s = (s+1) & (N-1); /* buffer may not be empty */ r = (r+1) & (N-1); if (--len) lzss_insertnode(r,dat); } } while (len > 0); /* until length of string to be processed is zero */ if (code_buf_ptr > 1) { /* send remaining code */ if ((file->is_normal_packfile) && (file->normal.passpos) && (file->normal.flags & PACKFILE_FLAG_OLD_CRYPT)) { dat->code_buf[0] ^= *file->normal.passpos; file->normal.passpos++; if (!*file->normal.passpos) file->normal.passpos = file->normal.passdata; } for (i=0; icode_buf[i], file); if (pack_ferror(file)) { ret = EOF; goto getout; } } } dat->state = 0; getout: dat->i = i; dat->c = c; dat->len = len; dat->r = r; dat->s = s; dat->last_match_length = last_match_length; dat->code_buf_ptr = code_buf_ptr; dat->mask = mask; return ret; } /*** Decompression (reading) ***/ /* create_unpack_data: * Creates an LZSS_UNPACK_DATA structure. */ LZSS_UNPACK_DATA *create_lzss_unpack_data(void) { LZSS_UNPACK_DATA *dat; int c; if ((dat = _AL_MALLOC_ATOMIC(sizeof(LZSS_UNPACK_DATA))) == NULL) { *allegro_errno = ENOMEM; return NULL; } for (c=0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; return dat; } /* free_lzss_unpack_data: * Frees an LZSS_UNPACK_DATA structure. */ void free_lzss_unpack_data(LZSS_UNPACK_DATA *dat) { ASSERT(dat); _AL_FREE(dat); } /* lzss_read: * Unpacks from dat into buf, until either EOF is reached or s bytes have * been extracted. Returns the number of bytes added to the buffer */ int lzss_read(PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, unsigned char *buf) { int i = dat->i; int j = dat->j; int k = dat->k; int r = dat->r; int c = dat->c; unsigned int flags = dat->flags; int size = 0; if (dat->state==2) goto pos2; else if (dat->state==1) goto pos1; r = N-F; flags = 0; for (;;) { if (((flags >>= 1) & 256) == 0) { if ((c = pack_getc(file)) == EOF) break; if ((file->is_normal_packfile) && (file->normal.passpos) && (file->normal.flags & PACKFILE_FLAG_OLD_CRYPT)) { c ^= *file->normal.passpos; file->normal.passpos++; if (!*file->normal.passpos) file->normal.passpos = file->normal.passdata; } flags = c | 0xFF00; /* uses higher byte to count eight */ } if (flags & 1) { if ((c = pack_getc(file)) == EOF) break; dat->text_buf[r++] = c; r &= (N - 1); *(buf++) = c; if (++size >= s) { dat->state = 1; goto getout; } pos1: ; } else { if ((i = pack_getc(file)) == EOF) break; if ((j = pack_getc(file)) == EOF) break; i |= ((j & 0xF0) << 4); j = (j & 0x0F) + THRESHOLD; for (k=0; k <= j; k++) { c = dat->text_buf[(i + k) & (N - 1)]; dat->text_buf[r++] = c; r &= (N - 1); *(buf++) = c; if (++size >= s) { dat->state = 2; goto getout; } pos2: ; } } } dat->state = 0; getout: dat->i = i; dat->j = j; dat->k = k; dat->r = r; dat->c = c; dat->flags = flags; return size; } /* _al_lzss_incomplete_state: * Return non-zero if the previous lzss_read() call was in the middle of * unpacking a sequence of bytes into the supplied buffer, but had to suspend * because the buffer wasn't big enough. */ int _al_lzss_incomplete_state(AL_CONST LZSS_UNPACK_DATA *dat) { return dat->state == 2; } allegro-4.4.3.1/src/amd64/0000775000175000017500000000000013437077643014002 5ustar siegesiegeallegro-4.4.3.1/src/amd64/acpus.s0000664000175000017500000000522113437077643015301 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * AMD64 CPU detection routines, by Evert Glebbeek. * * Original i386 code by Phil Frisbie. * * See readme.txt for copyright information. */ #include "asmdefs.inc" .text /* int _i_is_486(); * Returns TRUE for 486+, and FALSE for 386. */ FUNC(_i_is_486) movl $0, %eax /* 80486 not present */ ret /* int _i_is_fpu(); * Returns TRUE is the CPU has floating point hardware. */ FUNC(_i_is_fpu) movl $1, %eax ret /* int _i_is_cyrix(); * Returns TRUE if this is a Cyrix processor. */ FUNC(_i_is_cyrix) movl $0, %eax /* FALSE NON-Cyrix CPU */ ret /* void _i_cx_w(int index, int value); * Writes to a Cyrix register. */ FUNC(_i_cx_w) ret /* char _i_cx_r(int index); * Reads from a Cyrix register. */ FUNC(_i_cx_r) ret /* int _i_is_cpuid_supported(); * Checks whether the cpuid instruction is available. */ FUNC(_i_is_cpuid_supported) pushq %rbp movq %rsp, %rbp pushfq /* get extended flags */ popq %rax movq %rax, %rdx /* save current flags */ xorq $0x200000, %rax /* toggle bit 21 */ pushq %rax /* put new flags on stack */ popfq /* flags updated now in flags */ pushfq /* get extended flags */ popq %rax xorq %rdx, %rax /* if bit 21 r/w then supports cpuid */ jz cpuid_not_found movl $1, %eax jmp cpuid_done cpuid_not_found: movl $0, %eax cpuid_done: popq %rbp ret /* void _i_get_cpuid_info(int cpuid_levels, int *reg); * This is so easy! */ FUNC(_i_get_cpuid_info) pushq %rbp movq %rsp, %rbp pushq %rbx pushq %rcx pushq %rdi /* rdi contains the first argument */ movl %edi, %eax /* eax = cpuid_levels */ .byte 0x0F, 0xA2 /* cpuid instruction */ /* rsi contains the second argument */ movl %eax, (%rsi) /* store results */ movl %ebx, 4(%rsi) /* store results */ movl %ecx, 8(%rsi) /* store results */ movl %edx, 12(%rsi) /* store results */ popq %rdi popq %rcx popq %rbx popq %rbp ret allegro-4.4.3.1/src/amd64/asmdefs.inc0000664000175000017500000000632713437077643016127 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * A few macros to make my asm code (slightly :-) more readable. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef ALLEGRO_ASMDEFS_INC #define ALLEGRO_ASMDEFS_INC #ifndef SCAN_DEPEND #include "allegro/platform/alplatf.h" #endif #if defined ALLEGRO_UNIX #define FUNC(name) .globl name ; _align_ ; .type name,@function ; name: #else #define FUNC(name) .globl name ; _align_ ; name: #endif /* helper macro in case we ever need to change this */ #define _align_ .balign 4, 0x90 /* readable way to access the nth argument passed from C code * i is the number of 32 bit arguments passed before and including this one, * l is the number of 64 bit arguments passed before and including this one */ #define ARG(i,l) (4*(i+1) + 8*l)(%rbp) /* integer arguments */ #define ARG1 ARG(1, 0) #define ARG2 ARG(2, 0) #define ARG3 ARG(3, 0) #define ARG4 ARG(4, 0) #define ARG5 ARG(5, 0) #define ARG6 ARG(6, 0) #define ARG7 ARG(7, 0) #define ARG8 ARG(8, 0) #define ARG9 ARG(9, 0) #define ARG10 ARG(10, 0) /* Bank switching macros. These should be called with a pointer to the * bitmap structure in %rdx, and the line number you want to access in * %rax. Registers will be unchanged, except %rax will return a pointer * to the start of the selected scanline. */ #define WRITE_BANK() call *BMP_WBANK(%rdx) #define READ_BANK() call *BMP_RBANK(%rdx) #define UNWRITE_BANK() movl BMP_VTABLE(%rdx), %rax ; call *VTABLE_UNBANK(%rax) #define UNREAD_BANK() movl BMP_VTABLE(%rdx), %rax ; call *VTABLE_UNBANK(%rax) /* Helper macro for looking up a position in the pattern bitmap. Passed * registers containing the x and y coordinates of the point, it returns * a 'start of pattern line' pointer in y, and an offset into this line * in x. It clobbers the tmp register. */ #define LOOKUP_PATTERN_POS(x, y, tmp) ; \ subl GLOBL(_drawing_x_anchor), x /* adjust x */ ; \ andl GLOBL(_drawing_x_mask), x /* limit range of x */ ; \ ; \ subl GLOBL(_drawing_y_anchor), y /* adjust y */ ; \ andl GLOBL(_drawing_y_mask), y /* limit range of y */ ; \ ; \ movl GLOBL(_drawing_pattern), tmp /* get position in pattern */ ; \ movl BMP_LINE(tmp, y, sizeof(unsigned char*)), y /* How many stacks to allocate for the irq wrappers. This can't be in the * main headers, because it is used by both C and asm code. You could * probably get away with fewer of these, if you want to save memory and * you are feeling brave... */ #define IRQ_STACKS 8 #endif /* ifndef ALLEGRO_ASMDEFS_INC */ allegro-4.4.3.1/src/dos/0000775000175000017500000000000013437077643013654 5ustar siegesiegeallegro-4.4.3.1/src/dos/emu8k.c0000664000175000017500000007431413437077643015062 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Low-level functions for the AWE32 driver. * * By George Foot. * * Information taken primarily from "AWE32/EMU8000 Programmer's Guide" * (AEPG) by Dave Rossum. The AEPG is part of the AWE32 Developers' * Information Pack (ADIP) from Creative Labs. * * I/O port verification technique taken from "The Un-official Sound * Blaster AWE32 Programming Guide" by Vince Vu a.k.a. Judge Dredd * * Miscellaneous guidance taken from Takashi Iwai's Linux AWE32 driver * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "emu8k.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /****************************************************************************\ * * * EMU8000.H : EMU8000 init arrays ( for hardware level programming only ) * * * * (C) Copyright Creative Technology Ltd. 1992-96. All rights reserved * * worldwide. * * * * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * * PURPOSE. * * * \****************************************************************************/ static unsigned short init1_1[32] = { 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30 }; static unsigned short init1_2[32] = { 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30 }; static unsigned short init1_3[32] = { 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30 }; static unsigned short init1_4[32] = { 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30 }; static unsigned short init2_1[32] = { 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30 }; static unsigned short init2_2[32] = { 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30 }; static unsigned short init2_3[32] = { 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30 }; static unsigned short init2_4[32] = { 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30 }; static unsigned short init3_1[32] = { 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224 }; static unsigned short init3_2[32] = { 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3 }; static unsigned short init3_3[32] = { 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55 }; static unsigned short init3_4[32] = { 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570 }; static unsigned short init4_1[32] = { 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224 }; static unsigned short init4_2[32] = { 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3 }; static unsigned short init4_3[32] = { 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55 }; static unsigned short init4_4[32] = { 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570 }; /*** (end of init arrays) ***/ #define MIN_LOOP_LEN 2 int _emu8k_baseport = 0; int _emu8k_numchannels = 32; /* Functions to deal with the AWE32's I/O ports */ static INLINE void write_word(int reg, int channel, int port, int data) { int out_port = _emu8k_baseport; switch (port) { case 0: out_port += 0x0000; break; case 1: out_port += 0x0400; break; case 2: out_port += 0x0402; break; case 3: out_port += 0x0800; break; default: return; } outportw(_emu8k_baseport + 0x802, (reg << 5) + (channel & 0x1f)); outportw(out_port, data); } static INLINE unsigned int read_word(int reg, int channel, int port) { int in_port = _emu8k_baseport; switch (port) { case 0: in_port += 0x0000; break; case 1: in_port += 0x0400; break; case 2: in_port += 0x0402; break; case 3: in_port += 0x0800; break; default: return 0; } outportw(_emu8k_baseport + 0x802, (reg << 5) + (channel & 0x1f)); return inportw(in_port); } static INLINE void write_dword(int reg, int channel, int port, unsigned int data) { int out_port = _emu8k_baseport; switch (port) { case 0: out_port += 0x0000; break; case 1: out_port += 0x0400; break; case 2: out_port += 0x0402; break; case 3: out_port += 0x0800; break; default: return; } outportw(_emu8k_baseport + 0x802, (reg << 5) + (channel & 0x1f)); outportw(out_port, data & 0xffff); outportw(out_port + 2, (data >> 16) & 0xffff); } static INLINE unsigned int read_dword(int reg, int channel, int port) { int in_port, a, b; in_port = _emu8k_baseport; switch (port) { case 0: in_port += 0x0000; break; case 1: in_port += 0x0400; break; case 2: in_port += 0x0402; break; case 3: in_port += 0x0800; break; default: return 0; } outportw(_emu8k_baseport + 0x802, (reg << 5) + (channel & 0x1f)); a = inportw(in_port); b = inportw(in_port + 2); return ((b << 16) + a); } /* write_*: * Functions to write information to the AWE32's registers * (abbreviated as in the EPG). */ static INLINE void write_CPF(int channel, int i) { write_dword(0, channel, 0, i); } static INLINE void write_PTRX(int channel, int i) { write_dword(1, channel, 0, i); } static INLINE void write_CVCF(int channel, int i) { write_dword(2, channel, 0, i); } static INLINE void write_VTFT(int channel, int i) { write_dword(3, channel, 0, i); } static INLINE void write_PSST(int channel, int i) { write_dword(6, channel, 0, i); } static INLINE void write_CSL(int channel, int i) { write_dword(7, channel, 0, i); } static INLINE void write_CCCA(int channel, int i) { write_dword(0, channel, 1, i); } static INLINE void write_HWCF4(int i) { write_dword(1, 9, 1, i); } static INLINE void write_HWCF5(int i) { write_dword(1, 10, 1, i); } static INLINE void write_HWCF6(int i) { write_dword(1, 13, 1, i); } static INLINE void write_SMALR(int i) { write_dword(1, 20, 1, i); } static INLINE void write_SMARR(int i) { write_dword(1, 21, 1, i); } static INLINE void write_SMALW(int i) { write_dword(1, 22, 1, i); } static INLINE void write_SMARW(int i) { write_dword(1, 23, 1, i); } /* static INLINE void write_SMLD(int i) { write_word(1, 26, 1, i); } */ /* static INLINE void write_SMRD(int i) { write_word(1, 26, 2, i); } */ /* static INLINE void write_WC(int i) { write_word(1, 27, 2, i); } */ static INLINE void write_HWCF1(int i) { write_word(1, 29, 1, i); } static INLINE void write_HWCF2(int i) { write_word(1, 30, 1, i); } static INLINE void write_HWCF3(int i) { write_word(1, 31, 1, i); } static INLINE void write_INIT1(int channel, int i) { write_word(2, channel, 1, i); } /* `channel' is really `element' here */ static INLINE void write_INIT2(int channel, int i) { write_word(2, channel, 2, i); } static INLINE void write_INIT3(int channel, int i) { write_word(3, channel, 1, i); } static INLINE void write_INIT4(int channel, int i) { write_word(3, channel, 2, i); } static INLINE void write_ENVVOL(int channel, int i) { write_word(4, channel, 1, i); } static INLINE void write_DCYSUSV(int channel, int i) { write_word(5, channel, 1, i); } static INLINE void write_ENVVAL(int channel, int i) { write_word(6, channel, 1, i); } static INLINE void write_DCYSUS(int channel, int i) { write_word(7, channel, 1, i); } static INLINE void write_ATKHLDV(int channel, int i) { write_word(4, channel, 2, i); } static INLINE void write_LFO1VAL(int channel, int i) { write_word(5, channel, 2, i); } static INLINE void write_ATKHLD(int channel, int i) { write_word(6, channel, 2, i); } static INLINE void write_LFO2VAL(int channel, int i) { write_word(7, channel, 2, i); } static INLINE void write_IP(int channel, int i) { write_word(0, channel, 3, i); } static INLINE void write_IFATN(int channel, int i) { write_word(1, channel, 3, i); } static INLINE void write_PEFE(int channel, int i) { write_word(2, channel, 3, i); } static INLINE void write_FMMOD(int channel, int i) { write_word(3, channel, 3, i); } static INLINE void write_TREMFRQ(int channel, int i) { write_word(4, channel, 3, i); } static INLINE void write_FM2FRQ2(int channel, int i) { write_word(5, channel, 3, i); } /* read_*: * Functions to read information from the AWE32's registers * (abbreviated as in the AEPG). */ /* static INLINE int read_CPF(int channel) { return read_dword(0, channel, 0); } */ /* static INLINE int read_PTRX(int channel) { return read_dword(1, channel, 0); } */ /* static INLINE int read_CVCF(int channel) { return read_dword(2, channel, 0); } */ /* static INLINE int read_VTFT(int channel) { return read_dword(3, channel, 0); } */ static INLINE int read_PSST(int channel) { return read_dword(6, channel, 0); } /* static INLINE int read_CSL(int channel) { return read_dword(7, channel, 0); } */ /* static INLINE int read_CCCA(int channel) { return read_dword(0, channel, 1); } */ /* static INLINE int read_HWCF4(void) { return read_dword(1, 9, 1); } */ /* static INLINE int read_HWCF5(void) { return read_dword(1, 10, 1); } */ /* static INLINE int read_HWCF6(void) { return read_dword(1, 13, 1); } */ /* static INLINE int read_SMALR(void) { return read_dword(1, 20, 1); } */ /* static INLINE int read_SMARR(void) { return read_dword(1, 21, 1); } */ /* static INLINE int read_SMALW(void) { return read_dword(1, 22, 1); } */ /* static INLINE int read_SMARW(void) { return read_dword(1, 23, 1); } */ /* static INLINE int read_SMLD(void) { return read_word(1, 26, 1); } */ /* static INLINE int read_SMRD(void) { return read_word(1, 26, 2); } */ /* static INLINE int read_WC(void) { return read_word(1, 27, 2); } */ /* static INLINE int read_HWCF1(void) { return read_word(1, 29, 1); } */ /* static INLINE int read_HWCF2(void) { return read_word(1, 30, 1); } */ /* static INLINE int read_HWCF3(void) { return read_word(1, 31, 1); } */ /* static INLINE int read_INIT1(void) { return read_word(2, 0, 1); } */ /* static INLINE int read_INIT2(void) { return read_word(2, 0, 2); } */ /* static INLINE int read_INIT3(void) { return read_word(3, 0, 1); } */ /* static INLINE int read_INIT4(void) { return read_word(3, 0, 2); } */ /* static INLINE int read_ENVVOL(int channel) { return read_word(4, channel, 1); } */ /* static INLINE int read_DCYSUSV(int channel) { return read_word(5, channel, 1); } */ /* static INLINE int read_ENVVAL(int channel) { return read_word(6, channel, 1); } */ /* static INLINE int read_DCYSUS(int channel) { return read_word(7, channel, 1); } */ /* static INLINE int read_ATKHLDV(int channel) { return read_word(4, channel, 2); } */ /* static INLINE int read_LFO1VAL(int channel) { return read_word(5, channel, 2); } */ /* static INLINE int read_ATKHLD(int channel) { return read_word(6, channel, 2); } */ /* static INLINE int read_LFO2VAL(int channel) { return read_word(7, channel, 2); } */ /* static INLINE int read_IP(int channel) { return read_word(0, channel, 3); } */ static INLINE int read_IFATN(int channel) { return read_word(1, channel, 3); } /* static INLINE int read_PEFE(int channel) { return read_word(2, channel, 3); } */ /* static INLINE int read_FMMOD(int channel) { return read_word(3, channel, 3); } */ /* static INLINE int read_TREMFRQ(int channel) { return read_word(4, channel, 3); } */ /* static INLINE int read_FM2FRQ2(int channel) { return read_word(5, channel, 3); } */ /* wait_*: * Functions to wait for DMA streams to be ready. */ /* static INLINE void wait_LR(void) { while (read_SMALR() & 0x80000000) ; } */ /* static INLINE void wait_LW(void) { while (read_SMALW() & 0x80000000) ; } */ /* static INLINE void wait_RR(void) { while (read_SMARR() & 0x80000000) ; } */ /* static INLINE void wait_RW(void) { while (read_SMARW() & 0x80000000) ; } */ /* write_init_arrays: * Writes the given set of initialisation arrays to the card. */ static void write_init_arrays(unsigned short *init1, unsigned short *init2, unsigned short *init3, unsigned short *init4) { int i; for (i = 0; i < 32; i++) write_INIT1(i, init1[i]); for (i = 0; i < 32; i++) write_INIT2(i, init2[i]); for (i = 0; i < 32; i++) write_INIT3(i, init3[i]); for (i = 0; i < 32; i++) write_INIT4(i, init4[i]); } /* emu8k_init: * Initialise the synthesiser. See AEPG chapter 4. */ void emu8k_init(void) { int channel; write_HWCF1(0x0059); write_HWCF2(0x0020); for (channel=0; channel<_emu8k_numchannels; channel++) write_DCYSUSV(channel, 0x0080); for (channel=0; channel<_emu8k_numchannels; channel++) { write_ENVVOL(channel, 0); write_ENVVAL(channel, 0); write_DCYSUS(channel, 0); write_ATKHLDV(channel, 0); write_LFO1VAL(channel, 0); write_ATKHLD(channel, 0); write_LFO2VAL(channel, 0); write_IP(channel, 0); write_IFATN(channel, 0); write_PEFE(channel, 0); write_FMMOD(channel, 0); write_TREMFRQ(channel, 0); write_FM2FRQ2(channel, 0); write_PTRX(channel, 0); write_VTFT(channel, 0); write_PSST(channel, 0); write_CSL(channel, 0); write_CCCA(channel, 0); } for (channel=0; channel<_emu8k_numchannels; channel++) { write_CPF(channel, 0); write_CVCF(channel, 0); } write_SMALR(0); write_SMARR(0); write_SMALW(0); write_SMARW(0); write_init_arrays(init1_1, init1_2, init1_3, init1_4); rest(25); /* wait 24 msec + 1 for luck */ write_init_arrays(init2_1, init2_2, init2_3, init2_4); write_init_arrays(init3_1, init3_2, init3_3, init3_4); write_HWCF4(0); write_HWCF5(0x00000083); write_HWCF6(0x00008000); write_init_arrays(init4_1, init4_2, init4_3, init4_4); write_HWCF3(0x0004); } /* emu8k_startsound: * Start a sound on a channel. */ void emu8k_startsound(int channel, struct envparms_t *envparms) { int psst = 0, csl = 0; write_DCYSUSV(channel, 0x0080); write_VTFT(channel, 0); write_CVCF(channel, 0); write_PTRX(channel, 0); write_CPF(channel, 0); write_ENVVOL(channel, envparms->envvol); write_ENVVAL(channel, envparms->envval); write_DCYSUS(channel, envparms->dcysus); write_ATKHLDV(channel, envparms->atkhldv); write_LFO1VAL(channel, envparms->lfo1val); write_ATKHLD(channel, envparms->atkhld); write_LFO2VAL(channel, envparms->lfo2val); write_IP(channel, envparms->ip); write_IFATN(channel, envparms->ifatn); write_PEFE(channel, envparms->pefe); write_FMMOD(channel, envparms->fmmod); write_TREMFRQ(channel, envparms->tremfrq); write_FM2FRQ2(channel, envparms->fm2frq2); switch (envparms->smpmode & 3) { case 0: /* no looping */ case 2: /* invalid; should be read as `no looping' */ psst = (envparms->psst & 0xff000000) /* copy pan verbatim; mask out loop start */ + (envparms->sampend) /* set loop start to near sample end */ - MIN_LOOP_LEN; csl = (envparms->csl & 0xff000000) /* copy chorus verbatim; mask out loop end */ + (envparms->sampend) /* set loop end to sample end */ + MIN_LOOP_LEN; break; case 1: /* loop indefinitely */ case 3: /* loop until key released, then continue */ psst = envparms->psst; /* leave the loop as it stands */ csl = envparms->csl; break; } write_PSST(channel, psst); write_CSL(channel, csl); write_CCCA(channel, envparms->ccca); write_VTFT(channel, 0x0000FFFF); write_CVCF(channel, 0x0000FFFF); write_DCYSUSV(channel, envparms->dcysusv); write_PTRX(channel, envparms->ptrx); write_CPF(channel, 0x40000000); } END_OF_STATIC_FUNCTION(emu8k_startsound); /* emu8k_releasesound: * End a sound on a channel by starting its release phase. */ void emu8k_releasesound(int channel, struct envparms_t *envparms) { if (envparms->smpmode == 3) { /* If sound should stop looping and continue, do so */ write_CSL(channel, (envparms->chorus << 24) + envparms->sampend + MIN_LOOP_LEN); write_PSST(channel, (envparms->pan << 24) + envparms->sampend - MIN_LOOP_LEN); } write_DCYSUSV(channel, 0x8000 + envparms->volrel); /* Start volume envelope release phase */ write_DCYSUS(channel, 0x8000 + envparms->modrel); /* Start modulation envelope release phase */ } END_OF_STATIC_FUNCTION(emu8k_releasesound); /* emu8k_modulate_*: * Modulation functions - changing a channel's sound in various ways. */ void emu8k_modulate_atten(int channel, int atten) { int ifatn; ifatn = read_IFATN(channel); write_IFATN(channel, (ifatn & 0xff00) + (atten & 0xff)); } END_OF_STATIC_FUNCTION(emu8k_modulate_atten); void emu8k_modulate_ip(int channel, int ip) { write_IP(channel, ip); } END_OF_STATIC_FUNCTION(emu8k_modulate_ip); void emu8k_modulate_pan(int channel, int pan) { int psst; psst = read_PSST(channel); write_PSST(channel, (pan << 24) + (psst & 0x00ffffff)); } END_OF_STATIC_FUNCTION(emu8k_modulate_pan); /* emu8k_terminatesound: * End a sound on a channel immediately (may produce an audible click). */ void emu8k_terminatesound(int channel) { write_DCYSUSV(channel, 0x0080); write_VTFT(channel, 0x0000FFFF); write_CVCF(channel, 0x0000FFFF); } END_OF_STATIC_FUNCTION(emu8k_terminatesound); /* emu8k_detect: * Locate the EMU8000. This tries to extract the base port from the E section * of the BLASTER environment variable, and then does some test reads to check * that there is an EMU8000 there. */ int emu8k_detect(void) { char *envvar; if (!(envvar = getenv("BLASTER"))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("BLASTER environment variable not set")); return 0; } _emu8k_baseport = 0; while (*envvar) { if (*envvar == 'E') _emu8k_baseport = strtol(envvar + 1, NULL, 16); while ((*envvar != ' ') && (*envvar != 0)) envvar++; if (*envvar) envvar++; } if (!_emu8k_baseport) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("BLASTER environment variable has no E section")); return 0; } uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("AWE32 detection failed on port 0x%04x"), _emu8k_baseport); if ((read_word(7, 0, 3) & 0x000f) != 0x000c) return 0; if ((read_word(1, 29, 1) & 0x007e) != 0x0058) return 0; if ((read_word(1, 30, 1) & 0x0003) != 0x0003) return 0; usetc(allegro_error, 0); return 1; } /* emu_*: * Functions to convert SoundFont information to EMU8000 parameters. */ static INLINE unsigned short emu_delay(int x) { int a = 0x8000 - pow(2, x / 1200.0) / 0.000725; return (a < 0) ? 0 : ((a > 0x8000) ? 0x8000 : a); } static INLINE unsigned char emu_attack(int x) { /* * AEPG doesn't specify exact conversion here; I'm using what Takashi * Iwai used for his Linux driver */ int a, msec; msec = pow(2, x / 1200.0) * 1000; if (msec == 0) return 0x7f; a = 11878 / msec; return (a < 1) ? 1 : ((a > 0x7f) ? 0x7f : a); } static INLINE unsigned char emu_hold(int x) { int a = 0x7f - (int)(pow(2, x / 1200.0) * 0x7f / 11.68); return (a < 0) ? 0 : ((a > 0x7f) ? 0x7f : a); } static INLINE unsigned char emu_decay(int x) { /* * AEPG doesn't specify exact conversion here; I'm using an adaptation of * what Takashi Iwai used for his Linux driver */ int a, msec; msec = pow(2, x / 1200.0) * 1000; if (msec == 0) return 0x7f; a = 0x7f - 54.8 * log10(msec / 23.04); /* Takashi's */ // a = 47349/(msec+349); /* mine */ return (a < 1) ? 1 : ((a > 0x7f) ? 0x7f : a); } static INLINE unsigned char emu_sustain(int x) { /* This is not the same as in Takashi Iwai's Linux driver, but I think I'm right */ int a = 0x7f - x / 7.5; return (a < 0) ? 0 : ((a > 0x7f) ? 0x7f : a); } static INLINE unsigned char emu_release(int x) { return emu_decay(x); } static INLINE unsigned char emu_mod(int x, int peak_deviation) { int a = x * 0x80 / peak_deviation; return (a < -0x80) ? 0x80 : ((a > 0x7f) ? 0x7f : a); } static INLINE unsigned char emu_freq(int x) { int a = (8.176 * pow(2, x / 1200.0) + 0.032) / 0.042; return (a < 0) ? 0 : ((a > 0xff) ? 0xff : a); } static INLINE unsigned char emu_reverb(int x) { int a = (x * 0xff) / 1000; return (a < 0) ? 0 : ((a > 0xff) ? 0xff : a); } static INLINE unsigned char emu_chorus(int x) { int a = (x * 0xff) / 1000; return (a < 0) ? 0 : ((a > 0xff) ? 0xff : a); } static INLINE unsigned char emu_pan(int x) { int a = 0x7f - (x * 0xff) / 1000; return (a < 8) ? 8 : ((a > 0xf8) ? 0xf8 : a); } static INLINE unsigned char emu_filterQ(int x) { int a = (x / 15); return (a < 0) ? 0 : ((a > 15) ? 15 : a); } static INLINE unsigned int emu_address(int base, int offset, int coarse_offset) { return base + offset + coarse_offset * 32 * 1024; } /* static INLINE unsigned short emu_pitch(int key, int rootkey, int scale, int coarse, int fine, int initial) { int a = (((key - rootkey) * scale + coarse * 100 + fine - initial) * 0x1000) / 1200 + 0xE000; return (a < 0) ? 0 : ((a > 0xFFFF) ? 0xFFFF : a); } */ static INLINE unsigned char emu_filter(int x) { int a = (x - 4721) / 25; return (a < 0) ? 0 : ((a > 0xff) ? 0xff : a); } static INLINE unsigned char emu_atten(int x) { int a = x / 3.75; return (a < 0) ? 0 : ((a > 0xff) ? 0xff : a); } /* emu8k_createenvelope: * Converts a set of SoundFont generators to equivalent EMU8000 register * settings, for passing to the sound playing functions above. */ envparms_t *emu8k_createenvelope(generators_t sfgen) { envparms_t *envelope = (envparms_t *) _lock_malloc(sizeof(envparms_t)); if (envelope) { envelope->envvol = emu_delay(sfgen[sfgen_delayModEnv]); envelope->envval = emu_delay(sfgen[sfgen_delayVolEnv]); envelope->modsust = (emu_sustain(sfgen[sfgen_sustainModEnv]) << 8); envelope->modrel = (emu_release(sfgen[sfgen_releaseModEnv]) << 0); envelope->dcysus = (0 << 15) // we're programming the decay, not the release + envelope->modsust + (0 << 7) // unused + (emu_decay(sfgen[sfgen_decayModEnv]) << 0); envelope->atkhldv = (0 << 15) // 0 otherwise it won't attack + (emu_hold(sfgen[sfgen_holdVolEnv]) << 8) + (0 << 7) // unused + (emu_attack(sfgen[sfgen_attackVolEnv]) << 0); envelope->lfo1val = emu_delay(sfgen[sfgen_delayModLFO]); envelope->atkhld = (0 << 15) // 0 otherwise it won't attack + (emu_hold(sfgen[sfgen_holdModEnv]) << 8) + (0 << 7) // unused + (emu_attack(sfgen[sfgen_attackModEnv]) << 0); envelope->lfo2val = emu_delay(sfgen[sfgen_delayVibLFO]); envelope->pitch = 0xe000; envelope->ip = envelope->pitch; envelope->filter = (emu_filter(sfgen[sfgen_initialFilterFc]) << 8); envelope->atten = (emu_atten(sfgen[sfgen_initialAttenuation]) << 0); envelope->ifatn = envelope->filter + envelope->atten; envelope->pefe = (emu_mod(sfgen[sfgen_modEnvToPitch], 1200) << 8) + (emu_mod(sfgen[sfgen_modEnvToFilterFc], 7200) << 0); envelope->fmmod = (emu_mod(sfgen[sfgen_modLfoToPitch], 1200) << 8) + (emu_mod(sfgen[sfgen_modLfoToFilterFc], 3600) << 0); envelope->tremfrq = (emu_mod(sfgen[sfgen_modLfoToVolume], 120) << 8) + (emu_freq(sfgen[sfgen_freqModLFO]) << 0); envelope->fm2frq2 = (emu_mod(sfgen[sfgen_vibLfoToPitch], 1200) << 8) + (emu_freq(sfgen[sfgen_freqVibLFO]) << 0); envelope->volsust = (emu_sustain(sfgen[sfgen_sustainVolEnv]) << 8); envelope->volrel = (emu_release(sfgen[sfgen_releaseVolEnv]) << 0); envelope->dcysusv = (0 << 15) // we're programming decay not release + envelope->volsust + (0 << 7) // turn on envelope engine + (emu_decay(sfgen[sfgen_decayVolEnv]) << 0); envelope->ptrx = (0x4000 << 16) // ??? I thought the top word wasn't for me to use + (emu_reverb(sfgen[sfgen_reverbEffectsSend]) << 8) + (0 << 0); // unused envelope->pan = emu_pan(sfgen[sfgen_pan]); envelope->loopst = emu_address(sfgen[gfgen_startloopAddrs], sfgen[sfgen_startloopAddrsOffset], sfgen[sfgen_startloopAddrsCoarseOffset]); envelope->sampend = emu_address(sfgen[gfgen_endAddrs], sfgen[sfgen_endAddrsOffset], sfgen[sfgen_endAddrsCoarseOffset]); envelope->psst = (envelope->pan << 24) + (envelope->loopst); envelope->chorus = emu_chorus(sfgen[sfgen_chorusEffectsSend]); envelope->csl = (envelope->chorus << 24) + (emu_address(sfgen[gfgen_endloopAddrs], sfgen[sfgen_endloopAddrsOffset], sfgen[sfgen_endloopAddrsCoarseOffset]) << 0); envelope->ccca = (emu_filterQ(sfgen[sfgen_initialFilterQ]) << 28) + (0 << 24) // DMA control bits + (emu_address(sfgen[gfgen_startAddrs], sfgen[sfgen_startAddrsOffset], sfgen[sfgen_startAddrsCoarseOffset]) << 0); envelope->rootkey = (sfgen[sfgen_overridingRootKey] != -1) ? sfgen[sfgen_overridingRootKey] : 69; envelope->ipbase = ((sfgen[sfgen_coarseTune] * 100 + sfgen[sfgen_fineTune] - envelope->rootkey * sfgen[sfgen_scaleTuning]) * 0x1000) / 1200 + 0xE000; envelope->ipscale = sfgen[sfgen_scaleTuning]; envelope->minkey = sfgen[sfgen_keyRange] & 0xff; envelope->maxkey = (sfgen[sfgen_keyRange] >> 8) & 0xff; envelope->minvel = sfgen[sfgen_velRange] & 0xff; envelope->maxvel = (sfgen[sfgen_velRange] >> 8) & 0xff; envelope->key = -1; envelope->vel = -1; envelope->exc = sfgen[sfgen_exclusiveClass]; envelope->keyMEH = 0; envelope->keyMED = 0; envelope->keyVEH = 0; envelope->keyVED = 0; envelope->smpmode = sfgen[sfgen_sampleModes]; } return envelope; } /* emu8k_destroyenvelope: * Destroys an envelope created by emu8k_createenvelope. */ void emu8k_destroyenvelope(envparms_t * env) { _AL_FREE(env); } /* emu8k_lock: * Locks all data and functions which might be called in an interrupt context. */ void emu8k_lock(void) { LOCK_VARIABLE(_emu8k_baseport); LOCK_VARIABLE(_emu8k_numchannels); LOCK_FUNCTION(emu8k_startsound); LOCK_FUNCTION(emu8k_releasesound); LOCK_FUNCTION(emu8k_modulate_atten); LOCK_FUNCTION(emu8k_modulate_ip); LOCK_FUNCTION(emu8k_modulate_pan); LOCK_FUNCTION(emu8k_terminatesound); } allegro-4.4.3.1/src/dos/sndscape.c0000664000175000017500000005735513437077643015637 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Ensoniq Soundscape driver. * * By Andreas Kluge. * * Based on code by Andrew P. Weir. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define ODIE 0 /* ODIE gate array */ #define OPUS 1 /* OPUS gate array */ #define MMIC 2 /* MiMIC gate array */ static int soundscape_hw_ver = -1; /* as reported by detection */ static char *ensoniq_gate_array[] = { "ODIE", "OPUS", "MiMIC" }; #define GA_HOSTCTL_OFF 2 /* host port ctrl/stat reg */ #define GA_ADDR_OFF 4 /* indirect address reg */ #define GA_DATA_OFF 5 /* indirect data reg */ #define GA_CODEC_OFF 8 /* for some boards CoDec is fixed from base */ #define GA_DMAB_REG 3 /* DMA chan B assign reg */ #define GA_INTCFG_REG 4 /* interrupt configuration reg */ #define GA_DMACFG_REG 5 /* DMA configuration reg */ #define GA_CDCFG_REG 6 /* CD-ROM/CoDec config reg */ #define GA_HMCTL_REG 9 /* host master control reg */ #define CD_ADDR_OFF 0 /* indirect address reg */ #define CD_DATA_OFF 1 /* indirect data reg */ #define CD_STATUS_OFF 2 /* status register */ #define OUT_TO_ADDR(n) outportb(soundscape_waveport + CD_ADDR_OFF, n) #define CODEC_MODE_CHANGE_ON() OUT_TO_ADDR(0x40) #define CODEC_MODE_CHANGE_OFF() OUT_TO_ADDR(0x00) #define CD_ADCL_REG 0 /* left DAC input control reg */ #define CD_ADCR_REG 1 /* right DAC input control reg */ #define CD_CDAUXL_REG 2 /* left DAC output control reg */ #define CD_CDAUXR_REG 3 /* right DAC output control reg */ #define CD_DACL_REG 6 /* left DAC output control reg */ #define CD_DACR_REG 7 /* right DAC output control reg */ #define CD_FORMAT_REG 8 /* clock and data format reg */ #define CD_CONFIG_REG 9 /* interface config register */ #define CD_PINCTL_REG 10 /* external pin control reg */ #define CD_UCOUNT_REG 14 /* upper count reg */ #define CD_LCOUNT_REG 15 /* lower count reg */ #define CD_XFORMAT_REG 28 /* extended format reg - 1845 record */ #define CD_XUCOUNT_REG 30 /* extended upper count reg - 1845 record */ #define CD_XLCOUNT_REG 31 /* extended lower count reg - 1845 record */ #define ENABLE_CODEC_IRQ() cd_write(CD_PINCTL_REG, cd_read(CD_PINCTL_REG) | 0x02) #define DISABLE_CODEC_IRQ() cd_write(CD_PINCTL_REG, cd_read(CD_PINCTL_REG) & 0xFD); static int soundscape_enabled = FALSE; static int soundscape_mem_allocated = FALSE; static int soundscape_dma_count = 0; static int soundscape_dma; static int soundscape_freq; static int soundscape_baseport; /* gate Array/MPU-401 port */ static int soundscape_waveport; /* the AD-1848 base port */ static int soundscape_midiirq; /* the MPU-401 IRQ */ static int soundscape_waveirq; /* the PCM IRQ */ static int soundscape_detect(int input); static int soundscape_init(int input, int voices); static void soundscape_exit(int input); static int soundscape_set_mixer_volume(int volume); static int soundscape_buffer_size(void); static int soundscape_int = -1; /* interrupt vector */ static int soundscape_dma_size = -1; /* size of dma transfer */ static volatile int soundscape_semaphore = FALSE; static int soundscape_sel; /* selector for the DMA buffer */ static unsigned long soundscape_buf[2]; /* pointers to the two buffers */ static int soundscape_bufnum = 0; /* the one currently in use */ static void soundscape_lock_mem(void); static char soundscape_desc[256] = EMPTY_STRING; static int cd_cfg_save; /* gate array register save area */ static int dma_cfg_save; /* gate array register save area */ static int int_cfg_save; /* gate array register save area */ static int dac_save_l; /* DAC left volume save */ static int dac_save_r; /* DAC right volume save */ static int cdx_save_l; /* CD/Aux left volume save */ static int cdx_save_r; /* CD/Aux right volume save */ static int adc_save_l; /* ADC left volume save */ static int adc_save_r; /* ADC right volume save */ static int ss_irqs[4] = { 9, 5, 7, 10 }; static int rs_irqs[4] = { 9, 7, 5, 15 }; static int *soundscape_irqset; /* pointer to one of the IRQ sets */ static int soundscape_detected = FALSE; typedef struct /* DMA controller registers ... */ { unsigned char addr; /* address register, lower/upper */ unsigned char count; /* address register, lower/upper */ unsigned char status; /* status register */ unsigned char mask; /* single channel mask register */ unsigned char mode; /* mode register */ unsigned char clrff; /* clear flip-flop register */ unsigned char page; /* fixed page register */ } DMAC_REGS; static DMAC_REGS dmac_regs[4] = /* the DMAC regs for chans 0-3 */ { { 0x00, 0x01, 0x08, 0x0A, 0x0B, 0x0C, 0x87 }, { 0x02, 0x03, 0x08, 0x0A, 0x0B, 0x0C, 0x83 }, { 0x04, 0x05, 0x08, 0x0A, 0x0B, 0x0C, 0x81 }, { 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x82 } }; static DMAC_REGS *dmac_reg_p; /* a pointer to a DMAC reg struct */ DIGI_DRIVER digi_soundscape = { DIGI_SOUNDSCAPE, empty_string, empty_string, "Soundscape", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, soundscape_detect, soundscape_init, soundscape_exit, soundscape_set_mixer_volume, NULL, NULL, NULL, soundscape_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }; /* soundscape_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int soundscape_buffer_size(void) { return soundscape_dma_size/4; /* convert bytes to stereo 16 bit samples */ } /* cd_write: * This function is used to write the indirect addressed registers in the * Ad-1848 or compatible CoDec. It will preserve the special function bits * in the upper-nibble of the indirect address register. */ static void cd_write(int rnum, int value) { OUT_TO_ADDR((inportb(soundscape_waveport + CD_ADDR_OFF) & 0xF0) | rnum); outportb(soundscape_waveport + CD_DATA_OFF, value); } /* cd_read: * This function is used to read the indirect addressed registers in the * AD-1848 or compatible CoDec. It will preserve the special function bits * in the upper-nibble of the indirect address register. */ static int cd_read(int rnum) { OUT_TO_ADDR((inportb(soundscape_waveport + CD_ADDR_OFF) & 0xF0) | rnum); return inportb(soundscape_waveport + CD_DATA_OFF); } /* ga_write: * This function is used to write the indirect addressed registers in the * Ensoniq Soundscape gate array. */ static void ga_write(int rnum, int value) { outportb(soundscape_baseport + GA_ADDR_OFF, rnum); outportb(soundscape_baseport + GA_DATA_OFF, value); } /* ga_read: * This function is used to read the indirect addressed registers in the * Ensoniq Soundscape gate array. */ static int ga_read(int rnum) { outportb(soundscape_baseport + GA_ADDR_OFF, rnum); return inportb(soundscape_baseport + GA_DATA_OFF); } /* set_dac_vol: * This function sets the left and right DAC output level in the CoDec. */ static void set_dac_vol(int lvol, int rvol) { cd_write(CD_DACL_REG, ~(lvol >> 2) & 0x3F); cd_write(CD_DACR_REG, ~(rvol >> 2) & 0x3F); } /* resume_codec: * This function will resume the CoDec auto-restart DMA process. */ static void resume_codec(int direction) { cd_write(CD_CONFIG_REG, direction ? 0x02 : 0x01); } /* set_format: * This function sets the CoDec audio data format for record or playback. */ static int set_format(int srate, int stereo, int size16bit, int direction) { int format = 0; int i; /* first, find the sample rate ... */ switch (srate) { case 5512: format = 0x01; soundscape_dma_size = 512; break; case 6615: format = 0x0F; soundscape_dma_size = 512; break; case 8000: format = 0x00; soundscape_dma_size = 512; break; case 9600: format = 0x0E; soundscape_dma_size = 512; break; case 11025: format = 0x03; soundscape_dma_size = 512; break; /* 11363 */ case 16000: format = 0x02; soundscape_dma_size = 512; break; /* 17046 */ case 18900: format = 0x05; soundscape_dma_size = 1024; break; case 22050: format = 0x07; soundscape_dma_size = 1024; break; /* 22729 */ case 27428: format = 0x04; soundscape_dma_size = 1024; break; case 32000: format = 0x06; soundscape_dma_size = 2048; break; case 33075: format = 0x0D; soundscape_dma_size = 2048; break; case 37800: format = 0x09; soundscape_dma_size = 2048; break; case 44100: format = 0x0B; soundscape_dma_size = 2048; break; /* 44194 */ case 48000: format = 0x0C; soundscape_dma_size = 2048; break; default: return FALSE; } /* set other format bits ... */ if (stereo) format |= 0x10; if (size16bit) { format |= 0x40; soundscape_dma_size *= 2; } soundscape_freq = srate; CODEC_MODE_CHANGE_ON(); /* and write the format register */ cd_write(CD_FORMAT_REG, format); /* if not using ODIE and recording, setup extended format register */ if ((soundscape_hw_ver) != ODIE && (direction)) cd_write(CD_XFORMAT_REG, format & 0x70); /* delay for internal re-sync */ for (i=0; i<200000; i++) inportb(soundscape_baseport + GA_ADDR_OFF); CODEC_MODE_CHANGE_OFF(); return TRUE; } /* stop_codec: * This function will stop the CoDec auto-restart DMA process. */ static void stop_codec(void) { int i; cd_write(CD_CONFIG_REG, cd_read(CD_CONFIG_REG) & 0xFC); /* let the CoDec receive its last DACK(s). The DMAC must not be */ /* masked while the CoDec has DRQs pending. */ for (i=0; i<64; i++) { if (!(inportb(dmac_reg_p->status) & (0x10 << soundscape_dma))) break; } } /* get_ini_config_entry: * This function parses a file (SNDSCAPE.INI) for a left-hand string and, * if found, writes its associated right-hand value to a destination buffer. * This function is case-insensitive. */ static int get_ini_config_entry(char *entry, char *dest, unsigned int dest_size, FILE *fp) { char str[83]; char tokstr[33]; char *p; /* make a local copy of the entry, upper-case it */ _al_sane_strncpy(tokstr, entry, sizeof(tokstr)); strupr(tokstr); /* rewind the file and try to find it... */ rewind(fp); for (;;) { /* get the next string from the file */ fgets(str, 83, fp); if (feof(fp)) { fclose(fp); return -1; } /* properly terminate the string */ for (p=str; *p; p++) { if (uisspace(*p)) { *p = 0; break; } } /* see if it's an 'equate' string; if so, zero the '=' */ p = strchr(str, '='); if (!p) continue; *p = 0; /* upper-case the current string and test it */ strupr(str); if (strcmp(str, tokstr)) continue; /* it's our string - copy the right-hand value to buffer */ _al_sane_strncpy(dest, str+strlen(str)+1, dest_size); break; } return 0; } /* get_init_config: * This function gets all parameters from a file (SNDSCAPE.INI) */ static int get_init_config(void) { FILE *fp = NULL; char str[78]; char *ep; /* get the environment var and build the filename, then open it */ if (!(ep = getenv("SNDSCAPE"))) return FALSE; _al_sane_strncpy(str, ep, sizeof(str)); if (str[strlen(str)-1] == '\\') str[strlen(str)-1] = 0; strncat(str, "\\SNDSCAPE.INI", sizeof(str)-1); if (!(fp = fopen(str, "r"))) return FALSE; /* read all of the necessary config info ... */ if (get_ini_config_entry("Product", str, sizeof(str), fp)) { fclose(fp); return FALSE; } /* if an old product name is read, set the IRQs accordingly */ strupr(str); if (strstr(str, "SOUNDFX") || strstr(str, "MEDIA_FX")) soundscape_irqset = rs_irqs; else soundscape_irqset = ss_irqs; if (get_ini_config_entry("Port", str, sizeof(str), fp)) { fclose(fp); return FALSE; } soundscape_baseport = strtol(str, NULL, 16); if (get_ini_config_entry("WavePort", str, sizeof(str), fp)) { fclose(fp); return FALSE; } soundscape_waveport = strtol(str, NULL, 16); if (get_ini_config_entry("IRQ", str, sizeof(str), fp)) { fclose(fp); return FALSE; } soundscape_midiirq = strtol(str, NULL, 10); if (soundscape_midiirq == 2) soundscape_midiirq = 9; if (get_ini_config_entry("SBIRQ", str, sizeof(str), fp)) { fclose(fp); return FALSE; } soundscape_waveirq = strtol(str, NULL, 10); if (soundscape_waveirq == 2) soundscape_waveirq = 9; if (get_ini_config_entry("DMA", str, sizeof(str), fp)) { fclose(fp); return FALSE; } soundscape_dma = strtol(str, NULL, 10); fclose(fp); return TRUE; } /* detect_soundscape: * This function is used to detect the presence of a Soundscape card in a * system. It will read the hardware config info from the SNDSCAPE.INI file, * the path to which is indicated by the SNDSCAPE environment variable. This * config info will be stored in global variable space for the other driver * functions to reference. Once the config settings have been determined, a * hardware test will be performed to see if the Soundscape card is actually * present. If this function is not explicitly called by the application, it * it will be called by the OpenSoundscape function. */ static int detect_soundscape(void) { int tmp; if (!get_init_config()) return FALSE; /* see if Soundscape is there by reading HW ... */ if ((inportb(soundscape_baseport + GA_HOSTCTL_OFF) & 0x78) != 0x00) return FALSE; if ((inportb(soundscape_baseport + GA_ADDR_OFF) & 0xF0) == 0xF0) return FALSE; outportb(soundscape_baseport + GA_ADDR_OFF, 0xF5); tmp = inportb(soundscape_baseport + GA_ADDR_OFF); if ((tmp & 0xF0) == 0xF0) return FALSE; if ((tmp & 0x0F) != 0x05) return FALSE; /* formulate the chip ID */ if ((tmp & 0x80) != 0x00) soundscape_hw_ver = MMIC; else if ((tmp & 0x70) != 0x00) soundscape_hw_ver = OPUS; else soundscape_hw_ver = ODIE; /* now do a quick check to make sure the CoDec is there too */ if ((inportb(soundscape_waveport) & 0x80) != 0x00) return FALSE; soundscape_detected = TRUE; return TRUE; } /* soundscape_set_mixer_volume: * Sets the Soundscape mixer volume for playing digital samples. */ static int soundscape_set_mixer_volume(int volume) { if (volume >= 0) set_dac_vol(volume, volume); return 0; } /* soundscape_interrupt: * The Soundscape end-of-buffer interrupt handler. */ static int soundscape_interrupt(void) { /* if the CoDec is interrupting ... */ if (inportb(soundscape_waveport + CD_STATUS_OFF) & 0x01) { /* clear the AD-1848 interrupt */ outportb(soundscape_waveport + CD_STATUS_OFF, 0x00); soundscape_dma_count++; if (soundscape_dma_count > 16) { soundscape_bufnum = (_dma_todo(soundscape_dma) > (unsigned)soundscape_dma_size) ? 1 : 0; soundscape_dma_count = 0; } if (!(soundscape_semaphore)) { soundscape_semaphore = TRUE; /* mix some more samples */ ENABLE(); _mix_some_samples(soundscape_buf[soundscape_bufnum], _dos_ds, TRUE); DISABLE(); soundscape_semaphore = FALSE; } soundscape_bufnum = 1 - soundscape_bufnum; } /* acknowledge interrupt */ _eoi(soundscape_waveirq); return 0; } END_OF_STATIC_FUNCTION(soundscape_interrupt); /* soundscape_detect: * This function is used to detect the presence of a Soundscape card. */ static int soundscape_detect(int input) { char tmp[64]; /* input isn't supported yet */ if (input) return FALSE; if (!detect_soundscape()) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Soundscape not found")); return FALSE; } /* figure out the hardware interrupt number */ soundscape_int = _map_irq(soundscape_waveirq); /* get desired frequency from _sound variable */ soundscape_freq = _sound_freq; if (soundscape_freq == -1) soundscape_freq = 48000; /* adjust SB-frequencies for this CoDec */ if (soundscape_freq < 12000) /* 11906 -> 11025 */ soundscape_freq = 11025; else if (soundscape_freq < 18000) /* 16129 -> 16000 */ soundscape_freq = 16000; else if (soundscape_freq < 24000) /* 22727 -> 22050 */ soundscape_freq = 22050; else /* 45454 -> 48000 */ soundscape_freq = 48000; /* set up the card description */ uszprintf(soundscape_desc, sizeof(soundscape_desc), get_config_text("Soundscape %s (%d hz) on port %X, using IRQ %d, DMA channel %d and waveport %X"), uconvert_ascii(ensoniq_gate_array[soundscape_hw_ver], tmp), soundscape_freq, soundscape_baseport, soundscape_waveirq, soundscape_dma, soundscape_waveport); digi_soundscape.desc = soundscape_desc; return TRUE; } /* soundscape_init: * This function opens the Soundscape driver. It will setup the Soundscape * hardware for Native PCM mode. */ static int soundscape_init(int input, int voices) { int windx, mindx, tmp; /* see if we need to detect first */ if (!soundscape_detected) if (!soundscape_detect(0)) return -1; /* set DMA controller register set pointer based on channel */ dmac_reg_p = &dmac_regs[soundscape_dma]; /* in case the CoDec is running, stop it */ stop_codec(); /* clear possible CoDec and SoundBlaster emulation interrupts */ outportb(soundscape_waveport + CD_STATUS_OFF, 0x00); inportb(0x22E); /* input isn't supported yet, don't init twice without exit */ if ((input) || (soundscape_enabled)) return -1; /* set format, always stereo, 16 bit */ set_format(soundscape_freq, 1, 1, 0); if (_dma_allocate_mem(soundscape_dma_size * 2, &soundscape_sel, &soundscape_buf[0]) != 0) return -1; soundscape_mem_allocated = TRUE; soundscape_buf[1] = soundscape_buf[0] + soundscape_dma_size; soundscape_lock_mem(); digi_soundscape.voices = voices; if (_mixer_init(soundscape_dma_size/2, soundscape_freq, TRUE, TRUE, &digi_soundscape.voices) != 0) { soundscape_exit(0); return -1; } _mix_some_samples(soundscape_buf[0], _dos_ds, TRUE); _mix_some_samples(soundscape_buf[1], _dos_ds, TRUE); soundscape_bufnum = 0; _enable_irq(soundscape_waveirq); _install_irq(soundscape_int, soundscape_interrupt); if (soundscape_hw_ver != MMIC) { /* derive the MIDI and Wave IRQ indices (0-3) for reg writes */ for (mindx=0; mindx<4; mindx++) if (soundscape_midiirq == *(soundscape_irqset + mindx)) break; for (windx=0; windx<4; windx++) if (soundscape_waveirq == *(soundscape_irqset + windx)) break; /* setup the CoDec DMA polarity */ ga_write(GA_DMACFG_REG, 0x50); /* give the CoDec control of the DMA and Wave IRQ resources */ cd_cfg_save = ga_read(GA_CDCFG_REG); ga_write(GA_CDCFG_REG, 0x89 | (soundscape_dma << 4) | (windx << 1)); /* pull the Sound Blaster emulation off of those resources */ dma_cfg_save = ga_read(GA_DMAB_REG); ga_write(GA_DMAB_REG, 0x20); int_cfg_save = ga_read(GA_INTCFG_REG); ga_write(GA_INTCFG_REG, 0xF0 | (mindx << 2) | mindx); } /* save all volumes that we might use */ dac_save_l = cd_read(CD_DACL_REG); dac_save_r = cd_read(CD_DACR_REG); cdx_save_l = cd_read(CD_CDAUXL_REG); cdx_save_r = cd_read(CD_CDAUXL_REG); adc_save_l = cd_read(CD_ADCL_REG); adc_save_r = cd_read(CD_ADCR_REG); set_dac_vol(127, 127); /* select the mic/line input to the record mux */ /* if not ODIE, set the mic gain bit too */ cd_write(CD_ADCL_REG, (cd_read(CD_ADCL_REG) & 0x3F) | (soundscape_hw_ver == ODIE ? 0x80 : 0xA0)); cd_write(CD_ADCR_REG, (cd_read(CD_ADCR_REG) & 0x3F) | (soundscape_hw_ver == ODIE ? 0x80 : 0xA0)); /* put the CoDec into mode change state */ CODEC_MODE_CHANGE_ON(); /* setup CoDec mode - single DMA chan, AutoCal on */ cd_write(CD_CONFIG_REG, 0x0c); ENABLE_CODEC_IRQ(); _dma_start(soundscape_dma, soundscape_buf[0], soundscape_dma_size * 2, TRUE, FALSE) ; /* write the CoDec interrupt count - sample frames per half-buffer. */ tmp = soundscape_dma_size / 4 - 1; cd_write(CD_LCOUNT_REG, tmp); cd_write(CD_UCOUNT_REG, tmp >> 8); CODEC_MODE_CHANGE_OFF(); /* start the CoDec for output */ resume_codec(0); rest(100); soundscape_enabled = TRUE; return 0; } /* soundscape_exit: * Soundscape driver cleanup routine, removes ints, stops dma, * frees buffers, etc. */ static void soundscape_exit(int input) { if (soundscape_enabled) { /* in case the CoDec is running, stop it */ stop_codec(); /* stop dma transfer */ _dma_stop(soundscape_dma); /* disable the CoDec interrupt pin */ DISABLE_CODEC_IRQ(); /* restore all volumes ... */ cd_write(CD_DACL_REG, dac_save_l); cd_write(CD_DACR_REG, dac_save_r); cd_write(CD_CDAUXL_REG, cdx_save_l); cd_write(CD_CDAUXL_REG, cdx_save_r); cd_write(CD_ADCL_REG, adc_save_l); cd_write(CD_ADCR_REG, adc_save_r); /* if necessary, restore gate array resource registers */ if (soundscape_hw_ver != MMIC) { ga_write(GA_INTCFG_REG, int_cfg_save); ga_write(GA_DMAB_REG, dma_cfg_save); ga_write(GA_CDCFG_REG, cd_cfg_save); } _remove_irq(soundscape_int); /* restore interrupts */ _restore_irq(soundscape_waveirq); /* reset PIC channels */ } if (soundscape_mem_allocated) __dpmi_free_dos_memory(soundscape_sel); /* free DMA memory buffer */ _mixer_exit(); soundscape_hw_ver = -1; soundscape_detected = FALSE; soundscape_detected = FALSE; soundscape_enabled = FALSE; } /* soundscape_lock_mem: * Locks all the memory touched by parts of the Soundscape code that are * executed in an interrupt context. */ static void soundscape_lock_mem(void) { LOCK_VARIABLE(digi_soundscape); LOCK_VARIABLE(soundscape_freq); LOCK_VARIABLE(soundscape_baseport); LOCK_VARIABLE(soundscape_waveport); LOCK_VARIABLE(soundscape_dma); LOCK_VARIABLE(soundscape_midiirq); LOCK_VARIABLE(soundscape_waveirq); LOCK_VARIABLE(soundscape_int); LOCK_VARIABLE(soundscape_hw_ver); LOCK_VARIABLE(soundscape_dma_size); LOCK_VARIABLE(soundscape_sel); LOCK_VARIABLE(soundscape_buf); LOCK_VARIABLE(soundscape_bufnum); LOCK_VARIABLE(soundscape_dma_count); LOCK_VARIABLE(soundscape_semaphore); LOCK_FUNCTION(soundscape_interrupt); _dma_lock_mem(); } allegro-4.4.3.1/src/dos/adlib.c0000664000175000017500000005243213437077643015101 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Adlib/FM driver for the MIDI player. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* external interface to the Adlib driver */ static int fm_detect(int input); static int fm_init(int input, int voices); static void fm_exit(int input); static int fm_set_mixer_volume(int volume); static int fm_load_patches(AL_CONST char *patches, AL_CONST char *drums); static void fm_key_on(int inst, int note, int bend, int vol, int pan); static void fm_key_off(int voice); static void fm_set_volume(int voice, int vol); static void fm_set_pitch(int voice, int note, int bend); static char adlib_desc[256] = EMPTY_STRING; MIDI_DRIVER midi_opl2 = { MIDI_OPL2, empty_string, empty_string, "Adlib (OPL2)", 9, 0, 9, 9, -1, -1, fm_detect, fm_init, fm_exit, fm_set_mixer_volume, NULL, NULL, fm_load_patches, _dummy_adjust_patches, fm_key_on, fm_key_off, fm_set_volume, fm_set_pitch, _dummy_noop2, _dummy_noop2 }; MIDI_DRIVER midi_2xopl2 = { MIDI_2XOPL2, empty_string, empty_string, "Adlib (dual OPL2)", 18, 0, 18, 18, -1, -1, fm_detect, fm_init, fm_exit, fm_set_mixer_volume, NULL, NULL, fm_load_patches, _dummy_adjust_patches, fm_key_on, fm_key_off, fm_set_volume, fm_set_pitch, _dummy_noop2, _dummy_noop2 }; MIDI_DRIVER midi_opl3 = { MIDI_OPL3, empty_string, empty_string, "Adlib (OPL3)", 18, 0, 18, 18, -1, -1, fm_detect, fm_init, fm_exit, fm_set_mixer_volume, NULL, NULL, fm_load_patches, _dummy_adjust_patches, fm_key_on, fm_key_off, fm_set_volume, fm_set_pitch, _dummy_noop2, _dummy_noop2 }; #define FM_HH 1 #define FM_CY 2 #define FM_TT 4 #define FM_SD 8 #define FM_BD 16 /* include the GM patch set (static data) */ #include "../misc/fm_instr.h" #include "../misc/fm_drum.h" /* where to find the card */ int _fm_port = -1; /* is the OPL in percussion mode? */ static int fm_drum_mode = FALSE; /* delays when writing to OPL registers */ static int fm_delay_1 = 6; static int fm_delay_2 = 35; /* register offsets for each voice */ static int fm_offset[18] = { 0x000, 0x001, 0x002, 0x008, 0x009, 0x00A, 0x010, 0x011, 0x012, 0x100, 0x101, 0x102, 0x108, 0x109, 0x10A, 0x110, 0x111, 0x112 }; /* for converting midi note numbers to FM frequencies */ static int fm_freq[13] = { 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE }; /* logarithmic relationship between midi and FM volumes */ static int fm_vol_table[128] = { 0, 11, 16, 19, 22, 25, 27, 29, 32, 33, 35, 37, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95, 96, 96, 97, 97, 98, 99, 99, 100, 101, 101, 102, 103, 103, 104, 104, 105, 106, 106, 107, 107, 108, 109, 109, 110, 110, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127 }; /* drum channel tables: BD SD TT CY HH */ static int fm_drum_channel[] = { 6, 7, 8, 8, 7 }; static int fm_drum_op1[] = { TRUE, FALSE, TRUE, FALSE, TRUE }; static int fm_drum_op2[] = { TRUE, TRUE, FALSE, TRUE, FALSE }; /* cached information about the state of the drum channels */ static FM_INSTRUMENT *fm_drum_cached_inst1[5]; static FM_INSTRUMENT *fm_drum_cached_inst2[5]; static int fm_drum_cached_vol1[5]; static int fm_drum_cached_vol2[5]; static long fm_drum_cached_time[5]; /* various bits of information about the current state of the FM chip */ static unsigned char fm_drum_mask; static unsigned char fm_key[18]; static unsigned char fm_keyscale[18]; static unsigned char fm_feedback[18]; static int fm_level[18]; static int fm_patch[18]; #define VOICE_OFFSET(x) ((x < 9) ? x : 0x100+x-9) /* fm_write: * Writes a byte to the specified register on the FM chip. */ static void fm_write(int reg, unsigned char data) { int i; int port = (reg & 0x100) ? _fm_port+2 : _fm_port; outportb(port, reg & 0xFF); /* write the register */ for (i=0; i0; i--) fm_write(i, 0); if (midi_card == MIDI_OPL3) { /* if we have an OPL3... */ fm_delay_1 = 1; fm_delay_2 = 2; fm_write(0x105, 1); /* enable OPL3 mode */ for (i=0x1F5; i>0x105; i--) fm_write(i, 0); for (i=0x104; i>0x100; i--) fm_write(i, 0); if (!enable) fm_write(0x105, 0); /* turn OPL3 mode off again */ } else { fm_delay_1 = 6; fm_delay_2 = 35; if (midi_card == MIDI_2XOPL2) { /* if we have a second OPL2... */ for (i=0x1F5; i>0x100; i--) fm_write(i, 0); fm_write(0x101, 0x20); fm_write(0x1BD, 0xC0); } } for (i=0; ivoices; i++) { fm_key[i] = 0; fm_keyscale[i] = 0; fm_feedback[i] = 0; fm_level[i] = 0; fm_patch[i] = -1; fm_write(0x40+fm_offset[i], 63); fm_write(0x43+fm_offset[i], 63); } for (i=0; i<5; i++) { fm_drum_cached_inst1[i] = NULL; fm_drum_cached_inst2[i] = NULL; fm_drum_cached_vol1[i] = -1; fm_drum_cached_vol2[i] = -1; fm_drum_cached_time[i] = 0; } fm_write(0x01, 0x20); /* turn on wave form control */ fm_drum_mode = FALSE; fm_drum_mask = 0xC0; fm_write(0xBD, fm_drum_mask); /* set AM and vibrato to high */ midi_driver->xmin = -1; midi_driver->xmax = -1; } END_OF_STATIC_FUNCTION(fm_reset); /* fm_set_drum_mode: * Switches the OPL synth between normal and percussion modes. */ static void fm_set_drum_mode(int usedrums) { int i; fm_drum_mode = usedrums; fm_drum_mask = usedrums ? 0xE0 : 0xC0; midi_driver->xmin = usedrums ? 6 : -1; midi_driver->xmax = usedrums ? 8 : -1; for (i=6; i<9; i++) if (midi_card == MIDI_OPL3) fm_write(0xC0+VOICE_OFFSET(i), 0x30); else fm_write(0xC0+VOICE_OFFSET(i), 0); fm_write(0xBD, fm_drum_mask); } END_OF_STATIC_FUNCTION(fm_set_drum_mode); /* fm_set_voice: * Sets the sound to be used for the specified voice, from a structure * containing eleven bytes of FM operator data. Note that it doesn't * actually set the volume: it just stores volume data in the fm_level * arrays for fm_set_volume() to use. */ static INLINE void fm_set_voice(int voice, FM_INSTRUMENT *inst) { /* store some info */ fm_keyscale[voice] = inst->level2 & 0xC0; fm_level[voice] = 63 - (inst->level2 & 63); fm_feedback[voice] = inst->feedback; /* write the new data */ fm_write(0x20+fm_offset[voice], inst->characteristic1); fm_write(0x23+fm_offset[voice], inst->characteristic2); fm_write(0x60+fm_offset[voice], inst->attackdecay1); fm_write(0x63+fm_offset[voice], inst->attackdecay2); fm_write(0x80+fm_offset[voice], inst->sustainrelease1); fm_write(0x83+fm_offset[voice], inst->sustainrelease2); fm_write(0xE0+fm_offset[voice], inst->wave1); fm_write(0xE3+fm_offset[voice], inst->wave2); /* don't set operator1 level for additive synthesis sounds */ if (!(inst->feedback & 1)) fm_write(0x40+fm_offset[voice], inst->level1); /* on OPL3, 0xC0 contains pan info, so don't set it until fm_key_on() */ if (midi_card != MIDI_OPL3) fm_write(0xC0+VOICE_OFFSET(voice), inst->feedback); } /* fm_set_drum_op1: * Sets the sound for operator #1 of a drum channel. */ static INLINE void fm_set_drum_op1(int voice, FM_INSTRUMENT *inst) { fm_write(0x20+fm_offset[voice], inst->characteristic1); fm_write(0x60+fm_offset[voice], inst->attackdecay1); fm_write(0x80+fm_offset[voice], inst->sustainrelease1); fm_write(0xE0+fm_offset[voice], inst->wave1); } /* fm_set_drum_op2: * Sets the sound for operator #2 of a drum channel. */ static INLINE void fm_set_drum_op2(int voice, FM_INSTRUMENT *inst) { fm_write(0x23+fm_offset[voice], inst->characteristic2); fm_write(0x63+fm_offset[voice], inst->attackdecay2); fm_write(0x83+fm_offset[voice], inst->sustainrelease2); fm_write(0xE3+fm_offset[voice], inst->wave2); } /* fm_set_drum_vol_op1: * Sets the volume for operator #1 of a drum channel. */ static INLINE void fm_set_drum_vol_op1(int voice, int vol) { vol = 63 * fm_vol_table[vol] / 128; fm_write(0x40+fm_offset[voice], (63-vol)); } /* fm_set_drum_vol_op2: * Sets the volume for operator #2 of a drum channel. */ static INLINE void fm_set_drum_vol_op2(int voice, int vol) { vol = 63 * fm_vol_table[vol] / 128; fm_write(0x43+fm_offset[voice], (63-vol)); } /* fm_set_drum_pitch: * Sets the pitch of a drum channel. */ static INLINE void fm_set_drum_pitch(int voice, FM_INSTRUMENT *drum) { fm_write(0xA0+VOICE_OFFSET(voice), drum->freq); fm_write(0xB0+VOICE_OFFSET(voice), drum->key & 0x1F); } /* fm_trigger_drum: * Triggers a note on a drum channel. */ static INLINE void fm_trigger_drum(int inst, int vol) { FM_INSTRUMENT *drum = fm_drum+inst; int d; if (!fm_drum_mode) fm_set_drum_mode(TRUE); if (drum->type == FM_BD) d = 0; else if (drum->type == FM_SD) d = 1; else if (drum->type == FM_TT) d = 2; else if (drum->type == FM_CY) d = 3; else d = 4; /* don't let drum sounds come too close together */ if (fm_drum_cached_time[d] == _midi_tick) return; fm_drum_cached_time[d] = _midi_tick; fm_drum_mask &= (~drum->type); fm_write(0xBD, fm_drum_mask); vol = vol*3/4; if (fm_drum_op1[d]) { if (fm_drum_cached_inst1[d] != drum) { fm_drum_cached_inst1[d] = drum; fm_set_drum_op1(fm_drum_channel[d], drum); } if (fm_drum_cached_vol1[d] != vol) { fm_drum_cached_vol1[d] = vol; fm_set_drum_vol_op1(fm_drum_channel[d], vol); } } if (fm_drum_op2[d]) { if (fm_drum_cached_inst2[d] != drum) { fm_drum_cached_inst2[d] = drum; fm_set_drum_op2(fm_drum_channel[d], drum); } if (fm_drum_cached_vol2[d] != vol) { fm_drum_cached_vol2[d] = vol; fm_set_drum_vol_op2(fm_drum_channel[d], vol); } } fm_set_drum_pitch(fm_drum_channel[d], drum); fm_drum_mask |= drum->type; fm_write(0xBD, fm_drum_mask); } /* fm_key_on: * Triggers the specified voice. The instrument is specified as a GM * patch number, pitch as a midi note number, and volume from 0-127. * The bend parameter is _not_ expressed as a midi pitch bend value. * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp). * Drum sounds are indicated by passing an instrument number greater than * 128, in which case the sound is GM percussion key #(inst-128). */ static void fm_key_on(int inst, int note, int bend, int vol, int pan) { int voice; if (inst > 127) { /* drum sound? */ inst -= 163; if (inst < 0) inst = 0; else if (inst > 46) inst = 46; fm_trigger_drum(inst, vol); } else { /* regular instrument */ if (midi_card == MIDI_2XOPL2) { /* the SB Pro-1 has fixed pan positions per voice... */ if (pan < 64) voice = _midi_allocate_voice(0, 5); else voice = _midi_allocate_voice(9, midi_driver->voices-1); } else /* on other cards we can use any voices */ voice = _midi_allocate_voice(-1, -1); if (voice < 0) return; /* make sure the voice isn't sounding */ fm_write(0x43+fm_offset[voice], 63); if (fm_feedback[voice] & 1) fm_write(0x40+fm_offset[voice], 63); /* make sure the voice is set up with the right sound */ if (inst != fm_patch[voice]) { fm_set_voice(voice, fm_instrument+inst); fm_patch[voice] = inst; } /* set pan position */ if (midi_card == MIDI_OPL3) { if (pan < 48) pan = 0x10; else if (pan >= 80) pan = 0x20; else pan = 0x30; fm_write(0xC0+VOICE_OFFSET(voice), pan | fm_feedback[voice]); } /* and play the note */ fm_set_pitch(voice, note, bend); fm_set_volume(voice, vol); } } END_OF_STATIC_FUNCTION(fm_key_on); /* fm_key_off: * Hey, guess what this does :-) */ static void fm_key_off(int voice) { fm_write(0xB0+VOICE_OFFSET(voice), fm_key[voice] & 0xDF); } END_OF_STATIC_FUNCTION(fm_key_off); /* fm_set_volume: * Sets the volume of the specified voice (vol range 0-127). */ static void fm_set_volume(int voice, int vol) { vol = fm_level[voice] * fm_vol_table[vol] / 128; fm_write(0x43+fm_offset[voice], (63-vol) | fm_keyscale[voice]); if (fm_feedback[voice] & 1) fm_write(0x40+fm_offset[voice], (63-vol) | fm_keyscale[voice]); } END_OF_STATIC_FUNCTION(fm_set_volume); /* fm_set_pitch: * Sets the pitch of the specified voice. */ static void fm_set_pitch(int voice, int note, int bend) { int oct = 1; int freq; note -= 24; while (note >= 12) { note -= 12; oct++; } freq = fm_freq[note]; if (bend) freq += (fm_freq[note+1] - fm_freq[note]) * bend / 0x1000; fm_key[voice] = (oct<<2) | (freq >> 8); fm_write(0xA0+VOICE_OFFSET(voice), freq & 0xFF); fm_write(0xB0+VOICE_OFFSET(voice), fm_key[voice] | 0x20); } END_OF_STATIC_FUNCTION(fm_set_pitch); /* fm_load_patches: * Called before starting to play a MIDI file, to check if we need to be * in rhythm mode or not. */ static int fm_load_patches(AL_CONST char *patches, AL_CONST char *drums) { int i; int usedrums = FALSE; for (i=6; i<9; i++) { fm_key[i] = 0; fm_keyscale[i] = 0; fm_feedback[i] = 0; fm_level[i] = 0; fm_patch[i] = -1; fm_write(0x40+fm_offset[i], 63); fm_write(0x43+fm_offset[i], 63); } for (i=0; i<5; i++) { fm_drum_cached_inst1[i] = NULL; fm_drum_cached_inst2[i] = NULL; fm_drum_cached_vol1[i] = -1; fm_drum_cached_vol2[i] = -1; fm_drum_cached_time[i] = 0; } for (i=0; i<128; i++) { if (drums[i]) { usedrums = TRUE; break; } } fm_set_drum_mode(usedrums); return 0; } END_OF_STATIC_FUNCTION(fm_load_patches); /* fm_set_mixer_volume: * For SB-Pro cards, sets the mixer volume for FM output. */ static int fm_set_mixer_volume(int volume) { return _sb_set_mixer(-1, volume); } /* fm_is_there: * Checks for the presence of an OPL synth at the current port. */ static int fm_is_there(void) { fm_write(1, 0); /* init test register */ fm_write(4, 0x60); /* reset both timers */ fm_write(4, 0x80); /* enable interrupts */ if (inportb(_fm_port) & 0xE0) return FALSE; fm_write(2, 0xFF); /* write 0xFF to timer 1 */ fm_write(4, 0x21); /* start timer 1 */ rest(100); if ((inportb(_fm_port) & 0xE0) != 0xC0) return FALSE; fm_write(4, 0x60); /* reset both timers */ fm_write(4, 0x80); /* enable interrupts */ return TRUE; } /* fm_detect: * Adlib detection routine. */ static int fm_detect(int input) { static int ports[] = { 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x388, 0 }; char tmp1[64], tmp2[64]; int opl_type; AL_CONST char *s; int i; if (input) return FALSE; _fm_port = get_config_hex(uconvert_ascii("sound", tmp1), uconvert_ascii("fm_port", tmp2), -1); if (_fm_port < 0) { if (midi_card == MIDI_OPL2) { _fm_port = 0x388; if (fm_is_there()) goto found_it; } for (i=0; ports[i]; i++) { /* find the card */ _fm_port = ports[i]; if (fm_is_there()) goto found_it; } } if (!fm_is_there()) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("OPL synth not found")); return FALSE; } found_it: if ((inportb(_fm_port) & 6) == 0) { /* check for OPL3 */ opl_type = MIDI_OPL3; _sb_read_dsp_version(); } else { /* check for second OPL2 */ if (_sb_read_dsp_version() >= 0x300) opl_type = MIDI_2XOPL2; else opl_type = MIDI_OPL2; } if (midi_card == MIDI_OPL3) { if (opl_type != MIDI_OPL3) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("OPL3 synth not found")); return FALSE; } } else if (midi_card == MIDI_2XOPL2) { if (opl_type != MIDI_2XOPL2) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Second OPL2 synth not found")); return FALSE; } } else if (midi_card != MIDI_OPL2) midi_card = opl_type; if (midi_card == MIDI_OPL2) s = get_config_text("OPL2 synth"); else if (midi_card == MIDI_2XOPL2) s = get_config_text("Dual OPL2 synths"); else s = get_config_text("OPL3 synth"); uszprintf(adlib_desc, sizeof(adlib_desc), get_config_text("%s on port %X"), s, _fm_port); midi_driver->desc = adlib_desc; return TRUE; } /* load_ibk: * Reads in a .IBK patch set file, for use by the Adlib driver. */ int load_ibk(AL_CONST char *filename, int drums) { char sig[4]; FM_INSTRUMENT *inst; int c, note, oct, skip, count; PACKFILE *f = pack_fopen(filename, F_READ); if (!f) return -1; pack_fread(sig, 4, f); if (memcmp(sig, "IBK\x1A", 4) != 0) { pack_fclose(f); return -1; } if (drums) { inst = fm_drum; skip = 35; count = 47; } else { inst = fm_instrument; skip = 0; count = 128; } for (c=0; ccharacteristic1 = pack_getc(f); inst->characteristic2 = pack_getc(f); inst->level1 = pack_getc(f); inst->level2 = pack_getc(f); inst->attackdecay1 = pack_getc(f); inst->attackdecay2 = pack_getc(f); inst->sustainrelease1 = pack_getc(f); inst->sustainrelease2 = pack_getc(f); inst->wave1 = pack_getc(f); inst->wave2 = pack_getc(f); inst->feedback = pack_getc(f); if (drums) { switch (pack_getc(f)) { case 6: inst->type = FM_BD; break; case 7: inst->type = FM_HH; break; case 8: inst->type = FM_TT; break; case 9: inst->type = FM_SD; break; case 10: inst->type = FM_CY; break; default: inst->type = 0; break; } pack_getc(f); note = pack_getc(f) - 24; oct = 1; while (note >= 12) { note -= 12; oct++; } inst->freq = fm_freq[note]; inst->key = (oct<<2) | (fm_freq[note] >> 8); } else { inst->type = 0; inst->freq = 0; inst->key = 0; pack_getc(f); pack_getc(f); pack_getc(f); } pack_getc(f); pack_getc(f); inst++; } pack_fclose(f); return 0; } /* fm_init: * Setup the adlib driver. */ static int fm_init(int input, int voices) { char tmp1[128], tmp2[128]; AL_CONST char *s; int i; fm_reset(1); for (i=0; i<2; i++) { s = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii(((i == 0) ? "ibk_file" : "ibk_drum_file"), tmp2), NULL); if ((s) && (ugetc(s))) { if (load_ibk(s, (i > 0)) != 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error reading .IBK file '%s'"), s); return -1; } } } LOCK_VARIABLE(midi_opl2); LOCK_VARIABLE(midi_2xopl2); LOCK_VARIABLE(midi_opl3); LOCK_VARIABLE(fm_instrument); LOCK_VARIABLE(fm_drum); LOCK_VARIABLE(_fm_port); LOCK_VARIABLE(fm_offset); LOCK_VARIABLE(fm_freq); LOCK_VARIABLE(fm_vol_table); LOCK_VARIABLE(fm_drum_channel); LOCK_VARIABLE(fm_drum_op1); LOCK_VARIABLE(fm_drum_op2); LOCK_VARIABLE(fm_drum_cached_inst1); LOCK_VARIABLE(fm_drum_cached_inst2); LOCK_VARIABLE(fm_drum_cached_vol1); LOCK_VARIABLE(fm_drum_cached_vol2); LOCK_VARIABLE(fm_drum_cached_time); LOCK_VARIABLE(fm_drum_mask); LOCK_VARIABLE(fm_drum_mode); LOCK_VARIABLE(fm_key); LOCK_VARIABLE(fm_keyscale); LOCK_VARIABLE(fm_feedback); LOCK_VARIABLE(fm_level); LOCK_VARIABLE(fm_patch); LOCK_VARIABLE(fm_delay_1); LOCK_VARIABLE(fm_delay_2); LOCK_FUNCTION(fm_write); LOCK_FUNCTION(fm_reset); LOCK_FUNCTION(fm_set_drum_mode); LOCK_FUNCTION(fm_key_on); LOCK_FUNCTION(fm_key_off); LOCK_FUNCTION(fm_set_volume); LOCK_FUNCTION(fm_set_pitch); LOCK_FUNCTION(fm_load_patches); return 0; } /* fm_exit: * Cleanup when we are finished. */ static void fm_exit(int input) { fm_reset(0); } allegro-4.4.3.1/src/dos/multijoy.c0000664000175000017500000002421413437077643015677 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Drivers for multisystem joysticks (Atari, Commodore 64 etc.) * with 9-pin connectors. * * By Fabrizio Gennari. * * JOY_TYPE_DB9_LPT[123] * * Supports 2 two-button joysticks. Port 1 is compatible with Linux * joy-db9 driver (multisystem 2-button), and port 2 is compatible * with Atari interface for DirectPad Pro. * * Based on joy-db9 driver for Linux by Vojtech Pavlik * and on Atari interface for DirectPad Pro by Earle F. Philhower, III * * Interface pinout * * * Parallel port Joystick port 1 * 1----------------------------------------------------1 * 14----------------------------------------------------2 * 16----------------------------------------------------3 * 17----------------------------------------------------4 * 11----------------------------------------------------6 * 12----------------------------------------------------7 (button 2) * 18----------------------------------------------------8 * * Joystick port 2 * 2----------------------------------------------------1 * 3----------------------------------------------------2 * 4----------------------------------------------------3 * 5----------------------------------------------------4 * 6----------------------------------------------------6 * 7----------------------------------------------------7 (button 2) * 19----------------------------------------------------8 * * Advantages * * * Simpler to build (no diodes required) * * Autofire will work (if joystick supports it) * * Drawbacks * * * The parallel port must be in SPP (PS/2) mode in order for this * driver to work. In Normal mode, port 2 won't work because data * pins are not inputs. In EPP/ECP PS/2 mode, directions for * port 1 won't work (buttons will) beacuse control pins are not * inputs. * * * The parallel port should not require pull-up resistors * (however, newer ones don't) * * JOY_TYPE_TURBOGRAFX_LPT[123] * * Supports up to 7 joysticks, each one with up to 5 buttons. * * Original interface and driver by Steffen Schwenke * See for details * on how to build the interface * * Advantages * * * Exploits the parallel port to its limits * * Drawbacks * * * Autofire will not work */ #include "allegro.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define LPT1_BASE 0x378 #define LPT2_BASE 0x278 #define LPT3_BASE 0x3bc /* driver functions */ static int db91_init(void); static int db92_init(void); static int db93_init(void); static void db91_exit(void); static void db92_exit(void); static void db93_exit(void); static int db91_poll(void); static int db92_poll(void); static int db93_poll(void); static int tgx1_init(void); static int tgx2_init(void); static int tgx3_init(void); static void tgx1_exit(void); static void tgx2_exit(void); static void tgx3_exit(void); static int tgx1_poll(void); static int tgx2_poll(void); static int tgx3_poll(void); JOYSTICK_DRIVER joystick_db91 = { JOY_TYPE_DB9_LPT1, NULL, NULL, "DB9-LPT1", db91_init, db91_exit, db91_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_db92 = { JOY_TYPE_DB9_LPT2, NULL, NULL, "DB9-LPT2", db92_init, db92_exit, db92_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_db93 = { JOY_TYPE_DB9_LPT3, NULL, NULL, "DB9-LPT3", db93_init, db93_exit, db93_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_tgx1 = { JOY_TYPE_TURBOGRAFX_LPT1, NULL, NULL, "TGX-LPT1", tgx1_init, tgx1_exit, tgx1_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_tgx2 = { JOY_TYPE_TURBOGRAFX_LPT2, NULL, NULL, "TGX-LPT2", tgx2_init, tgx2_exit, tgx2_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_tgx3 = { JOY_TYPE_TURBOGRAFX_LPT3, NULL, NULL, "TGX-LPT3", tgx3_init, tgx3_exit, tgx3_poll, NULL, NULL, NULL, NULL }; #define STATUS_PORT_INVERT 0x80 #define CONTROL_PORT_INVERT 0x0B static int db9_init (int base) { num_joysticks = 2; joy[0].flags = joy[1].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[0].num_sticks = joy[1].num_sticks = 1; joy[0].num_buttons = joy[1].num_buttons = 2; joy[0].stick[0].flags = joy[1].stick[0].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[0].stick[0].num_axis = joy[1].stick[0].num_axis = 2; joy[0].stick[0].axis[0].name = joy[1].stick[0].axis[0].name = get_config_text("Position x"); joy[0].stick[0].axis[1].name = joy[1].stick[0].axis[1].name = get_config_text("Position y"); joy[0].stick[0].name = joy[1].stick[0].name = get_config_text("Position"); joy[0].button[0].name = joy[1].button[0].name = get_config_text("Button 1"); joy[0].button[1].name = joy[1].button[0].name = get_config_text("Button 2"); /* turns the 4 control bits and the 8 data bits into inputs */ outportb(base + 2, 0x2F ^ CONTROL_PORT_INVERT); return 0; } static int db91_init(void) { return db9_init(LPT1_BASE); } static int db92_init(void) { return db9_init(LPT2_BASE); } static int db93_init(void) { return db9_init(LPT3_BASE); } static void db91_exit(void) { outportb(LPT1_BASE + 2 , 0 ^ CONTROL_PORT_INVERT); outportb(LPT1_BASE + 0x402, 0x15); } static void db92_exit(void) { outportb(LPT2_BASE + 2 , 0 ^ CONTROL_PORT_INVERT); outportb(LPT2_BASE + 0x402, 0x15); } static void db93_exit(void) { outportb(LPT3_BASE + 2 , 0 ^ CONTROL_PORT_INVERT); outportb(LPT3_BASE + 0x402, 0x15); } static void db9_poll(int base) { unsigned char data, control, status; data = inportb (base); status = inportb (base + 1) ^ STATUS_PORT_INVERT; control = inportb (base + 2) ^ CONTROL_PORT_INVERT; joy[1].stick[0].axis[0].d1 = (data & 4) ? 0 : 1; joy[1].stick[0].axis[0].d2 = (data & 8) ? 0 : 1; joy[1].stick[0].axis[1].d1 = (data & 1) ? 0 : 1; joy[1].stick[0].axis[1].d2 = (data & 2) ? 0 : 1; joy[1].stick[0].axis[0].pos = ((data & 8) ? 0 : 128) - ((data & 4) ? 0 : 128); joy[1].stick[0].axis[1].pos = ((data & 2) ? 0 : 128) - ((data & 1) ? 0 : 128); joy[1].button[0].b = (data & 16) ? 0 : 1; joy[1].button[1].b = (data & 32) ? 0 : 1; joy[0].stick[0].axis[0].d1 = (control & 4) ? 0 : 1; joy[0].stick[0].axis[0].d2 = (control & 8) ? 0 : 1; joy[0].stick[0].axis[1].d1 = (control & 1) ? 0 : 1; joy[0].stick[0].axis[1].d2 = (control & 2) ? 0 : 1; joy[0].stick[0].axis[0].pos = ((control & 8) ? 0 : 128) - ((control & 4) ? 0 : 128); joy[0].stick[0].axis[1].pos = ((control & 2) ? 0 : 128) - ((control & 1) ? 0 : 128); joy[0].button[0].b = (status & 128) ? 0 : 1; joy[0].button[1].b = (status & 32 ) ? 0 : 1; } static int db91_poll(void) { db9_poll (LPT1_BASE); return 0; } static int db92_poll(void) { db9_poll (LPT2_BASE); return 0; } static int db93_poll(void) { db9_poll (LPT3_BASE); return 0; } static int tgx_init(int base) { int number; num_joysticks=7; for (number=0;number<7;number++){ joy[number].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[number].num_sticks = 1; joy[number].num_buttons = 5; joy[number].stick[0].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[number].stick[0].num_axis = 2; joy[number].stick[0].axis[0].name = get_config_text ("Position x"); joy[number].stick[0].axis[1].name = get_config_text ("Position y"); joy[number].stick[0].name = get_config_text ("Position"); joy[number].button[0].name = get_config_text("Button 1"); joy[number].button[1].name = get_config_text("Button 2"); joy[number].button[2].name = get_config_text("Button 3"); joy[number].button[3].name = get_config_text("Button 4"); joy[number].button[4].name = get_config_text("Button 5"); } /* turns the 4 control bits into inputs */ outportb(base + 2, 0x0F ^ CONTROL_PORT_INVERT); /* If the parallel port is ECP, ensure it is in standard mode */ outportb(base + 0x402, 0x04); return 0; } static int tgx1_init(void) { return tgx_init(LPT1_BASE); } static int tgx2_init(void) { return tgx_init(LPT2_BASE); } static int tgx3_init(void) { return tgx_init(LPT3_BASE); } static void tgx1_exit(void) { outportb (LPT1_BASE + 2, 0 ^ CONTROL_PORT_INVERT); } static void tgx2_exit(void) { outportb (LPT2_BASE + 2, 0 ^ CONTROL_PORT_INVERT); } static void tgx3_exit(void) { outportb (LPT3_BASE + 2, 0 ^ CONTROL_PORT_INVERT); } static void tgx_poll(int base) { unsigned char control, status; int number; for (number=0;number<7;number++){ outportb (base, ~(1 << number)); status = inportb (base + 1) ^ STATUS_PORT_INVERT; control = inportb (base + 2) ^ CONTROL_PORT_INVERT; joy[number].stick[0].axis[0].d1 = (status & 64 ) ? 0 : 1; joy[number].stick[0].axis[0].d2 = (status & 128) ? 0 : 1; joy[number].stick[0].axis[1].d1 = (status & 16 ) ? 0 : 1; joy[number].stick[0].axis[1].d2 = (status & 32 ) ? 0 : 1; joy[number].stick[0].axis[0].pos = ((status & 128) ? 0 : 128) - ((status & 64) ? 0 : 128); joy[number].stick[0].axis[1].pos = ((status & 32 ) ? 0 : 128) - ((status & 16) ? 0 : 128); joy[number].button[0].b = (status & 8) ? 0 : 1; joy[number].button[1].b = (control & 2) ? 0 : 1; joy[number].button[2].b = (control & 4) ? 0 : 1; joy[number].button[3].b = (control & 1) ? 0 : 1; joy[number].button[4].b = (control & 8) ? 0 : 1; } } static int tgx1_poll(void) { tgx_poll (LPT1_BASE); return 0; } static int tgx2_poll(void) { tgx_poll (LPT2_BASE); return 0; } static int tgx3_poll(void) { tgx_poll (LPT3_BASE); return 0; } allegro-4.4.3.1/src/dos/gripjoy.c0000664000175000017500000004505213437077643015511 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the Gravis GrIP. * (Xterminator, GamepadPro, Stinger, ?) * * By Robert J. Ragno, using the Gravis SDK and the other * Allegro drivers as references. * * TODO: * - Test on more devices * - Add support for restricting joystick to 4-directions * - Look into dropping the grip.gll support (with asm code) * - Look into providing direction names, not just axis names * - (analog detection) */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #include "grip.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* If this is true, throttles will be 'packed' to fit in the * smallest number of pseudo-sticks possible. */ #define PACK_THROTTLES 1 /* enable support for each type of control */ #define ENABLE_AXIS 1 #define ENABLE_ANALOG 1 #define ENABLE_POV 1 #define ENABLE_THROTTLE 1 /* driver functions */ static int grip_init(void); static void grip_exit(void); static int grip_poll(void); static int grip_link(void); static int grip_unlink(void); static int read_grip(int joy_num); /* hack to simplify axis names... */ #define SIMPLIFY_AXIS(foo) \ if (((foo[0] == 'X') || (foo[0] == 'Y')) && (foo[1] == '_')) \ foo[1] = '\0'; /* internal variables for extra joystick data */ static GRIP_SLOT slot_index[MAX_JOYSTICKS]; static GRIP_VALUE max_value[MAX_JOYSTICKS][(int)GRIP_CLASS_MAX+1]; static int throttle_button_start[MAX_JOYSTICKS]; static GRIP_CLASS stick_class[MAX_JOYSTICKS][MAX_JOYSTICK_STICKS]; static int fourway[MAX_JOYSTICKS][MAX_JOYSTICK_STICKS]; /* the normal GrIP driver */ JOYSTICK_DRIVER joystick_grip = { JOY_TYPE_GRIP, empty_string, empty_string, "GrIP", grip_init, grip_exit, grip_poll, NULL, NULL, /* no saving/loading data */ NULL, NULL /* no calibrating */ }; /* only allows 4-way movement on digital pad */ JOYSTICK_DRIVER joystick_grip4 = { JOY_TYPE_GRIP4, empty_string, empty_string, "GrIP 4-way", grip_init, grip_exit, grip_poll, NULL, NULL, /* no saving/loading data */ NULL, NULL /* no calibrating */ }; /* read_grip; * Reads the GrIP controller pointed to by joy_num (0 or 1) and * sets its state; no useful return value currently. */ static int read_grip(int j) { GRIP_BITFIELD buttons_packed; GRIP_SLOT slot_num; GRIP_CLASS last_class; GRIP_INDEX axis; int a, b, s, state; slot_num = slot_index[j]; /* sticks must be grouped by type for axis grouping to work! */ axis = 0; last_class = stick_class[j][0]; for (s=0; s 64; axis++; } } /* handle 4-way restriction */ if (_joy_type == JOY_TYPE_GRIP4) { for (s=0; s= MAX_JOYSTICKS) break; } } if (num_joysticks == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("No GrIP devices available")); grip_exit(); return -1; } /* loop over each joystick (active GrIP slot) */ for (i=0; i MAX_JOYSTICK_STICKS) { joy[i].num_sticks = MAX_JOYSTICK_STICKS; last_axis = MAX_JOYSTICK_STICKS*2; } max_value[i][GRIP_CLASS_AXIS] = _GrGetMaxValue(slot_index[i], GRIP_CLASS_AXIS); /* loop over each actual stick on the device (often just 1) * We arbitrarily split the axes up into pairs... GrIP gives no * info on how this can be identified */ for (stick=0; stick < joy[i].num_sticks; stick++) { stick_class[i][stick] = GRIP_CLASS_AXIS; /* name stick... :( */ _al_sane_strncpy(tmpstr, "Stick", sizeof(tmpstr)); if (joy[i].num_sticks > 1) { tmpstr[strlen(tmpstr)+2] = '\0'; tmpstr[strlen(tmpstr)+1] = '1'+stick; tmpstr[strlen(tmpstr)] = ' '; } joy[i].stick[stick].name = get_config_text(tmpstr); joy[i].stick[stick].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; /* name axes */ joy[i].stick[stick].num_axis = ((stick*2) == last_axis) ? 1 : 2; _GrGetControlName(slot_index[i], GRIP_CLASS_AXIS, stick*2, tmpstr); if (tmpstr[0] == '\0') _al_sane_strncpy(tmpstr, "X", sizeof(tmpstr)); SIMPLIFY_AXIS(tmpstr); joy[i].stick[stick].axis[0].name = get_config_text(tmpstr); joy[i].stick[stick].axis[0].pos = 0; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 0; if (joy[i].stick[stick].num_axis == 2) { _GrGetControlName(slot_index[i], GRIP_CLASS_AXIS, stick*2 + 1, tmpstr); if (tmpstr[0] == '\0') _al_sane_strncpy(tmpstr, "Y", sizeof(tmpstr)); SIMPLIFY_AXIS(tmpstr); joy[i].stick[stick].axis[1].name = get_config_text(tmpstr); joy[i].stick[stick].axis[1].pos = 0; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 0; } } } /* check for Analog pads (as in the Xterminator) */ if ((ENABLE_ANALOG) && (class_map & (1 << GRIP_CLASS_ANALOG)) && (_GrGetMaxIndex(slot_index[i], GRIP_CLASS_ANALOG) > 0)) { int num_pads = 0; int stick = 0; int analog_start; max_value[i][GRIP_CLASS_ANALOG] = _GrGetMaxValue(slot_index[i], GRIP_CLASS_ANALOG); num_pads = (_GrGetMaxIndex(slot_index[i], GRIP_CLASS_ANALOG) + 1) / 2; analog_start = joy[i].num_sticks; joy[i].num_sticks += num_pads; if (joy[i].num_sticks > MAX_JOYSTICK_STICKS) { num_pads -= joy[i].num_sticks - MAX_JOYSTICK_STICKS; joy[i].num_sticks = MAX_JOYSTICK_STICKS; } /* loop over each pair of analog pads on the device (often just 1) */ for (stick=analog_start; stick < analog_start+num_pads; stick++) { stick_class[i][stick] = GRIP_CLASS_ANALOG; /* name pad... :( */ _al_sane_strncpy(tmpstr, "Analog", sizeof(tmpstr)); if (num_pads > 1) { tmpstr[strlen(tmpstr)+2] = '\0'; tmpstr[strlen(tmpstr)+1] = '1'+stick-analog_start; tmpstr[strlen(tmpstr)] = ' '; } joy[i].stick[stick].name = get_config_text(tmpstr); joy[i].stick[stick].flags = JOYFLAG_ANALOG | JOYFLAG_SIGNED; /* name axes */ joy[i].stick[stick].num_axis = 2; _GrGetControlName(slot_index[i], GRIP_CLASS_ANALOG, (stick-analog_start)*2, tmpstr); if (tmpstr[0] == '\0') _al_sane_strncpy(tmpstr, "X", sizeof(tmpstr)); SIMPLIFY_AXIS(tmpstr); joy[i].stick[stick].axis[0].name = get_config_text(tmpstr); joy[i].stick[stick].axis[0].pos = 0; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 0; _GrGetControlName(slot_index[i], GRIP_CLASS_ANALOG, (stick-analog_start)*2 + 1, tmpstr); if (tmpstr[0] == '\0') _al_sane_strncpy(tmpstr, "Y", sizeof(tmpstr)); SIMPLIFY_AXIS(tmpstr); joy[i].stick[stick].axis[1].name = get_config_text(tmpstr); joy[i].stick[stick].axis[1].pos = 0; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 0; } } /* check for a Point-of-View Hat... */ if ((ENABLE_POV) && (class_map & (1 << GRIP_CLASS_POV_HAT)) && (_GrGetMaxIndex(slot_index[i], GRIP_CLASS_POV_HAT) > 0)) { int num_hats = 0; int stick = 0; int pov_start; max_value[i][GRIP_CLASS_POV_HAT] = _GrGetMaxValue(slot_index[i], GRIP_CLASS_POV_HAT); num_hats = (_GrGetMaxIndex(slot_index[i], GRIP_CLASS_POV_HAT) + 1) / 2; pov_start = joy[i].num_sticks; joy[i].num_sticks += num_hats; if (joy[i].num_sticks > MAX_JOYSTICK_STICKS) { num_hats -= joy[i].num_sticks - MAX_JOYSTICK_STICKS; joy[i].num_sticks = MAX_JOYSTICK_STICKS; } /* loop over each pov hat on the device (often just 1) */ for (stick=pov_start; stick < pov_start+num_hats; stick++) { stick_class[i][stick] = GRIP_CLASS_POV_HAT; /* name hat... :( */ _al_sane_strncpy(tmpstr, "Hat", sizeof(tmpstr)); if (num_hats > 1) { tmpstr[strlen(tmpstr)+2] = '\0'; tmpstr[strlen(tmpstr)+1] = '1'+stick-pov_start; tmpstr[strlen(tmpstr)] = ' '; } joy[i].stick[stick].name = get_config_text(tmpstr); joy[i].stick[stick].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; /* name axes */ joy[i].stick[stick].num_axis = 2; _GrGetControlName(slot_index[i], GRIP_CLASS_POV_HAT, (stick-pov_start)*2, tmpstr); if (tmpstr[0] == '\0') _al_sane_strncpy(tmpstr, "X", sizeof(tmpstr)); SIMPLIFY_AXIS(tmpstr); joy[i].stick[stick].axis[0].name = get_config_text(tmpstr); joy[i].stick[stick].axis[0].pos = 0; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 0; _GrGetControlName(slot_index[i], GRIP_CLASS_POV_HAT, (stick-pov_start)*2 + 1, tmpstr); if (tmpstr[0] == '\0') _al_sane_strncpy(tmpstr, "Y", sizeof(tmpstr)); SIMPLIFY_AXIS(tmpstr); joy[i].stick[stick].axis[1].name = get_config_text(tmpstr); joy[i].stick[stick].axis[1].pos = 0; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 0; } } /* check for throttles */ if ((ENABLE_THROTTLE) && (class_map & (1 << GRIP_CLASS_THROTTLE))) { int num_throt = 0; int num_throt_sticks = 0; int num_throt_extra_axes = 0; int stick = 0; int throttle_start; int throttle_count; max_value[i][GRIP_CLASS_THROTTLE] = _GrGetMaxValue(slot_index[i], GRIP_CLASS_THROTTLE); num_throt = _GrGetMaxIndex(slot_index[i], GRIP_CLASS_THROTTLE) + 1; if (PACK_THROTTLES) { num_throt_sticks = num_throt / MAX_JOYSTICK_AXIS; num_throt_extra_axes = num_throt % MAX_JOYSTICK_AXIS; } else { num_throt_sticks = num_throt; num_throt_extra_axes = 0; } throttle_start = joy[i].num_sticks; joy[i].num_sticks += num_throt_sticks; if (joy[i].num_sticks > MAX_JOYSTICK_STICKS) { num_throt_sticks -= joy[i].num_sticks - MAX_JOYSTICK_STICKS; joy[i].num_sticks = MAX_JOYSTICK_STICKS; } /* account for leftover axes, if packing: */ if ((num_throt_extra_axes) && (joy[i].num_sticks < MAX_JOYSTICK_STICKS)) { joy[i].num_sticks += 1; num_throt_sticks++; } else num_throt_extra_axes = 0; /* loop over each throttle on the device */ throttle_count = 0; for (stick=throttle_start; stick < throttle_start+num_throt_sticks; stick++) { int last_axis, a; if (PACK_THROTTLES) { if ((stick == throttle_start+num_throt_sticks-1) && (num_throt_extra_axes)) last_axis = num_throt_extra_axes; else last_axis = MAX_JOYSTICK_AXIS; } else last_axis = 1; stick_class[i][stick] = GRIP_CLASS_THROTTLE; joy[i].stick[stick].flags = JOYFLAG_ANALOG | JOYFLAG_SIGNED; joy[i].stick[stick].num_axis = last_axis; /* name throttle... */ _al_sane_strncpy(tmpstr, "Throttle", sizeof(tmpstr)); if (num_throt_sticks > 1) { tmpstr[strlen(tmpstr)+2] = '\0'; tmpstr[strlen(tmpstr)+1] = '1'+stick-throttle_start; tmpstr[strlen(tmpstr)] = ' '; } joy[i].stick[stick].name = get_config_text(tmpstr); for (a=0; a MAX_JOYSTICK_BUTTONS) joy[i].num_buttons = MAX_JOYSTICK_BUTTONS; for (b=0; b 32*1024)) return -1; /* open the loadable library file size */ if ((f = pack_fopen(name, F_READ)) == NULL) return -1; if ((image = _AL_MALLOC(size)) == NULL) { pack_fclose(f); return -1; } pack_fread(image, size, f); pack_fclose(f); /* link to the library (and free up the temporary memory) */ if (!_GrLink(image, size)) { _AL_FREE(image); return -1; } _AL_FREE(image); already_linked = 1; return 0; } static int grip_unlink(void) { already_linked = 0; if (!_GrUnlink()) return -1; return 0; } allegro-4.4.3.1/src/dos/vesas.s0000664000175000017500000001474313437077643015172 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * VESA bank switching code. These routines will be called with * a line number in %eax and a pointer to the bitmap in %edx. The * bank switcher should select the appropriate bank for the line, * and replace %eax with a pointer to the start of the line. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" .text /* Template for bank switchers. Produces a framework that checks which * bank is currently selected and only executes the provided code if it * needs to change bank. */ #define BANK_SWITCHER(name, cache, code) \ pushl %eax ; \ ; \ addl BMP_YOFFSET(%edx), %eax /* add line offset */ ; \ ; \ shll $2, %eax ; \ addl GLOBL(_gfx_bank), %eax /* lookup which bank */ ; \ movl (%eax), %eax ; \ cmpl cache, %eax /* need to change? */ ; \ je name##_done ; \ ; \ movl %eax, cache /* store the new bank */ ; \ code /* and change it */ ; \ ; \ _align_ ; \ name##_done: ; \ popl %eax ; \ movl BMP_LINE(%edx, %eax, 4), %eax /* load line address */ /* Uses VESA function 05h (real mode interrupt) to select the bank in %eax. */ #define SET_VESA_BANK_RM(window) \ pushal /* store registers */ ; \ pushw %es ; \ ; \ movw GLOBL(__djgpp_ds_alias), %bx ; \ movw %bx, %es ; \ ; \ movl $0x10, %ebx /* call int 0x10 */ ; \ movl $0, %ecx /* no stack required */ ; \ movl $GLOBL(_dpmi_reg), %edi /* register structure */ ; \ ; \ movw $0x4F05, DPMI_AX(%edi) /* VESA function 05h */ ; \ movw $window, DPMI_BX(%edi) /* which window? */ ; \ movw %ax, DPMI_DX(%edi) /* which bank? */ ; \ movw $0, DPMI_SP(%edi) /* zero stack */ ; \ movw $0, DPMI_SS(%edi) ; \ movw $0, DPMI_FLAGS(%edi) /* and zero flags */ ; \ ; \ movl $0x0300, %eax /* simulate RM interrupt */ ; \ int $0x31 ; \ ; \ popw %es /* restore registers */ ; \ popal /* VESA 1.x window 1 bank switcher */ FUNC(_vesa_window_1) BANK_SWITCHER(vesa_window_1, GLOBL(_last_bank_1), SET_VESA_BANK_RM(0)) ret FUNC(_vesa_window_1_end) ret /* VESA 1.x window 2 bank switcher */ FUNC(_vesa_window_2) BANK_SWITCHER(vesa_window_2, GLOBL(_last_bank_2), SET_VESA_BANK_RM(1)) addl GLOBL(_window_2_offset), %eax ret FUNC(_vesa_window_2_end) ret /* Uses the VESA 2.0 protected mode interface to select the bank in %eax. */ #define SET_VESA_BANK_PM(window) \ pushal /* store registers */ ; \ ; \ movw $window, %bx /* which window? */ ; \ movw %ax, %dx /* which bank? */ ; \ movl GLOBL(_pm_vesa_switcher), %eax ; \ call *%eax /* do it! */ ; \ ; \ popal /* restore registers */ /* VESA 2.0 window 1 bank switcher */ FUNC(_vesa_pm_window_1) BANK_SWITCHER(vesa_pm_window_1, GLOBL(_last_bank_1), SET_VESA_BANK_PM(0)) ret FUNC(_vesa_pm_window_1_end) ret /* VESA 2.0 window 2 bank switcher */ FUNC(_vesa_pm_window_2) BANK_SWITCHER(vesa_pm_window_2, GLOBL(_last_bank_2), SET_VESA_BANK_PM(1)) addl GLOBL(_window_2_offset), %eax ret FUNC(_vesa_pm_window_2_end) ret /* Uses the VESA 2.0 protected mode interface to select the bank in %eax, * passing a selector for memory mapped io in %es. */ #define SET_VESA_BANK_PM_ES(window) \ pushal /* store registers */ ; \ pushw %es ; \ ; \ movw $window, %bx /* which window? */ ; \ movw %ax, %dx /* which bank? */ ; \ movw GLOBL(_mmio_segment), %ax /* load selector into %es */ ; \ movw %ax, %es ; \ movl GLOBL(_pm_vesa_switcher), %eax ; \ call *%eax /* do it! */ ; \ ; \ popw %es /* restore registers */ ; \ popal /* VESA 2.0 MMIO mode window 2 bank switcher */ FUNC(_vesa_pm_es_window_1) BANK_SWITCHER(vesa_pm_es_window_1, GLOBL(_last_bank_1), SET_VESA_BANK_PM_ES(0)) ret FUNC(_vesa_pm_es_window_1_end) ret /* VESA 2.0 MMIO mode window 2 bank switcher */ FUNC(_vesa_pm_es_window_2) BANK_SWITCHER(vesa_pm_es_window_2, GLOBL(_last_bank_2), SET_VESA_BANK_PM_ES(1)) addl GLOBL(_window_2_offset), %eax ret FUNC(_vesa_pm_es_window_2_end) ret allegro-4.4.3.1/src/dos/dfile.c0000664000175000017500000001710513437077643015107 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper routines to make file.c work on DOS platforms. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #include #include #endif #include "allegro.h" #include "allegro/internal/aintern.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* _al_file_isok: * Helper function to check if it is safe to access a file on a floppy * drive. */ int _al_file_isok(AL_CONST char *filename) { char ch = utolower(ugetc(filename)); __dpmi_regs r; if (((ch == 'a') || (ch == 'b')) && (ugetat(filename, 1) == ':')) { r.x.ax = 0x440E; r.x.bx = 1; __dpmi_int(0x21, &r); if ((r.h.al != 0) && (r.h.al != (ch - 'a' + 1))) { *allegro_errno = EACCES; return FALSE; } } return TRUE; } /* _al_file_size_ex: * Measures the size of the specified file. */ uint64_t _al_file_size_ex(AL_CONST char *filename) { struct stat s; char tmp[1024]; if (stat(uconvert_toascii(filename, tmp), &s) != 0) { *allegro_errno = errno; return 0; } return s.st_size; } /* _al_file_time: * Returns the timestamp of the specified file. */ time_t _al_file_time(AL_CONST char *filename) { struct stat s; char tmp[1024]; if (stat(uconvert_toascii(filename, tmp), &s) != 0) { *allegro_errno = errno; return 0; } return s.st_mtime; } /* _al_detect_filename_encoding: * * Platform specific function to detect the filename encoding. This is called * after setting a system driver, and even if this driver is SYSTEM_NONE. */ void _al_detect_filename_encoding(void) { set_filename_encoding(U_ASCII); } /* structure for use by the directory scanning routines */ struct FF_DATA { struct ffblk data; int attrib; }; /* fill_ffblk: * Helper function to fill in an al_ffblk structure. */ static void fill_ffblk(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; struct tm t; info->attrib = ff_data->data.ff_attrib; memset(&t, 0, sizeof(struct tm)); t.tm_sec = (ff_data->data.ff_ftime & 0x1F) * 2; t.tm_min = (ff_data->data.ff_ftime >> 5) & 0x3F; t.tm_hour = (ff_data->data.ff_ftime >> 11) & 0x1F; t.tm_mday = (ff_data->data.ff_fdate & 0x1F); t.tm_mon = ((ff_data->data.ff_fdate >> 5) & 0x0F) - 1; t.tm_year = (ff_data->data.ff_fdate >> 9) + 80; t.tm_isdst = -1; info->time = mktime(&t); info->size = ff_data->data.ff_fsize; do_uconvert(ff_data->data.ff_name, U_ASCII, info->name, U_CURRENT, sizeof(info->name)); } /* al_findfirst: * Initiates a directory search. */ int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) { struct FF_DATA *ff_data; char tmp[1024]; int ret; /* allocate ff_data structure */ ff_data = _AL_MALLOC(sizeof(struct FF_DATA)); if (!ff_data) { *allegro_errno = ENOMEM; return NULL; } /* attach it to the info structure */ info->ff_data = (void *) ff_data; /* Win2k appears to set bit7 for files which otherwise * would not have any attribute flag set. */ ff_data->attrib = attrib | 0x80; /* start the search */ errno = *allegro_errno = 0; /* We pass all the flags to findfirst() in order to work around the DOS limitations * for FA_RDONLY and FA_ARCH which are normally ignored. * * The return value of findfirst() and findnext() is not meaningful because the * functions return an errno code under DJGPP (ENOENT or ENMFILE) whereas they * return a DOS error code under Watcom (02h, 03h or 12h). * However the functions of both compilers set errno accordingly. */ ret = findfirst(uconvert_toascii(pattern, tmp), &ff_data->data, 0xFF); if (ret != 0) { #ifdef ALLEGRO_DJGPP /* the DJGPP libc may set errno to ENMFILE, we convert it to ENOENT */ *allegro_errno = (errno == ENMFILE ? ENOENT : errno); #else *allegro_errno = errno; #endif _AL_FREE(ff_data); info->ff_data = NULL; return -1; } if (ff_data->data.ff_attrib & ~ff_data->attrib) { if (al_findnext(info) != 0) { al_findclose(info); return -1; } else return 0; } fill_ffblk(info); return 0; } /* al_findnext: * Retrieves the next file from a directory search. */ int al_findnext(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; do { if (findnext(&ff_data->data) != 0) { #ifdef ALLEGRO_DJGPP /* the DJGPP libc may set errno to ENMFILE, we convert it to ENOENT */ *allegro_errno = (errno == ENMFILE ? ENOENT : errno); #else *allegro_errno = errno; #endif return -1; } } while (ff_data->data.ff_attrib & ~ff_data->attrib); fill_ffblk(info); return 0; } /* al_findclose: * Cleans up after a directory search. */ void al_findclose(struct al_ffblk *info) { struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data; if (ff_data) { _AL_FREE(ff_data); info->ff_data = NULL; } } /* _al_drive_exists: * Checks whether the specified drive is valid. */ int _al_drive_exists(int drive) { unsigned int old_drive; int ret = FALSE; __dpmi_regs r; /* get actual drive */ r.h.ah = 0x19; __dpmi_int(0x21, &r); old_drive = r.h.al; /* see if the drive is assigned as a valid drive */ r.h.ah = 0x0E; r.h.dl = drive; __dpmi_int(0x21, &r); r.h.ah = 0x19; __dpmi_int(0x21, &r); if (r.h.al == drive) { /* ok, now check if it is a logical drive */ r.x.ax = 0x440E; r.h.bl = drive+1; __dpmi_int(0x21, &r); if ((r.x.flags & 1) || /* call failed */ (r.h.al == 0) || /* has no logical drives */ (r.h.al == (drive+1))) /* not a logical drive */ ret = TRUE; } /* now we set the old drive */ r.h.ah = 0x0E; r.h.dl = old_drive; __dpmi_int(0x21, &r); return ret; } /* _al_getdrive: * Returns the current drive number (0=A, 1=B, etc). */ int _al_getdrive(void) { unsigned int d; _dos_getdrive(&d); return d-1; } /* _al_getdcwd: * Returns the current directory on the specified drive. */ void _al_getdcwd(int drive, char *buf, int size) { unsigned int old_drive, tmp_drive; char filename[32], tmp[1024]; int pos; pos = usetc(filename, drive+'a'); pos += usetc(filename+pos, ':'); pos += usetc(filename+pos, '\\'); usetc(filename+pos, 0); if (!_al_file_isok(filename)) { *buf = 0; return; } _dos_getdrive(&old_drive); _dos_setdrive(drive+1, &tmp_drive); _dos_getdrive(&tmp_drive); if (tmp_drive == (unsigned int)drive+1) { if (getcwd(tmp, sizeof(tmp))) do_uconvert(tmp, U_ASCII, buf, U_CURRENT, size); else usetc(buf, 0); } else usetc(buf, 0); _dos_setdrive(old_drive, &tmp_drive); } /* _al_ffblk_get_size: * Returns the size out of an _al_ffblk structure. */ uint64_t al_ffblk_get_size(struct al_ffblk *info) { struct FF_DATA *ff_data; ASSERT(info); ff_data = (struct FF_DATA *) info->ff_data; return ff_data->data.ff_fsize; } allegro-4.4.3.1/src/dos/snespad.c0000664000175000017500000001247713437077643015470 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the SNES controller. * * By Kerry High, based on sample code by Earle F. Philhower, III. * * Mucked about with until it works better by Paul Hampson. * * Lower CPU usage by Paul Hampson, based on the Linux implementation * by Vojtech Pavlik. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define LPT1_BASE 0x378 #define LPT2_BASE 0x278 #define LPT3_BASE 0x3bc #define SNES_POWER 248 #define SNES_CLOCK 1 #define SNES_LATCH 2 #define SNES_BUTTONS 12 /* actually 16, but the last 4 aren't * connected in a real SNESpad */ /* driver functions */ static int sp_init(void); static void sp_exit(void); static int sp_poll(int); static int sp1_poll(void); static int sp2_poll(void); static int sp3_poll(void); JOYSTICK_DRIVER joystick_sp1 = { JOY_TYPE_SNESPAD_LPT1, empty_string, empty_string, "SNESpad-LPT1", sp_init, sp_exit, sp1_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_sp2 = { JOY_TYPE_SNESPAD_LPT2, empty_string, empty_string, "SNESpad-LPT2", sp_init, sp_exit, sp2_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_sp3 = { JOY_TYPE_SNESPAD_LPT3, empty_string, empty_string, "SNESpad-LPT3", sp_init, sp_exit, sp3_poll, NULL, NULL, NULL, NULL }; /* sp_init: * Initialises the driver. */ static int sp_init(void) { int i; /* can't autodetect this... */ num_joysticks = 5; for (i=0; i 22094) tc = 256 - 795500/rate; else tc = 128 - 397700/rate; rate = (rate*9)/20; divider = 256 - 7160000/(rate*82); ess_write_dsp(0xA1); ess_write_dsp(tc); ess_write_dsp(0xA2); ess_write_dsp(divider); } /* ess_read_dsp_version: * Reads the version number of the AudioDrive DSP chip, returning -1 on error. */ static int ess_read_dsp_version(void) { if (ess_hw_ver > 0) return ess_hw_ver; if (_sound_port <= 0) _sound_port = 0x220; if (_sb_reset_dsp(1) != 0) { ess_hw_ver = -1; } else { int major=0, minor=0; int i; ess_write_dsp(0xE7); for (i=0; i<240; i++) { if (is_dsp_ready_for_read()) { if (!major) major = ess_read_dsp(); else minor = ess_read_dsp(); } } if ((major==0x68) && ((minor&0xF0)==0x80)) { if ((minor&0x0F) >= 0xB) ess_hw_ver = 0x1868; else if ((minor&0x0F) >= 8) ess_hw_ver = 0x1688; else ess_hw_ver = 0x0688; return ess_hw_ver; } } return -1; } /* ess_play_buffer: * Starts a dma transfer of size bytes. */ static void ess_play_buffer(int size) { int value; ess_write_dsp(0xA4); ess_write_dsp((-size)&0xFF); ess_write_dsp(0xA5); ess_write_dsp((-size)>>8); ess_write_dsp(0xC0); ess_write_dsp(0xB8); value = ess_read_dsp() | 0x05; ess_write_dsp(0xB8); ess_write_dsp(value); } END_OF_STATIC_FUNCTION(ess_play_buffer); /* ess_interrupt: * The AudioDrive end-of-buffer interrupt handler. */ static int ess_interrupt(void) { int value; ess_dma_count++; if (ess_dma_count > 16) { ess_bufnum = (_dma_todo(_sound_dma) > (unsigned)ess_dma_size) ? 1 : 0; ess_dma_count = 0; } if (!ess_semaphore) { ess_semaphore = TRUE; ENABLE(); /* mix some more samples */ _mix_some_samples(ess_buf[ess_bufnum], _dos_ds, FALSE); DISABLE(); ess_semaphore = FALSE; } ess_bufnum = 1 - ess_bufnum; /* acknowlege AudioDrive */ ess_write_dsp(0xA4); ess_write_dsp((-ess_dma_size)&0xFF); ess_write_dsp(0xA5); ess_write_dsp((-ess_dma_size)>>8); ess_write_dsp(0xC0); ess_write_dsp(0xB8); value = ess_read_dsp() | 0x05; ess_write_dsp(0xB8); ess_write_dsp(value); /* acknowledge interrupt */ _eoi(_sound_irq); return 0; } END_OF_STATIC_FUNCTION(ess_interrupt); /* ess_detect: * AudioDrive detection routine. Uses the BLASTER environment variable, * or 'sensible' gueses if that doesn't exist. */ static int ess_detect(int input) { int orig_port = _sound_port; int orig_irq = _sound_irq; int orig_dma = _sound_dma; char *blaster = getenv("BLASTER"); if (input) return FALSE; /* parse BLASTER env */ if (blaster) { while (*blaster) { while ((*blaster == ' ') || (*blaster == '\t')) blaster++; if (*blaster) { switch (*blaster) { case 'a': case 'A': if (_sound_port < 0) _sound_port = strtol(blaster+1, NULL, 16); break; case 'i': case 'I': if (_sound_irq < 0) _sound_irq = strtol(blaster+1, NULL, 10); break; case 'd': case 'D': if (_sound_dma < 0) _sound_dma = strtol(blaster+1, NULL, 10); break; } while ((*blaster) && (*blaster != ' ') && (*blaster != '\t')) blaster++; } } } if (_sound_port < 0) _sound_port = 0x220; if (_sound_irq < 0) _sound_irq = 7; if (_sound_dma < 0) _sound_dma = 1; /* make sure we got a good port addres */ if (_sb_reset_dsp(1) != 0) { static int bases[] = { 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0 }; int i; for (i=0; bases[i]; i++) { _sound_port = bases[i]; if (_sb_reset_dsp(1) == 0) break; } } /* check if the card really exists */ ess_read_dsp_version(); if (ess_hw_ver < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("ESS AudioDrive not found")); _sound_port = orig_port; _sound_irq = orig_irq; _sound_dma = orig_dma; return FALSE; } /* figure out the hardware interrupt number */ ess_int = _map_irq(_sound_irq); /* set up the playback frequency */ if (_sound_freq <= 0) { _sound_freq = 22729; ess_dma_size = 1024; } else if (_sound_freq < 15000) { _sound_freq = 11363; ess_dma_size = 512; } else if (_sound_freq < 20000) { _sound_freq = 17046; ess_dma_size = 512; } else if (_sound_freq < 40000) { _sound_freq = 22729; ess_dma_size = 1024; } else { _sound_freq = 44194; ess_dma_size = 2048; } /* set up the card description */ uszprintf(ess_desc, sizeof(ess_desc), get_config_text("ES%X (%d hz) on port %X, using IRQ %d and DMA channel %d"), ess_hw_ver, _sound_freq, _sound_port, _sound_irq, _sound_dma); digi_audiodrive.desc = ess_desc; return TRUE; } /* ess_init: * AudioDrive init routine: returns zero on succes, -1 on failure. */ static int ess_init(int input, int voices) { int value; if (_dma_allocate_mem(ess_dma_size*2, &ess_sel, &ess_buf[0]) != 0) return -1; ess_buf[1] = ess_buf[0] + ess_dma_size; ess_lock_mem(); digi_audiodrive.voices = voices; if (_mixer_init(ess_dma_size/2, _sound_freq, TRUE, TRUE, &digi_audiodrive.voices) != 0) return -1; _mix_some_samples(ess_buf[0], _dos_ds, FALSE); _mix_some_samples(ess_buf[1], _dos_ds, FALSE); ess_bufnum = 0; _enable_irq(_sound_irq); _install_irq(ess_int, ess_interrupt); /* switch to AudioDrive extended mode */ _sb_reset_dsp(0x03); ess_write_dsp(0xC6); ess_set_sample_rate(_sound_freq); ess_write_dsp(0xB8); ess_write_dsp(0x04); ess_write_dsp(0xC0); ess_write_dsp(0xA8); value = ess_read_dsp() & ~3; /* 16 bit stereo */ value |= 0x01; ess_write_dsp(0xA8); ess_write_dsp(value); ess_write_dsp(0xB6); ess_write_dsp(0x00); ess_write_dsp(0xB7); ess_write_dsp(0x71); ess_write_dsp(0xB7); ess_write_dsp(0x9C); /* demand mode (4 bytes/request) */ ess_write_dsp(0xB9); ess_write_dsp(2); ess_write_dsp(0xC0); ess_write_dsp(0xB1); value = (ess_read_dsp() & 0x0F) | 0x50; ess_write_dsp(0xB1); ess_write_dsp(value); ess_write_dsp(0xC0); ess_write_dsp(0xB2); value = (ess_read_dsp() & 0x0F) | 0x50; ess_write_dsp(0xB2); ess_write_dsp(value); _dma_start(_sound_dma, ess_buf[0], ess_dma_size*2, TRUE, FALSE); ess_play_buffer(ess_dma_size); rest(100); _sb_voice(1); return 0; } /* ess_exit: * AudioDrive driver cleanup routine, removes ints, stops dma, * frees buffers, etc. */ static void ess_exit(int input) { /* halt sound output */ _sb_voice(0); /* stop dma transfer */ _dma_stop(_sound_dma); _sb_reset_dsp(1); /* restore interrupts */ _remove_irq(ess_int); /* reset PIC channels */ _restore_irq(_sound_irq); /* free conventional memory buffer */ __dpmi_free_dos_memory(ess_sel); _mixer_exit(); ess_hw_ver = -1; } /* ess_lock_mem: * Locks all the memory touched by parts of the AudiDrive code that are * executed in an interrupt context. */ static void ess_lock_mem(void) { LOCK_VARIABLE(digi_audiodrive); LOCK_VARIABLE(_sound_freq); LOCK_VARIABLE(_sound_port); LOCK_VARIABLE(_sound_dma); LOCK_VARIABLE(_sound_irq); LOCK_VARIABLE(ess_int); LOCK_VARIABLE(ess_hw_ver); LOCK_VARIABLE(ess_dma_size); LOCK_VARIABLE(ess_sel); LOCK_VARIABLE(ess_buf); LOCK_VARIABLE(ess_bufnum); LOCK_VARIABLE(ess_dma_count); LOCK_VARIABLE(ess_semaphore); LOCK_FUNCTION(ess_play_buffer); LOCK_FUNCTION(ess_interrupt); _dma_lock_mem(); } allegro-4.4.3.1/src/dos/swpps.s0000664000175000017500000000752413437077643015224 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Preliminary driver for Microsoft Sidewinder 3D/Precision/ * Force Feedback Pro Joysticks. * * By Acho A. Tang. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" #define PARAM1 40(%esp) #define PARAM2 44(%esp) #define PARAM3 48(%esp) #define PARAM4 52(%esp) #define PARAM5 56(%esp) #define PARAM6 60(%esp) #define PARAM7 64(%esp) #define PARAM8 68(%esp) .text /* void _swpp_get_portspeed(unsigned int port, unsigned int npasses, unsigned int *nqueries, unsigned int *elapsed) */ FUNC(_swpp_get_portspeed) pushfl pushal movl PARAM1,%edx // edx <- port movl PARAM2,%eax // eax <- npasses movl PARAM3,%esi // esi <- *nqueries movl PARAM4,%edi // edi <- *elapsed xorl %ebp,%ebp movb %al,%ah cli movb $0xb4,%al // select ch.2 to mode 2 outb %al,$0x43 xorb %al,%al // reset divisor and start counting outb %al,$0x42 outb %al,$0x42 .p2align 2 1: movl (%esi,%ebp),%ecx // load innerloop counter movb $0x84,%al // latch and read start timer value outb %al,$0x43 inb $0x42,%al movb %al,%bl inb $0x42,%al movb %al,%bh .p2align 2 0: inb %dx,%al // query game port decl %ecx jnz 0b movb $0x84,%al // latch and read end timer value outb %al,$0x43 inb $0x42,%al movb %al,%cl inb $0x42,%al movb %al,%ch subw %cx,%bx // store number of ticks elapsed movswl %bx,%ecx movl %ecx,(%edi,%ebp) addl $4,%ebp decb %ah jnz 1b sti popal popfl ret /* void _swpp_init_digital(unsigned int port, unsigned int ncmds, unsigned char *cmdiv, unsigned int *timeout) */ FUNC(_swpp_init_digital) pushfl pushal movl PARAM1,%edx // edx <- port addr movl PARAM2,%eax // eax <- ncmds movl PARAM3,%esi // esi <- *cmdiv movl PARAM4,%edi // ecx <- *timeout movl (%edi),%ecx movb %al,%ah cli movb $0xb0,%al // set ch.2 to mode 0 outb %al,$0x43 outb %al,%dx // trigger game port // wait for axis 0 to fall, time-out if necessary .p2align 2 0: // outter looptop inb %dx,%al decl %ecx jz 2f testb $1,%al jnz 0b // load counter 2 and start counting movb (%esi),%al outb %al,$0x42 movb 1(%esi),%al addl $2,%esi outb %al,$0x42 // wait for terminal state(output pin going high) *** NO TIME-OUT *** .p2align 2 1: movb $0xe8,%al // set ch.2 to read-back mode outb %al,$0x43 inb $0x42,%al // read output pin status testb $0x80,%al jz 1b // send the next/last command outb %al,%dx decb %ah jnz 0b 2: sti movl %ecx,(%edi) // save time-out status popal popfl ret /* void _swpp_read_analogue(unsigned int port, unsigned int *outbuf, unsigned int pollout) */ FUNC(_swpp_read_analogue) pushfl pushal movl PARAM1,%edx movl PARAM3,%ecx xorl %eax,%eax xorl %ebx,%ebx xorl %ebp,%ebp xorl %esi,%esi xorl %edi,%edi cli outb %al,%dx .p2align 4 0: inb %dx,%al rorb $1,%al adcl $0,%ebx rorb $1,%al adcl $0,%ebp rorb $1,%al adcl $0,%esi rorb $1,%al adcl $0,%edi testb $0xf0,%al jz 1f decl %ecx jnz 0b 1: sti movl PARAM2,%edx movzbl %al,%eax movl %eax,(%edx) movl %ebx,4(%edx) movl %ebp,8(%edx) movl %esi,12(%edx) movl %edi,16(%edx) movl %ecx,20(%edx) popal popfl ret allegro-4.4.3.1/src/dos/grip.h0000664000175000017500000001257513437077643015000 0ustar siegesiege/************************************************************************\ ** ** ** GrIP Prototype API Interface Library ** ** for ** ** DJGPP ** ** ** ** Revision 1.00 ** ** ** ** COPYRIGHT: ** ** ** ** (C) Copyright Advanced Gravis Computer Technology Ltd 1995. ** ** All Rights Reserved. ** ** ** ** DISCLAIMER OF WARRANTIES: ** ** ** ** The following [enclosed] code is provided to you "AS IS", ** ** without warranty of any kind. You have a royalty-free right to ** ** use, modify, reproduce and distribute the following code (and/or ** ** any modified version) provided that you agree that Advanced ** ** Gravis has no warranty obligations and shall not be liable for ** ** any damages arising out of your use of this code, even if they ** ** have been advised of the possibility of such damages. This ** ** Copyright statement and Disclaimer of Warranties may not be ** ** removed. ** ** ** ** HISTORY: ** ** ** ** 0.102 Jul 12 95 David Bollo Initial public release on ** ** GrIP hardware ** ** 0.200 Aug 10 95 David Bollo Added Gravis Loadable Library ** ** support ** ** 0.201 Aug 11 95 David Bollo Removed Borland C++ support ** ** for maintenance reasons ** ** 1.00 Nov 1 95 David Bollo First official release as ** ** part of GrIP SDK ** ** ** \************************************************************************/ #ifndef ALLEGRO_DOS_GRIP_H #define ALLEGRO_DOS_GRIP_H /* 2. Type Definitions */ typedef unsigned char GRIP_SLOT; typedef unsigned char GRIP_CLASS; typedef unsigned char GRIP_INDEX; typedef unsigned short GRIP_VALUE; typedef unsigned long GRIP_BITFIELD; typedef unsigned short GRIP_BOOL; typedef char *GRIP_STRING; typedef void *GRIP_BUF; typedef unsigned char *GRIP_BUF_C; typedef unsigned short *GRIP_BUF_S; typedef unsigned long *GRIP_BUF_L; /* Standard Classes */ #define GRIP_CLASS_BUTTON ((GRIP_CLASS)1) #define GRIP_CLASS_AXIS ((GRIP_CLASS)2) #define GRIP_CLASS_POV_HAT ((GRIP_CLASS)3) #define GRIP_CLASS_VELOCITY ((GRIP_CLASS)4) #define GRIP_CLASS_THROTTLE ((GRIP_CLASS)5) #define GRIP_CLASS_ANALOG ((GRIP_CLASS)6) #define GRIP_CLASS_MIN GRIP_CLASS_BUTTON #define GRIP_CLASS_MAX GRIP_CLASS_ANALOG /* Refresh Flags */ #define GRIP_REFRESH_COMPLETE 0 /* Default */ #define GRIP_REFRESH_PARTIAL 2 #define GRIP_REFRESH_TRANSMIT 0 /* Default */ #define GRIP_REFRESH_NOTRANSMIT 4 /* 3.1 System API Calls */ GRIP_BOOL _GrInitialize(void); void _GrShutdown(void); GRIP_BITFIELD _GrRefresh(GRIP_BITFIELD flags); /* 3.2 Configuration API Calls */ GRIP_BITFIELD _GrGetSlotMap(void); GRIP_BITFIELD _GrGetClassMap(GRIP_SLOT s); GRIP_BITFIELD _GrGetOEMClassMap(GRIP_SLOT s); GRIP_INDEX _GrGetMaxIndex(GRIP_SLOT s, GRIP_CLASS c); GRIP_VALUE _GrGetMaxValue(GRIP_SLOT s, GRIP_CLASS c); /* 3.3 Data API Calls */ GRIP_VALUE _GrGetValue(GRIP_SLOT s, GRIP_CLASS c, GRIP_INDEX i); GRIP_BITFIELD _GrGetPackedValues(GRIP_SLOT s, GRIP_CLASS c, GRIP_INDEX start, GRIP_INDEX end); void _GrSetValue(GRIP_SLOT s, GRIP_CLASS c, GRIP_INDEX i, GRIP_VALUE v); /* 3.4 OEM Information API Calls */ void _GrGetVendorName(GRIP_SLOT s, GRIP_STRING name); GRIP_VALUE _GrGetProductName(GRIP_SLOT s, GRIP_STRING name); void _GrGetControlName(GRIP_SLOT s, GRIP_CLASS c, GRIP_INDEX i, GRIP_STRING name); GRIP_BITFIELD _GrGetCaps(GRIP_SLOT s, GRIP_CLASS c, GRIP_INDEX i); /* 3.5 Library Management Calls */ GRIP_BOOL _GrLink(GRIP_BUF image, GRIP_VALUE size); GRIP_BOOL _GrUnlink(void); GRIP_BOOL _Gr__Link(void); void _Gr__Unlink(void); /* Diagnostic Information Calls */ GRIP_VALUE _GrGetSWVer(void); GRIP_VALUE _GrGetHWVer(void); GRIP_VALUE _GrGetDiagCnt(void); unsigned long _GrGetDiagReg(GRIP_INDEX reg); /* API Call Thunk */ typedef unsigned char GRIP_THUNK[14]; extern GRIP_THUNK _GRIP_Thunk; #endif /* ALLEGRO_DOS_GRIP_H */ allegro-4.4.3.1/src/dos/dsnddrv.c0000664000175000017500000000207713437077643015472 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of DOS sound drivers, kept in a seperate file so that * they can be overriden by user programs. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif BEGIN_DIGI_DRIVER_LIST DIGI_DRIVER_SOUNDSCAPE DIGI_DRIVER_AUDIODRIVE DIGI_DRIVER_WINSOUNDSYS DIGI_DRIVER_SB END_DIGI_DRIVER_LIST BEGIN_MIDI_DRIVER_LIST MIDI_DRIVER_AWE32 MIDI_DRIVER_DIGMID MIDI_DRIVER_ADLIB MIDI_DRIVER_MPU MIDI_DRIVER_SB_OUT END_MIDI_DRIVER_LIST allegro-4.4.3.1/src/dos/sw.c0000664000175000017500000003511213437077643014453 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the Microsoft Sidewinder. * * Main code by S.Sakamaki, using information provided by Robert Grubbs. * * Sidewinder detection routine (of aggressive mode) under Windows, * comments and translation by Tomohiko Sugiura. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error Something is wrong with the makefile #endif /* driver functions */ static int sw_init(void); static int sw_init_aggressive(void); static void sw_exit(void); static int sw_poll(void); #define DETECT_TRIES 1 static int read_sidewinder(void); static int change_mode_b(void); static int g_aggressive = FALSE; static int g_port = 0x201; static int g_swbuff_index = 0; static char g_swbuff[4096]; static char g_swdata[60]; static int g_swpaddata[4]; static int g_valid_count = 4096; static int g_base_count = 0; static int g_sw_count = 0; static int g_sw_mode = 0; static int g_sw_status = 0; static int g_endstrobelimit = 0; static int g_sw_raw_input[4]; #define SWMODE_A 1 #define SWMODE_B 2 static void _sw_reset_swbuff_index(void); static void _sw_swbuff_index_dec(void); static int _sw_poll(int gameport, int endstrobe_limit); static int _sw_poll_b(int gameport, int endstrobelimit); static int _sw_wait_strobe(char* data, int* length, char HL); static int _sw_in(char* data); static int _sw_mode_a_convert(char* data); static int _sw_mode_b_convert(char* data); static int _sw_convert(char* data, int* paddatabuff, int mode, int sw_count); static int _sw_trace_data(char* data, int* sw_count, int* mode); static int _sw_get_base_count(int* count); static int _sw_check_parity(int data); static void wait_for_sw_sleep(int gameport, int count); JOYSTICK_DRIVER joystick_sw = { JOY_TYPE_SIDEWINDER, empty_string, empty_string, "Sidewinder", sw_init, sw_exit, sw_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_sw_ag = { JOY_TYPE_SIDEWINDER_AG, empty_string, empty_string, "Sidewinder Aggressive", sw_init_aggressive, sw_exit, sw_poll, NULL, NULL, NULL, NULL }; /* sw_init_aggressive: * Initializes the aggressive driver. */ static int sw_init_aggressive(void) { g_aggressive = TRUE; return sw_init(); } /* sw_init: * Initializes the driver. */ static int sw_init(void) { int i; int d0; int d1; int mode; int port[] = { 0x201, 0x200, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207 }; int portindex; int success; int basecount; int validcount; d0 = 0; while (d0 < 4) { g_sw_raw_input[d0] = 0; d0 += 1; } if (g_aggressive) { portindex = 0; while (portindex < 8) { g_port = port[portindex]; for (success=0, i=0; i 0) { _sw_poll(g_port, g_endstrobelimit); /* read sw data */ result = TRUE; /* decode sw data */ if (!_sw_trace_data(g_swdata, &c_sw_count, &mode)) result = FALSE; if (result) { if (c_sw_count != g_sw_count) result = FALSE; /* error if numbers of sw is not equal to initialized one. */ } if (result) { /* convert 5(modeB) or 15(modeA) chars to 1 int */ if (!_sw_convert(g_swdata, g_swpaddata, mode, c_sw_count)) result = FALSE; } if (result) break; try -= 1; /* Wait for a while to confirm sw is inactive */ if (try != 0) wait_for_sw_sleep(g_port, g_base_count); } } else { wait_for_sw_sleep(g_port, g_base_count); /* Wait for a while to confirm sw is inactive */ _sw_poll(g_port, g_endstrobelimit); /* read sw data */ result = TRUE; /* decode sw data */ if (!_sw_trace_data(g_swdata, &c_sw_count, &mode)) result = FALSE; if (result) { if (c_sw_count != g_sw_count) result = FALSE; /* error if numbers of sw is not equal to initialized one. */ } if (result) { /* convert 5(modeB) or 15(modeA) chars to 1 int */ if (!_sw_convert(g_swdata, g_swpaddata, mode, c_sw_count)) result = FALSE; } } if (result) { d0 = 0; while (d0 < c_sw_count) { g_sw_raw_input[d0] = g_swpaddata[d0] << 1; /* store final sw status */ d0 += 1; } } return result; } static int _sw_convert(char* data, int* paddatabuff, int mode, int sw_count) { int d0; int d1; d0 = 0; while (d0 < sw_count) { switch (mode) { case 5: d1 = _sw_mode_b_convert(data + (d0*mode)); g_sw_mode = SWMODE_B; break; case 15: d1 = _sw_mode_a_convert(data + (d0*mode)); g_sw_mode = SWMODE_A; break; default: return FALSE; } if (_sw_check_parity(d1) == 0) return FALSE; *paddatabuff++ = d1; d0 += 1; } return TRUE; } /* _sw_check_parity: * Parity bit is 0 if odd button is pressed, else 1. */ static int _sw_check_parity(int data) { /* * valid lower 16bit */ int d0; d0 = 8; while (d0 > 0) { data = data ^ (data >> d0); d0 = d0 >> 1; } d0 = data & 0x01; return d0; /* return 1 if parity check passed. */ } /* _sw_mode_a_convert: * * xxUxxxxx * xxDxxxxx * xxRxxxxx * xxLxxxxx * converts xx0xxxxx to xPMS76543210LRDU * xx1xxxxx MLB is not used * xx2xxxxx * xx3xxxxx * xx4xxxxx * xx5xxxxx * xx6xxxxx * xx7xxxxx * xxSxxxxx * xxMxxxxx * xxPxxxxx */ static int _sw_mode_a_convert(char* data) { int d0; int d1; d0 = 14; d1 = 0; while (d0 >= 0) { d1 = d1 << 1; d1 |= ( *(data + d0) >> 5 ) & 0x01; d0 -= 1; } return d1; /* 15 buttons status */ } /*_sw_mode_b_convert: * RDUxxxxx * 10Lxxxxx * converts 432xxxxx to xPMS76543210LRDU * 765xxxxx MLB is not used * PMSxxxxx */ static int _sw_mode_b_convert(char* data) { int d0; int d1; d0 = 4; d1 = 0; while (d0 >= 0) { d1 = d1 << 3; d1 |= ( *(data + d0) >> 5 ) & 0x07; d0 -= 1; } return d1; /* 15 buttons status */ } static int _sw_trace_data(char* data, int* sw_count, int* mode) { char swbyte; int length; int d2; int d3; int data_index = 0; *mode = 0; *sw_count = 0; d2 = 0; if (!_sw_wait_strobe(&swbyte, &length, 1)) return FALSE; /* wait strobe 1 */ while (1) { if (!_sw_wait_strobe(&swbyte, &length, 0)) return FALSE; /* wait strobe 0 */ d2 += 1; if (data_index < 60) data[data_index++] = swbyte; if (!_sw_wait_strobe(&swbyte, &length, 1)) return FALSE; if (length >= g_base_count) { /* finish one pad */ /* if continued strobe 1 more than base_count */ if ((d2 == 5) || (d2 == 15)) { *mode = d2; /* data length is 5 on modeBC15 on modeA */ *sw_count += 1; if (length >= g_endstrobelimit) return TRUE; /* finish all pad */ /* if continued strobe 1 more than base_count*4 */ break; } else { /* if data length is not 5 or 15 ,sw data is destroyed */ return FALSE; } } } d2 = 0; while (1) { if (!_sw_wait_strobe(&swbyte, &length, 0)) return FALSE; d2 += 1; if (data_index < 60) data[data_index++] = swbyte; if (!_sw_wait_strobe(&swbyte, &length, 1)) return FALSE; if (length >= g_base_count) { /* finish one pad */ /* if continued strobe 1 more than base_count */ if ( d2 == *mode) { /* All sw must be same mode(A or B) */ /* if recieved data is valid, */ d2 = 0; *sw_count += 1; if (length >= g_endstrobelimit) break; /* finish all pad */ /* if continued strobe 1 more than base_count*4 */ } else { return FALSE; } } } return TRUE; } static int _sw_get_base_count(int* count) { char swbyte; int length; if (!_sw_wait_strobe(&swbyte, &length, 0)) return FALSE; if (!_sw_wait_strobe(&swbyte, &length, 1)) return FALSE; *count = length; if (!_sw_wait_strobe(&swbyte, &length, 0)) return FALSE; *count += length; return TRUE; } static int _sw_wait_strobe(char* data, int* length, char HL) { /* HL is 0 or 1 */ char d0; char d1; *length = 0; while (1) { if (_sw_in(data)) d1 = (*data & 0x10) >> 4; else return FALSE; if (d1 == HL) break; /* upclock or downclock */ } *length += 1; /* search next upclock or downclock point */ while (1) { if (_sw_in(&d0)) d1 = (d0 & 0x10) >> 4; else break; if (d1 != HL) { _sw_swbuff_index_dec(); break; } *length += 1; } return TRUE; } static void _sw_reset_swbuff_index(void) { g_swbuff_index = 0; } static void _sw_swbuff_index_dec(void) { g_swbuff_index -= 1; } /* _sw_in: * Reads memory of sw data buffer. */ static int _sw_in(char* data) { if (g_swbuff_index == g_valid_count) return FALSE; g_swbuff_index += 1; *data = g_swbuff[g_swbuff_index] & 0xF0; return TRUE; } /* _sw_poll: * Polls sw data from gameport. */ static int _sw_poll(int gameport, int endstrobelimit) { unsigned char* buff = (unsigned char *)g_swbuff; int bufflength = sizeof(g_swbuff); int read_count; int fill; int d0; int d1; int *a0; int strobecount; if (endstrobelimit == 0) endstrobelimit = bufflength; fill = 512; if (bufflength < 512) fill = bufflength; fill = (fill / sizeof(int)) - 2; _enter_critical(); a0 = (int*)buff; d0 = 0; while (d0 < fill) { *(a0 + d0) = *(a0 + d0 + 1); d0 += 1; } strobecount = 0; d0 = bufflength; outportb(gameport, 0x00); while (d0 > 0) { d1 = inportb(gameport); d1 = ~d1; *buff++ = (unsigned char)d1; d1 = (d1 >> 4) & 0x01; strobecount += d1; strobecount &= d1 * -1; d0 -= 1; if (strobecount == endstrobelimit) break; } _exit_critical(); g_valid_count = bufflength - d0; _sw_reset_swbuff_index(); return g_valid_count; } static void wait_for_sw_sleep(int gameport, int count) { int limit; int d0; d0 = 0; limit = 0; while (limit < 8192) { if ((inportb(gameport) & 0x10) != 0) { d0 += 1; } else { d0 = 0; } if (d0 >= count) break; limit += 1; } } static int change_mode_b(void) { int loop; int d0; int validcount; int limit; wait_for_sw_sleep(g_port, 4096); validcount = _sw_poll(g_port, g_endstrobelimit); limit = 256; loop = 0; while (loop < limit) { wait_for_sw_sleep(g_port, 4096); _enter_critical(); outportb(g_port, 0x00); d0 = 0; while (d0 < (g_base_count * (4 + loop))) { inportb(g_port); d0 += 1; } d0 = 0; while (d0 < validcount) { outportb(g_port, 0x00); d0 += 1; } _exit_critical(); wait_for_sw_sleep(g_port, 4096); sw_poll(); if (g_sw_status && (g_sw_mode == SWMODE_B)) break; loop += 1; } if (loop >= limit) return FALSE; return TRUE; } allegro-4.4.3.1/src/dos/djirq.c0000664000175000017500000000741113437077643015134 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Interrupt wrapper functions for djgpp. Unlike the libc * _go32_dpmi_* wrapper functions, these can deal with * reentrant interrupts. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #include "../i386/asmdefs.inc" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define MAX_IRQS 8 /* timer + keyboard + soundcard + spares */ #define STACK_SIZE 8192 /* an 8k stack should be plenty */ _IRQ_HANDLER _irq_handler[MAX_IRQS]; unsigned char *_irq_stack[IRQ_STACKS]; extern void _irq_wrapper_0(void), _irq_wrapper_1(void), _irq_wrapper_2(void), _irq_wrapper_3(void), _irq_wrapper_4(void), _irq_wrapper_5(void), _irq_wrapper_6(void), _irq_wrapper_7(void), _irq_wrapper_0_end(void); /* _dos_irq_init: * Initialises this module. */ void _dos_irq_init(void) { int c; LOCK_VARIABLE(_irq_handler); LOCK_VARIABLE(_irq_stack); LOCK_FUNCTION(_irq_wrapper_0); for (c=0; c> 8); } /* set_timer_rate: * Sets the delay time for PIT channel 1 in cycle mode. */ static INLINE void set_timer_rate(long time) { outportb(0x43, 0x34); outportb(0x40, time & 0xff); outportb(0x40, time >> 8); } /* read_timer: * Reads the elapsed time from PIT channel 1. */ static INLINE long read_timer(void) { long x; outportb(0x43, 0x00); x = inportb(0x40); x += inportb(0x40) << 8; return (0xFFFF - x + 1) & 0xFFFF; } /* fixed_timer_handler: * Interrupt handler for the fixed-rate timer driver. */ static int fixed_timer_handler(void) { int bios; bios_counter -= LOVEBILL_TIMER_SPEED; if (bios_counter <= 0) { bios_counter += 0x10000; bios = TRUE; } else { outportb(0x20, 0x20); ENABLE(); bios = FALSE; } _handle_timer_tick(LOVEBILL_TIMER_SPEED); if (!bios) DISABLE(); return bios; } END_OF_STATIC_FUNCTION(fixed_timer_handler); /* fixed_timer_init: * Installs the fixed-rate timer driver. */ int fixed_timer_init(void) { int i; LOCK_VARIABLE(timedrv_fixed_rate); LOCK_VARIABLE(bios_counter); LOCK_FUNCTION(fixed_timer_handler); bios_counter = 0x10000; if (_install_irq(TIMER_INT, fixed_timer_handler) != 0) return -1; DISABLE(); /* sometimes it doesn't seem to register if we only do this once... */ for (i=0; i<4; i++) set_timer_rate(LOVEBILL_TIMER_SPEED); ENABLE(); return 0; } /* fixed_timer_exit: * Shuts down the fixed-rate timer driver. */ void fixed_timer_exit(void) { DISABLE(); set_timer_rate(0); _remove_irq(TIMER_INT); set_timer_rate(0); ENABLE(); } /* var_timer_handler: * Interrupt handler for the variable-rate timer driver. */ static int var_timer_handler(void) { long new_delay = 0x8000; int callback[MAX_TIMERS]; int bios = FALSE; int x; /* reentrant interrupt? */ if (timer_semaphore) { timer_delay += REENTRANT_RECALL_GAP + read_timer(); set_timer(REENTRANT_RECALL_GAP - timer_clocking_loss/2); outportb(0x20, 0x20); return 0; } timer_semaphore = TRUE; /* deal with retrace synchronisation */ vsync_counter -= timer_delay; if (vsync_counter <= 0) { if (_timer_use_retrace) { /* wait for retrace to start */ do { } while (!(inportb(0x3DA)&8)); /* update the VGA pelpan register? */ if (_retrace_hpp_value >= 0) { inportb(0x3DA); outportb(0x3C0, 0x33); outportb(0x3C0, _retrace_hpp_value); _retrace_hpp_value = -1; } /* user callback */ retrace_count++; if (retrace_proc) retrace_proc(); vsync_counter = vsync_speed - VSYNC_MARGIN; } else { vsync_counter += vsync_speed; retrace_count++; if (retrace_proc) retrace_proc(); } } if (vsync_counter < new_delay) new_delay = vsync_counter; timer_delay += read_timer() + timer_clocking_loss; set_timer(0); /* process the user callbacks */ for (x=0; x 0)) { _timer_queue[x].counter -= timer_delay; if (_timer_queue[x].counter <= 0) { _timer_queue[x].counter += _timer_queue[x].speed; callback[x] = TRUE; } if ((_timer_queue[x].counter > 0) && (_timer_queue[x].counter < new_delay)) new_delay = _timer_queue[x].counter; } } /* update bios time */ bios_counter -= timer_delay; if (bios_counter <= 0) { bios_counter += 0x10000; bios = TRUE; } if (bios_counter < new_delay) new_delay = bios_counter; /* fudge factor to prevent interrupts coming too close to each other */ if (new_delay < 1024) timer_delay = 1024; else timer_delay = new_delay; /* start the timer up again */ new_delay = read_timer(); set_timer(timer_delay); timer_delay += new_delay; if (!bios) { outportb(0x20, 0x20); /* ack. the interrupt */ ENABLE(); } /* finally call the user timer routines */ for (x=0; xid == GFX_VGA) || (gfx_driver->id == GFX_MODEX))); } /* timer_calibrate_retrace: * Times several vertical retraces, and calibrates the retrace syncing * code accordingly. */ static void timer_calibrate_retrace(void) { int ot = _timer_use_retrace; int c; #define AVERAGE_COUNT 4 _timer_use_retrace = FALSE; vsync_speed = 0; /* time several retraces */ for (c=0; c BPS_TO_TIMER(40)) || (vsync_speed < BPS_TO_TIMER(110))) vsync_speed = BPS_TO_TIMER(70); vsync_counter = vsync_speed; _timer_use_retrace = ot; } /* var_timer_simulate_retrace: * Turns retrace syncing mode on or off. */ void var_timer_simulate_retrace(int enable) { if (enable) { timer_calibrate_retrace(); _timer_use_retrace = TRUE; } else { _timer_use_retrace = FALSE; vsync_counter = vsync_speed = BPS_TO_TIMER(70); } } /* var_timer_init: * Installs the variable-rate timer driver. */ int var_timer_init(void) { int x, y; if (i_love_bill) return -1; LOCK_VARIABLE(timedrv_variable_rate); LOCK_VARIABLE(bios_counter); LOCK_VARIABLE(timer_delay); LOCK_VARIABLE(timer_semaphore); LOCK_VARIABLE(timer_clocking_loss); LOCK_VARIABLE(vsync_counter); LOCK_VARIABLE(vsync_speed); LOCK_FUNCTION(var_timer_handler); vsync_counter = vsync_speed = BPS_TO_TIMER(70); bios_counter = 0x10000; timer_delay = 0x10000; if (_install_irq(TIMER_INT, var_timer_handler) != 0) return -1; DISABLE(); /* now work out how much time calls to the 8254 clock chip take * on this CPU/motherboard combination. It is impossible to time * a set_timer call so we approximate it by a read_timer call with * 4/5ths of a read_timer (no maths and no final read wait). This * gives 9/10ths of 4 read_timers. Do it three times all over to * get an averaging effect. */ x = read_timer(); read_timer(); read_timer(); read_timer(); y = read_timer(); read_timer(); read_timer(); read_timer(); y = read_timer(); read_timer(); read_timer(); read_timer(); y = read_timer(); if (y >= x) timer_clocking_loss = y - x; else timer_clocking_loss = 0x10000 - x + y; timer_clocking_loss = (9*timer_clocking_loss)/30; /* sometimes it doesn't seem to register if we only do this once... */ for (x=0; x<4; x++) set_timer(timer_delay); ENABLE(); return 0; } /* var_timer_exit: * Shuts down the variable-rate timer driver. */ void var_timer_exit(void) { DISABLE(); set_timer_rate(0); _remove_irq(TIMER_INT); set_timer_rate(0); ENABLE(); } allegro-4.4.3.1/src/dos/n64pad.c0000664000175000017500000002065513437077643015124 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for N64 controllers. * * By Richard Davies, based on sample code by Earle F. Philhower, III. * * This driver supports upto four N64 controllers. The analog stick * calibrates itself when the controller is powered up (in hardware). * There is some autodetection code included, but it's unused as it's * unreliable. Care to take a look? * * This driver is for the N64 pad -> parallel port interface developed * by Stephan Hans and Simon Nield, supported by DirectPad Pro 4.9. * * See http://www.st-hans.de/N64.htm for interface information, and * See http://www.ziplabel.com for DirectPad Pro information. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define LPT1_BASE 0x378 #define LPT2_BASE 0x278 #define LPT3_BASE 0x3bC #define D0 0x01 #define D1 0x02 #define D2 0x04 #define D3 0x08 #define D4 0x10 #define ACK 0x40 #define N64_HI 0xFF /* driver functions */ static int n64_init(void); static void n64p1_exit(void); static void n64p2_exit(void); static void n64p3_exit(void); static int n64p1_poll(void); static int n64p2_poll(void); static int n64p3_poll(void); static int n64_detect(int base, int joynum); JOYSTICK_DRIVER joystick_n641 = { JOY_TYPE_N64PAD_LPT1, NULL, NULL, "N64pad-LPT1", n64_init, n64p1_exit, n64p1_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_n642 = { JOY_TYPE_N64PAD_LPT2, NULL, NULL, "N64pad-LPT2", n64_init, n64p2_exit, n64p2_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_n643 = { JOY_TYPE_N64PAD_LPT3, NULL, NULL, "N64pad-LPT3", n64_init, n64p3_exit, n64p3_poll, NULL, NULL, NULL, NULL }; /* n64_init: * Initialiases the N64 joypad driver. */ static int n64_init(void) { int i; num_joysticks = 4; for (i=0; i 64); joy[joynum].stick[0].axis[1].d1 = (joy[joynum].stick[0].axis[1].pos < -64); joy[joynum].stick[0].axis[1].d2 = (joy[joynum].stick[0].axis[1].pos > 64); return 0; } /* n64p1_poll: * Input polling function. */ static int n64p1_poll(void) { int joynum; for (joynum=0; joynum #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif static BITMAP *vesa_1_init(int w, int h, int v_w, int v_h, int color_depth); static BITMAP *vesa_2b_init(int w, int h, int v_w, int v_h, int color_depth); static BITMAP *vesa_2l_init(int w, int h, int v_w, int v_h, int color_depth); static BITMAP *vesa_3_init(int w, int h, int v_w, int v_h, int color_depth); static void vesa_exit(BITMAP *b); static int vesa_scroll(int x, int y); static void vesa_vsync(void); static void vesa_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync); static int vesa_request_scroll(int x, int y); static int vesa_poll_scroll(void); static GFX_MODE_LIST *vesa_fetch_mode_list(void); static char vesa_desc[256] = EMPTY_STRING; GFX_DRIVER gfx_vesa_1 = { GFX_VESA1, empty_string, empty_string, "VESA 1.x", vesa_1_init, vesa_exit, vesa_scroll, _vga_vsync, _vga_set_palette_range, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ NULL, NULL, /* no state saving */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ vesa_fetch_mode_list, /* aye! */ 0, 0, FALSE, 0, 0, 0, 0, FALSE }; GFX_DRIVER gfx_vesa_2b = { GFX_VESA2B, empty_string, empty_string, "VESA 2.0 (banked)", vesa_2b_init, vesa_exit, vesa_scroll, vesa_vsync, vesa_set_palette_range, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ NULL, NULL, /* no state saving */ NULL, vesa_fetch_mode_list, /* aye! */ 0, 0, FALSE, 0, 0, 0, 0, FALSE }; GFX_DRIVER gfx_vesa_2l = { GFX_VESA2L, empty_string, empty_string, "VESA 2.0 (linear)", vesa_2l_init, vesa_exit, vesa_scroll, vesa_vsync, vesa_set_palette_range, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ NULL, NULL, /* no state saving */ NULL, vesa_fetch_mode_list, /* aye! */ 0, 0, FALSE, 0, 0, 0, 0, FALSE }; GFX_DRIVER gfx_vesa_3 = { GFX_VESA3, empty_string, empty_string, "VESA 3.0", vesa_3_init, vesa_exit, vesa_scroll, vesa_vsync, vesa_set_palette_range, vesa_request_scroll, vesa_poll_scroll, NULL, NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ NULL, NULL, /* no state saving */ NULL, vesa_fetch_mode_list, /* aye! */ 0, 0, FALSE, 0, 0, 0, 0, FALSE }; #define MASK_LINEAR(addr) ((addr) & 0x000FFFFF) #define RM_TO_LINEAR(addr) ((((addr) & 0xFFFF0000) >> 12) + ((addr) & 0xFFFF)) #define RM_OFFSET(addr) ((addr) & 0xF) #define RM_SEGMENT(addr) (((addr) >> 4) & 0xFFFF) #ifdef ALLEGRO_GCC #define __PACKED__ __attribute__ ((packed)) #else #define __PACKED__ #endif #ifdef ALLEGRO_WATCOM #pragma pack (1) #endif typedef struct VESA_INFO /* VESA information block structure */ { char VESASignature[4]; unsigned short VESAVersion __PACKED__; unsigned long OEMStringPtr __PACKED__; unsigned char Capabilities[4]; unsigned long VideoModePtr __PACKED__; unsigned short TotalMemory __PACKED__; unsigned short OemSoftwareRev __PACKED__; unsigned long OemVendorNamePtr __PACKED__; unsigned long OemProductNamePtr __PACKED__; unsigned long OemProductRevPtr __PACKED__; unsigned char Reserved[222]; unsigned char OemData[256]; } VESA_INFO; typedef struct MODE_INFO /* VESA information for a specific mode */ { unsigned short ModeAttributes __PACKED__; unsigned char WinAAttributes; unsigned char WinBAttributes; unsigned short WinGranularity __PACKED__; unsigned short WinSize __PACKED__; unsigned short WinASegment __PACKED__; unsigned short WinBSegment __PACKED__; unsigned long WinFuncPtr __PACKED__; unsigned short BytesPerScanLine __PACKED__; unsigned short XResolution __PACKED__; unsigned short YResolution __PACKED__; unsigned char XCharSize; unsigned char YCharSize; unsigned char NumberOfPlanes; unsigned char BitsPerPixel; unsigned char NumberOfBanks; unsigned char MemoryModel; unsigned char BankSize; unsigned char NumberOfImagePages; unsigned char Reserved_page; unsigned char RedMaskSize; unsigned char RedMaskPos; unsigned char GreenMaskSize; unsigned char GreenMaskPos; unsigned char BlueMaskSize; unsigned char BlueMaskPos; unsigned char ReservedMaskSize; unsigned char ReservedMaskPos; unsigned char DirectColorModeInfo; /* VBE 2.0 extensions */ unsigned long PhysBasePtr __PACKED__; unsigned long OffScreenMemOffset __PACKED__; unsigned short OffScreenMemSize __PACKED__; /* VBE 3.0 extensions */ unsigned short LinBytesPerScanLine __PACKED__; unsigned char BnkNumberOfPages; unsigned char LinNumberOfPages; unsigned char LinRedMaskSize; unsigned char LinRedFieldPos; unsigned char LinGreenMaskSize; unsigned char LinGreenFieldPos; unsigned char LinBlueMaskSize; unsigned char LinBlueFieldPos; unsigned char LinRsvdMaskSize; unsigned char LinRsvdFieldPos; unsigned long MaxPixelClock __PACKED__; unsigned char Reserved[190]; } MODE_INFO; typedef struct PM_INFO /* VESA 2.0 protected mode interface */ { unsigned short setWindow __PACKED__; unsigned short setDisplayStart __PACKED__; unsigned short setPalette __PACKED__; unsigned short IOPrivInfo __PACKED__; } PM_INFO; typedef struct CRTCInfoBlock /* VESA 3.0 CRTC timings structure */ { unsigned short HorizontalTotal __PACKED__; unsigned short HorizontalSyncStart __PACKED__; unsigned short HorizontalSyncEnd __PACKED__; unsigned short VerticalTotal __PACKED__; unsigned short VerticalSyncStart __PACKED__; unsigned short VerticalSyncEnd __PACKED__; unsigned char Flags; unsigned long PixelClock __PACKED__; /* units of Hz */ unsigned short RefreshRate __PACKED__; /* units of 0.01 Hz */ unsigned char reserved[40]; } CRTCInfoBlock; #define HPOS 0 #define HNEG (1 << 2) #define VPOS 0 #define VNEG (1 << 3) #define INTERLACED (1 << 1) #define DOUBLESCAN (1 << 0) static VESA_INFO vesa_info; /* SVGA info block */ static MODE_INFO mode_info; /* info for this video mode */ static char oem_string[256]; /* vendor name */ static unsigned long lb_linear = 0; /* linear address of framebuffer */ static int lb_segment = 0; /* descriptor for the buffer */ static PM_INFO *pm_info = NULL; /* VESA 2.0 pmode interface */ static unsigned long mmio_linear = 0; /* linear addr for mem mapped IO */ static int vesa_xscroll = 0; /* current display start address */ static int vesa_yscroll = 0; __dpmi_regs _dpmi_reg; /* for the bank switch routines */ int _window_2_offset = 0; /* window state information */ int _mmio_segment = 0; void (*_pm_vesa_switcher)(void) = NULL; /* VBE 2.0 pmode interface */ void (*_pm_vesa_scroller)(void) = NULL; void (*_pm_vesa_palette)(void) = NULL; static int evilness_flag = 0; /* set if we are doing dodgy things with VGA registers because the VESA implementation is no good */ /* get_vesa_info: * Retrieves a VESA info block structure, returning 0 for success. */ static int get_vesa_info(void) { unsigned long addr; int c; _farsetsel(_dos_ds); for (c=0; c<(int)sizeof(VESA_INFO); c++) _farnspokeb(MASK_LINEAR(__tb)+c, 0); dosmemput("VBE2", 4, MASK_LINEAR(__tb)); _dpmi_reg.x.ax = 0x4F00; _dpmi_reg.x.di = RM_OFFSET(__tb); _dpmi_reg.x.es = RM_SEGMENT(__tb); __dpmi_int(0x10, &_dpmi_reg); if (_dpmi_reg.h.ah) return -1; dosmemget(MASK_LINEAR(__tb), sizeof(VESA_INFO), &vesa_info); if (strncmp(vesa_info.VESASignature, "VESA", 4) != 0) return -1; addr = RM_TO_LINEAR(vesa_info.OEMStringPtr); _farsetsel(_dos_ds); c = 0; do { oem_string[c] = _farnspeekb(addr++); } while (oem_string[c++]); return 0; } /* get_mode_info: * Retrieves a mode info block structure, for a specific graphics mode. * Returns 0 for success. */ static int get_mode_info(int mode) { int c; _farsetsel(_dos_ds); for (c=0; c<(int)sizeof(MODE_INFO); c++) _farnspokeb(MASK_LINEAR(__tb)+c, 0); _dpmi_reg.x.ax = 0x4F01; _dpmi_reg.x.di = RM_OFFSET(__tb); _dpmi_reg.x.es = RM_SEGMENT(__tb); _dpmi_reg.x.cx = mode; __dpmi_int(0x10, &_dpmi_reg); if (_dpmi_reg.h.ah) return -1; dosmemget(MASK_LINEAR(__tb), sizeof(MODE_INFO), &mode_info); return 0; } /* _vesa_vidmem_check: * Trying to autodetect the available video memory in my hardware level * card drivers is a hopeless task. Fortunately that seems to be one of * the few things that VESA usually gets right, so if VESA is available * the non-VESA drivers can use it to confirm how much vidmem is present. */ long _vesa_vidmem_check(long mem) { if (get_vesa_info() != 0) return mem; if (vesa_info.TotalMemory <= 0) return mem; return MIN(mem, (vesa_info.TotalMemory << 16)); } /* find_vesa_mode: * Tries to find a VESA mode number for the specified screen size. * Searches the mode list from the VESA info block, and if that doesn't * work, uses the standard VESA mode numbers. */ static int find_vesa_mode(int w, int h, int color_depth, int vbe_version) { #define MAX_VESA_MODES 1024 unsigned short mode[MAX_VESA_MODES]; int memorymodel, bitsperpixel; int redmasksize, greenmasksize, bluemasksize; int greenmaskpos; int reservedmasksize, reservedmaskpos; int rs, gs, bs, gp, rss, rsp; int c, modes; long mode_ptr; if (get_vesa_info() != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA not available")); return 0; } if (vesa_info.VESAVersion < (vbe_version<<8)) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE %d.0 not available"), vbe_version); return 0; } mode_ptr = RM_TO_LINEAR(vesa_info.VideoModePtr); modes = 0; _farsetsel(_dos_ds); while ((mode[modes] = _farnspeekw(mode_ptr)) != 0xFFFF) { modes++; mode_ptr += 2; } switch (color_depth) { #ifdef ALLEGRO_COLOR8 case 8: memorymodel = 4; bitsperpixel = 8; redmasksize = greenmasksize = bluemasksize = 0; greenmaskpos = 0; reservedmasksize = 0; reservedmaskpos = 0; break; #endif #ifdef ALLEGRO_COLOR16 case 15: memorymodel = 6; bitsperpixel = 15; redmasksize = greenmasksize = bluemasksize = 5; greenmaskpos = 5; reservedmasksize = 1; reservedmaskpos = 15; break; case 16: memorymodel = 6; bitsperpixel = 16; redmasksize = bluemasksize = 5; greenmasksize = 6; greenmaskpos = 5; reservedmasksize = 0; reservedmaskpos = 0; break; #endif #ifdef ALLEGRO_COLOR24 case 24: memorymodel = 6; bitsperpixel = 24; redmasksize = bluemasksize = greenmasksize = 8; greenmaskpos = 8; reservedmasksize = 0; reservedmaskpos = 0; break; #endif #ifdef ALLEGRO_COLOR32 case 32: memorymodel = 6; bitsperpixel = 32; redmasksize = greenmasksize = bluemasksize = 8; greenmaskpos = 8; reservedmasksize = 8; reservedmaskpos = 24; break; #endif default: ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return 0; } #define MEM_MATCH(mem, wanted_mem) \ ((mem == wanted_mem) || ((mem == 4) && (wanted_mem == 6))) #define BPP_MATCH(bpp, wanted_bpp) \ ((bpp == wanted_bpp) || ((bpp == 16) && (wanted_bpp == 15))) #define RES_SIZE_MATCH(size, wanted_size, bpp) \ ((size == wanted_size) || ((size == 0) && ((bpp == 15) || (bpp == 32)))) #define RES_POS_MATCH(pos, wanted_pos, bpp) \ ((pos == wanted_pos) || ((pos == 0) && ((bpp == 15) || (bpp == 32)))) /* search the list of modes */ for (c=0; c= 3) && (mode_info.ModeAttributes & 0x80)) { rs = mode_info.LinRedMaskSize; gs = mode_info.LinGreenMaskSize; bs = mode_info.LinBlueMaskSize; gp = mode_info.LinGreenFieldPos; rss = mode_info.LinRsvdMaskSize; rsp = mode_info.LinRsvdFieldPos; } else { rs = mode_info.RedMaskSize; gs = mode_info.GreenMaskSize; bs = mode_info.BlueMaskSize; gp = mode_info.GreenMaskPos; rss = mode_info.ReservedMaskSize; rsp = mode_info.ReservedMaskPos; } if (((mode_info.ModeAttributes & 25) == 25) && (mode_info.XResolution == w) && (mode_info.YResolution == h) && (mode_info.NumberOfPlanes == 1) && MEM_MATCH(mode_info.MemoryModel, memorymodel) && BPP_MATCH(mode_info.BitsPerPixel, bitsperpixel) && (rs == redmasksize) && (gs == greenmasksize) && (bs == bluemasksize) && (gp == greenmaskpos) && RES_SIZE_MATCH(rss, reservedmasksize, mode_info.BitsPerPixel) && RES_POS_MATCH(rsp, reservedmaskpos, mode_info.BitsPerPixel)) /* looks like this will do... */ return mode[c]; } } /* try the standard mode numbers */ if ((w == 640) && (h == 400) && (color_depth == 8)) c = 0x100; else if ((w == 640) && (h == 480) && (color_depth == 8)) c = 0x101; else if ((w == 800) && (h == 600) && (color_depth == 8)) c = 0x103; else if ((w == 1024) && (h == 768) && (color_depth == 8)) c = 0x105; else if ((w == 1280) && (h == 1024) && (color_depth == 8)) c = 0x107; else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return 0; } if (get_mode_info(c) == 0) return c; ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return 0; } /* setup_vesa_desc: * Sets up the VESA driver description string. */ static void setup_vesa_desc(GFX_DRIVER *driver, int vbe_version, int linear) { char tmp1[64], tmp2[1600]; /* VESA version number */ uszprintf(vesa_desc, sizeof(vesa_desc), uconvert_ascii("%4.4s %d.%d (", tmp1), uconvert_ascii(vesa_info.VESASignature, tmp2), vesa_info.VESAVersion>>8, vesa_info.VESAVersion&0xFF); /* VESA description string */ ustrzcat(vesa_desc, sizeof(vesa_desc), uconvert_ascii(oem_string, tmp2)); ustrzcat(vesa_desc, sizeof(vesa_desc), uconvert_ascii(")", tmp1)); /* warn about dodgy hardware */ if (evilness_flag & 1) ustrzcat(vesa_desc, sizeof(vesa_desc), uconvert_ascii(", Trio64 bodge", tmp1)); if (evilness_flag & 2) ustrzcat(vesa_desc, sizeof(vesa_desc), uconvert_ascii(", 0x4F06 N.A.", tmp1)); /* banked/linear status for VBE 3.0 */ if (vbe_version >= 3) { if (linear) ustrzcat(vesa_desc, sizeof(vesa_desc), uconvert_ascii(", linear", tmp1)); else ustrzcat(vesa_desc, sizeof(vesa_desc), uconvert_ascii(", banked", tmp1)); } driver->desc = vesa_desc; } /* vesa_fetch_mode_list: * Generates a list of valid video modes for the VESA drivers. * Returns the mode list on success or NULL on failure. */ static GFX_MODE_LIST *vesa_fetch_mode_list(void) { GFX_MODE_LIST *mode_list; unsigned long mode_ptr; unsigned short *vesa_mode; int mode, pos, vesa_list_length; mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) return NULL; /* fetch list of VESA modes */ if (get_vesa_info()) return NULL; _farsetsel(_dos_ds); /* count number of VESA modes */ mode_ptr = RM_TO_LINEAR(vesa_info.VideoModePtr); for (mode_list->num_modes = 0; _farnspeekw(mode_ptr) != 0xFFFF; mode_list->num_modes++) mode_ptr += sizeof(unsigned short); /* allocate and fill in temporary vesa mode list */ vesa_mode = _AL_MALLOC(sizeof(unsigned short) * mode_list->num_modes); if (!vesa_mode) return NULL; mode_ptr = RM_TO_LINEAR(vesa_info.VideoModePtr); for (mode = 0; _farnspeekw(mode_ptr) != 0xFFFF; mode++) { vesa_mode[mode] = _farnspeekw(mode_ptr); mode_ptr += sizeof(unsigned short); } vesa_list_length = mode_list->num_modes; /* zero out text and <8 bpp modes for later exclusion */ for (mode = 0; mode < mode_list->num_modes; mode++) { if (get_mode_info(vesa_mode[mode])) return NULL; if ((mode_info.MemoryModel == 0) || (mode_info.BitsPerPixel < 8)) { vesa_mode[mode] = 0; mode_list->num_modes--; } } /* allocate mode list */ mode_list->mode = _AL_MALLOC(sizeof(GFX_MODE) * (mode_list->num_modes + 1)); if (!mode_list->mode) return NULL; /* fill in width, height and color depth for each VESA mode */ mode = 0; for (pos = 0; pos < vesa_list_length; pos++) { if (get_mode_info(vesa_mode[pos])) return NULL; if (!vesa_mode[pos]) continue; mode_list->mode[mode].width = mode_info.XResolution; mode_list->mode[mode].height = mode_info.YResolution; mode_list->mode[mode].bpp = mode_info.BitsPerPixel; mode++; } /* terminate list */ mode_list->mode[mode_list->num_modes].width = 0; mode_list->mode[mode_list->num_modes].height = 0; mode_list->mode[mode_list->num_modes].bpp = 0; /* free up temporary vesa mode list */ _AL_FREE(vesa_mode); return mode_list; } /* get_pmode_functions: * Attempts to use VBE 2.0 functions to get access to protected mode bank * switching, set display start, and palette routines, storing the bank * switchers in the w* parameters. */ static int get_pmode_functions(void (**w1)(void), void (**w2)(void)) { unsigned short *p; if (vesa_info.VESAVersion < 0x200) /* have we got VESA 2.0? */ return -1; _dpmi_reg.x.ax = 0x4F0A; /* retrieve pmode interface */ _dpmi_reg.x.bx = 0; __dpmi_int(0x10, &_dpmi_reg); if (_dpmi_reg.h.ah) return -1; if (pm_info) _AL_FREE(pm_info); pm_info = _AL_MALLOC(_dpmi_reg.x.cx); /* copy into our address space */ LOCK_DATA(pm_info, _dpmi_reg.x.cx); dosmemget((_dpmi_reg.x.es*16)+_dpmi_reg.x.di, _dpmi_reg.x.cx, pm_info); _mmio_segment = 0; if (pm_info->IOPrivInfo) { /* need memory mapped IO? */ p = (unsigned short *)((char *)pm_info + pm_info->IOPrivInfo); while (*p != 0xFFFF) /* skip the port table */ p++; p++; if (*p != 0xFFFF) { /* get descriptor */ if (_create_physical_mapping(&mmio_linear, &_mmio_segment, *((unsigned long *)p), *(p+2)) != 0) return -1; } } _pm_vesa_switcher = (void *)((char *)pm_info + pm_info->setWindow); _pm_vesa_scroller = (void *)((char *)pm_info + pm_info->setDisplayStart); _pm_vesa_palette = (void *)((char *)pm_info + pm_info->setPalette); if (_mmio_segment) { *w1 = _vesa_pm_es_window_1; *w2 = _vesa_pm_es_window_2; } else { *w1 = _vesa_pm_window_1; *w2 = _vesa_pm_window_2; } return 0; } /* sort_out_vesa_windows: * Checks the mode info block structure to determine which VESA windows * should be used for reading and writing to video memory. */ static int sort_out_vesa_windows(BITMAP *b, void (*w1)(void), void (*w2)(void)) { if ((mode_info.WinAAttributes & 5) == 5) /* write to window 1? */ b->write_bank = w1; else if ((mode_info.WinBAttributes & 5) == 5) /* write to window 2? */ b->write_bank = w2; else return -1; if ((mode_info.WinAAttributes & 3) == 3) /* read from window 1? */ b->read_bank = w1; else if ((mode_info.WinBAttributes & 3) == 3) /* read from window 2? */ b->read_bank = w2; else return -1; /* are the windows at different places in memory? */ _window_2_offset = (mode_info.WinBSegment - mode_info.WinASegment) * 16; /* is it safe to do screen->screen blits? */ if (b->read_bank == b->write_bank) b->id |= BMP_ID_NOBLIT; return 0; } /* make_linear_bitmap: * Creates a screen bitmap for a linear framebuffer mode, creating the * required physical address mappings and allocating an LDT descriptor * to access the memory. */ static BITMAP *make_linear_bitmap(GFX_DRIVER *driver, int width, int height, int color_depth, int bpl) { unsigned long addr; int seg; BITMAP *b; #ifdef ALLEGRO_DJGPP /* use farptr access with djgpp */ if (_create_physical_mapping(&lb_linear, &lb_segment, mode_info.PhysBasePtr, driver->vid_mem) != 0) return NULL; addr = 0; seg = lb_segment; #else /* use nearptr access with Watcom */ if (_create_linear_mapping(&lb_linear, mode_info.PhysBasePtr, driver->vid_mem) != 0) return NULL; addr = lb_linear; seg = _default_ds(); #endif b = _make_bitmap(width, height, addr, driver, color_depth, bpl); if (!b) { _remove_physical_mapping(&lb_linear, &lb_segment); return NULL; } driver->vid_phys_base = mode_info.PhysBasePtr; b->seg = seg; return b; } /* calc_crtc_timing: * Calculates CRTC mode timings. */ static void calc_crtc_timing(CRTCInfoBlock *crtc, int xres, int yres, int xadjust, int yadjust) { int HTotal, VTotal; int HDisp, VDisp; int HSS, VSS; int HSE, VSE; int HSWidth, VSWidth; int SS, SE; int doublescan = FALSE; if (yres < 400){ doublescan = TRUE; yres *= 2; } HDisp = xres; HTotal = (int)(HDisp * 1.27) & ~0x7; HSWidth = (int)((HTotal - HDisp) / 5) & ~0x7; HSS = HDisp + 16; HSE = HSS + HSWidth; VDisp = yres; VTotal = VDisp * 1.07; VSWidth = (VTotal / 100) + 1; VSS = VDisp + ((int)(VTotal - VDisp) / 5) + 1; VSE = VSS + VSWidth; SS = HSS + xadjust; SE = HSE + xadjust; if (xadjust < 0) { if (SS < (HDisp + 8)) { SS = HDisp + 8; SE = SS + HSWidth; } } else { if ((HTotal - 24) < SE) { SE = HTotal - 24; SS = SE - HSWidth; } } HSS = SS; HSE = SE; SS = VSS + yadjust; SE = VSE + yadjust; if (yadjust < 0) { if (SS < (VDisp + 3)) { SS = VDisp + 3; SE = SS + VSWidth; } } else { if ((VTotal - 4) < SE) { SE = VTotal - 4; SS = SE - VSWidth; } } VSS = SS; VSE = SE; crtc->HorizontalTotal = HTotal; crtc->HorizontalSyncStart = HSS; crtc->HorizontalSyncEnd = HSE; crtc->VerticalTotal = VTotal; crtc->VerticalSyncStart = VSS; crtc->VerticalSyncEnd = VSE; crtc->Flags = HNEG | VNEG; if (doublescan) crtc->Flags |= DOUBLESCAN; } /* get_closest_pixel_clock: * Uses VESA 3.0 function 0x4F0B to find the closest pixel clock to the * requested value. */ static unsigned long get_closest_pixel_clock(int mode_no, unsigned long vclk) { __dpmi_regs r; r.x.ax = 0x4F0B; r.h.bl = 0; r.d.ecx = vclk; r.x.dx = mode_no; __dpmi_int(0x10, &r); if (r.h.ah != 0) return 0; return r.d.ecx; } /* vesa_init: * Tries to enter the specified graphics mode, and makes a screen bitmap * for it. Will use a linear framebuffer if one is available. */ static BITMAP *vesa_init(GFX_DRIVER *driver, int linear, int vbe_version, int w, int h, int v_w, int v_h, int color_depth) { BITMAP *b; int width, height; int vesa_mode; int bytes_per_scanline; void (*w1)(void) = _vesa_window_1; void (*w2)(void) = _vesa_window_2; int bpp = BYTES_PER_PIXEL(color_depth); int rs, gs, bs; vesa_mode = find_vesa_mode(w, h, color_depth, vbe_version); if (vesa_mode == 0) return NULL; LOCK_FUNCTION(_vesa_window_1); LOCK_FUNCTION(_vesa_window_2); LOCK_FUNCTION(_vesa_pm_window_1); LOCK_FUNCTION(_vesa_pm_window_2); LOCK_FUNCTION(_vesa_pm_es_window_1); LOCK_FUNCTION(_vesa_pm_es_window_2); LOCK_VARIABLE(_window_2_offset); LOCK_VARIABLE(_dpmi_reg); LOCK_VARIABLE(_pm_vesa_switcher); LOCK_VARIABLE(_mmio_segment); driver->vid_mem = vesa_info.TotalMemory << 16; if (vbe_version >= 3) linear = (mode_info.ModeAttributes & 0x80) ? TRUE : FALSE; if (linear) { /* linear framebuffer */ if (mode_info.ModeAttributes & 0x80) { driver->linear = TRUE; driver->bank_size = driver->bank_gran = 0; } else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Linear framebuffer not available")); return NULL; } } else { /* banked framebuffer */ if (!(mode_info.ModeAttributes & 0x40)) { driver->linear = FALSE; driver->bank_size = mode_info.WinSize * 1024; driver->bank_gran = mode_info.WinGranularity * 1024; } else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Banked framebuffer not available")); return NULL; } } if (MAX(w, v_w) * MAX(h, v_h) * bpp > driver->vid_mem) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Insufficient video memory")); return NULL; } /* avoid bug in S3 Trio64 drivers (can't set SVGA without VGA first) */ if (strstr(oem_string, "Trio64")) { _dpmi_reg.x.ax = 0x13; __dpmi_int(0x10, &_dpmi_reg); evilness_flag = 1; } else evilness_flag = 0; /* set screen mode */ _dpmi_reg.x.ax = 0x4F02; _dpmi_reg.x.bx = vesa_mode; if (driver->linear) _dpmi_reg.x.bx |= 0x4000; if ((_refresh_rate_request > 0) && (vbe_version >= 3)) { /* VESA 3.0 stuff for controlling the refresh rate */ CRTCInfoBlock crtc; unsigned long vclk; double f0; calc_crtc_timing(&crtc, w, h, 0, 0); vclk = (double)crtc.HorizontalTotal * crtc.VerticalTotal * _refresh_rate_request; vclk = get_closest_pixel_clock(vesa_mode, vclk); if (vclk != 0) { f0 = (double)vclk / (crtc.HorizontalTotal * crtc.VerticalTotal); _set_current_refresh_rate((int)(f0 + 0.5)); crtc.PixelClock = vclk; crtc.RefreshRate = _refresh_rate_request * 100; dosmemput(&crtc, sizeof(CRTCInfoBlock), MASK_LINEAR(__tb)); _dpmi_reg.x.di = RM_OFFSET(__tb); _dpmi_reg.x.es = RM_SEGMENT(__tb); _dpmi_reg.x.bx |= 0x0800; } } __dpmi_int(0x10, &_dpmi_reg); if (_dpmi_reg.h.ah) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA function 0x4F02 failed")); return NULL; } if ((vbe_version >= 3) && (linear)) bytes_per_scanline = mode_info.LinBytesPerScanLine; else bytes_per_scanline = mode_info.BytesPerScanLine; width = MAX(bytes_per_scanline, v_w*bpp); _sort_out_virtual_width(&width, driver); if (width <= bytes_per_scanline) { height = driver->vid_mem / width; } else { /* increase logical width */ _dpmi_reg.x.ax = 0x4F06; _dpmi_reg.x.bx = 0; _dpmi_reg.x.cx = width/bpp; __dpmi_int(0x10, &_dpmi_reg); if ((_dpmi_reg.h.ah) || (width > _dpmi_reg.x.bx)) { /* Evil, evil, evil. I really wish I didn't have to do this, but * some crappy VESA implementations can't handle the set logical * width call, which Allegro depends on. This register write will * work on 99% of cards, if VESA lets me down. */ if ((width != 1024) && (width != 2048)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA function 0x4F06 failed")); return NULL; } _dpmi_reg.x.ax = 0x4F02; _dpmi_reg.x.bx = vesa_mode; if (driver->linear) _dpmi_reg.x.bx |= 0x4000; __dpmi_int(0x10, &_dpmi_reg); if (_dpmi_reg.h.ah) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA function 0x4F02 failed")); return NULL; } _set_vga_virtual_width(bytes_per_scanline, width); height = driver->vid_mem / width; evilness_flag |= 2; } else { /* Some VESA drivers don't report the available virtual height * properly, so we do a sanity check based on the total amount of * video memory. */ width = _dpmi_reg.x.bx; height = MIN(_dpmi_reg.x.dx, driver->vid_mem / width); } } if ((width/bpp < v_w) || (width/bpp < w) || (height < v_h) || (height < h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen size too large")); return NULL; } if (vbe_version >= 2) { if (get_pmode_functions(&w1, &w2) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA protected mode interface not available")); return NULL; } } if (driver->linear) { /* make linear bitmap? */ b = make_linear_bitmap(driver, width/bpp, height, color_depth, width); if (!b) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't make linear screen bitmap")); return NULL; } } else { /* or make bank switcher */ b = _make_bitmap(width/bpp, height, mode_info.WinASegment*16, driver, color_depth, width); if (!b) return NULL; if (sort_out_vesa_windows(b, w1, w2) != 0) { destroy_bitmap(b); return NULL; } } #if (defined ALLEGRO_COLOR16) || (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) if ((vbe_version >= 3) && (linear)) { rs = mode_info.LinRedFieldPos; gs = mode_info.LinGreenFieldPos; bs = mode_info.LinBlueFieldPos; } else { rs = mode_info.RedMaskPos; gs = mode_info.GreenMaskPos; bs = mode_info.BlueMaskPos; } switch (color_depth) { #ifdef ALLEGRO_COLOR16 case 15: _rgb_r_shift_15 = rs; _rgb_g_shift_15 = gs; _rgb_b_shift_15 = bs; break; case 16: _rgb_r_shift_16 = rs; _rgb_g_shift_16 = gs; _rgb_b_shift_16 = bs; break; #endif #ifdef ALLEGRO_COLOR24 case 24: _rgb_r_shift_24 = rs; _rgb_g_shift_24 = gs; _rgb_b_shift_24 = bs; break; #endif #ifdef ALLEGRO_COLOR32 case 32: _rgb_r_shift_32 = rs; _rgb_g_shift_32 = gs; _rgb_b_shift_32 = bs; break; #endif } #endif /* is triple buffering supported? */ if (vbe_version >= 3) { if (mode_info.ModeAttributes & 0x400) { driver->request_scroll = vesa_request_scroll; driver->poll_scroll = vesa_poll_scroll; } else { driver->request_scroll = NULL; driver->poll_scroll = NULL; } } vesa_xscroll = vesa_yscroll = 0; driver->w = b->cr = w; driver->h = b->cb = h; setup_vesa_desc(driver, vbe_version, linear); return b; } /* vesa_1_init: * Initialises a VESA 1.x screen mode. */ static BITMAP *vesa_1_init(int w, int h, int v_w, int v_h, int color_depth) { return vesa_init(&gfx_vesa_1, FALSE, 1, w, h, v_w, v_h, color_depth); } /* vesa_2b_init: * Initialises a VESA 2.0 banked screen mode. */ static BITMAP *vesa_2b_init(int w, int h, int v_w, int v_h, int color_depth) { return vesa_init(&gfx_vesa_2b, FALSE, 2, w, h, v_w, v_h, color_depth); } /* vesa_2l_init: * Initialises a VESA 2.0 linear framebuffer mode. */ static BITMAP *vesa_2l_init(int w, int h, int v_w, int v_h, int color_depth) { return vesa_init(&gfx_vesa_2l, TRUE, 2, w, h, v_w, v_h, color_depth); } /* vesa_3_init: * Initialises a VESA 3.0 mode. */ static BITMAP *vesa_3_init(int w, int h, int v_w, int v_h, int color_depth) { return vesa_init(&gfx_vesa_3, FALSE, 3, w, h, v_w, v_h, color_depth); } /* vesa_vsync: * VBE 2.0 vsync routine, needed for cards that don't emulate the VGA * blanking registers. VBE doesn't provide a vsync function, but we * can emulate it by changing the display start with the vsync flag set. */ static void vesa_vsync(void) { vesa_scroll(vesa_xscroll, vesa_yscroll); } /* vesa_scroll: * Hardware scrolling routine. */ static int vesa_scroll(int x, int y) { int ret, seg; long a; vesa_xscroll = x; vesa_yscroll = y; if (_pm_vesa_scroller) { /* use protected mode interface? */ seg = _mmio_segment ? _mmio_segment : _default_ds(); a = ((x * BYTES_PER_PIXEL(screen->vtable->color_depth)) + (y * ((unsigned long)screen->line[1] - (unsigned long)screen->line[0]))) / 4; #ifdef ALLEGRO_GCC /* use gcc-style inline asm */ asm ( " pushl %%ebp ; " " pushw %%es ; " " movw %w1, %%es ; " /* set the IO segment */ " call *%0 ; " /* call the VESA function */ " popw %%es ; " " popl %%ebp ; " : /* no outputs */ : "S" (_pm_vesa_scroller), /* function pointer in esi */ "a" (seg), /* IO segment in eax */ "b" (0x80), /* mode in ebx */ "c" (a&0xFFFF), /* low word of address in ecx */ "d" (a>>16) /* high word of address in edx */ : "memory", "%edi", "%cc" /* clobbers edi and flags */ ); #elif defined ALLEGRO_WATCOM /* use Watcom-style inline asm */ { void _scroll(void *func, int seg, int mode, int addr1, int addr2); #pragma aux _scroll = \ " push ebp " \ " push es " \ " mov es, ax " \ " call esi " \ " pop es " \ " pop ebp " \ \ parm [esi] [eax] [ebx] [ecx] [edx] \ modify [edi]; _scroll(_pm_vesa_scroller, seg, 0x80, a&0xFFFF, a>>16); } #else #error unknown platform #endif ret = 0; } else { /* use a real mode interrupt call */ _dpmi_reg.x.ax = 0x4F07; _dpmi_reg.x.bx = 0; _dpmi_reg.x.cx = x; _dpmi_reg.x.dx = y; __dpmi_int(0x10, &_dpmi_reg); ret = _dpmi_reg.h.ah; _vsync_in(); } return (ret ? -1 : 0); } /* vesa_set_palette_range: * Uses VESA function #9 (VBE 2.0 only) to set the palette. */ static void vesa_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) { PALETTE tmp; int c, mode, seg; if (_pm_vesa_palette) { /* use protected mode interface? */ mode = (vsync) ? 0x80 : 0; seg = (_mmio_segment) ? _mmio_segment : _default_ds(); /* swap the palette into the funny order VESA uses */ for (c=from; c<=to; c++) { tmp[c].r = p[c].b; tmp[c].g = p[c].g; tmp[c].b = p[c].r; } #ifdef ALLEGRO_GCC /* use gcc-style inline asm */ asm ( " pushl %%ebp ; " " pushw %%ds ; " " movw %w1, %%ds ; " /* set the IO segment */ " call *%0 ; " /* call the VESA function */ " popw %%ds ; " " popl %%ebp ; " : /* no outputs */ : "S" (_pm_vesa_palette), /* function pointer in esi */ "a" (seg), /* IO segment in eax */ "b" (mode), /* mode in ebx */ "c" (to-from+1), /* how many colors in ecx */ "d" (from), /* first color in edx */ "D" (tmp+from) /* palette data pointer in edi */ : "memory", "%cc" /* clobbers flags */ ); #elif defined ALLEGRO_WATCOM /* use Watcom-style inline asm */ { void _pal(void *func, int seg, int mode, int count, int from, void *data); #pragma aux _pal = \ " push ebp " \ " push ds " \ " mov ds, ax " \ " call esi " \ " pop ds " \ " pop ebp " \ \ parm [esi] [eax] [ebx] [ecx] [edx] [edi]; _pal(_pm_vesa_palette, seg, mode, to-from+1, from, tmp+from); } #else #error unknown platform #endif } else _vga_set_palette_range(p, from, to, vsync); } /* vesa_request_scroll: * VBE 3.0 triple buffering initiate routine. */ static int vesa_request_scroll(int x, int y) { long a = (x * BYTES_PER_PIXEL(screen->vtable->color_depth)) + (y * ((unsigned long)screen->line[1] - (unsigned long)screen->line[0])); vesa_xscroll = x; vesa_yscroll = y; _dpmi_reg.x.ax = 0x4F07; _dpmi_reg.x.bx = 2; _dpmi_reg.d.ecx = a; __dpmi_int(0x10, &_dpmi_reg); return (_dpmi_reg.h.ah ? -1 : 0); } /* vesa_poll_scroll: * VBE 3.0 triple buffering test routine. */ static int vesa_poll_scroll(void) { _dpmi_reg.x.ax = 0x4F07; _dpmi_reg.x.bx = 4; __dpmi_int(0x10, &_dpmi_reg); if ((_dpmi_reg.h.ah) || (_dpmi_reg.x.cx)) return FALSE; return TRUE; } /* vesa_exit: * Shuts down the VESA driver. */ static void vesa_exit(BITMAP *b) { if (b->vtable->color_depth > 8) { /* workaround for some buggy VESA drivers that fail to clean up * properly after using truecolor modes... */ _dpmi_reg.x.ax = 0x4F02; _dpmi_reg.x.bx = 0x101; __dpmi_int(0x10, &_dpmi_reg); } _remove_physical_mapping(&lb_linear, &lb_segment); _remove_physical_mapping(&mmio_linear, &_mmio_segment); if (pm_info) { _AL_FREE(pm_info); pm_info = NULL; } _pm_vesa_switcher = _pm_vesa_scroller = _pm_vesa_palette = NULL; } allegro-4.4.3.1/src/dos/awedata.c0000664000175000017500000025553113437077643015441 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Static SoundFont data, provided by George Foot. * * This file was created automatically from SoundFont data by use of * the write_sf_embedded function in readsfnt.c. * * See readme.txt for copyright information. */ short int _awe_sf_defaults[] = { 0, 0, 0, 0, 0, 0, 0, 0, 13500, 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, 0, 0, -12000, -725, -12000, -15600, -12000, -8800, -12000, -12000, 1000, -12000, 0, 0, -12000, -12000, -6772, -6772, 1000, -12000, 0, 0, -1, 0, 32512, 32512, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, -1 }; int _awe_sf_num_presets = 129; short int _awe_sf_presets[] = { 0, 0, 8, 1, 0, 8, 2, 0, 6, 3, 0, 16, 4, 0, 8, 5, 0, 2, 6, 0, 5, 7, 0, 2, 8, 0, 3, 9, 0, 4, 10, 0, 6, 11, 0, 3, 12, 0, 2, 13, 0, 2, 14, 0, 1, 15, 0, 2, 16, 0, 4, 17, 0, 3, 18, 0, 5, 19, 0, 5, 20, 0, 5, 21, 0, 6, 22, 0, 2, 23, 0, 5, 24, 0, 4, 25, 0, 3, 26, 0, 4, 27, 0, 2, 28, 0, 2, 29, 0, 6, 30, 0, 5, 31, 0, 2, 32, 0, 3, 33, 0, 3, 34, 0, 3, 35, 0, 3, 36, 0, 3, 37, 0, 3, 38, 0, 5, 39, 0, 6, 40, 0, 6, 41, 0, 6, 42, 0, 3, 43, 0, 3, 44, 0, 4, 45, 0, 2, 46, 0, 2, 47, 0, 8, 48, 0, 4, 49, 0, 4, 50, 0, 2, 51, 0, 4, 52, 0, 4, 53, 0, 4, 54, 0, 2, 55, 0, 2, 56, 0, 6, 57, 0, 5, 58, 0, 3, 59, 0, 3, 60, 0, 2, 61, 0, 6, 62, 0, 2, 63, 0, 2, 64, 0, 8, 65, 0, 8, 66, 0, 8, 67, 0, 7, 68, 0, 4, 69, 0, 2, 70, 0, 3, 71, 0, 3, 72, 0, 4, 73, 0, 4, 74, 0, 2, 75, 0, 4, 76, 0, 4, 77, 0, 2, 78, 0, 2, 79, 0, 2, 80, 0, 4, 81, 0, 4, 82, 0, 4, 83, 0, 4, 84, 0, 4, 85, 0, 4, 86, 0, 4, 87, 0, 5, 88, 0, 4, 89, 0, 2, 90, 0, 4, 91, 0, 4, 92, 0, 4, 93, 0, 8, 94, 0, 4, 95, 0, 2, 96, 0, 3, 97, 0, 4, 98, 0, 4, 99, 0, 5, 100, 0, 4, 101, 0, 4, 102, 0, 4, 103, 0, 3, 104, 0, 2, 105, 0, 3, 106, 0, 5, 107, 0, 2, 108, 0, 4, 109, 0, 4, 110, 0, 6, 111, 0, 2, 112, 0, 4, 113, 0, 4, 114, 0, 2, 115, 0, 2, 116, 0, 3, 117, 0, 2, 118, 0, 4, 119, 0, 2, 120, 0, 2, 121, 0, 2, 122, 0, 4, 123, 0, 4, 124, 0, 4, 125, 0, 4, 126, 0, 4, 127, 0, 4, 0, 128, 68 }; short int _awe_sf_splits[] = { /* 0 */ 11, 12, 12, 12, 12, 12, 12, 12, 18, 19, 19, 19, 19, 19, 19, 19, 17, 18, 18, 18, 18, 18, 12, 13, 13, 13, 13, 13, 13, 13, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 11, 11, 11, 14, 14, 17, 14, 11, 11, 11, 17, 14, /* 8 */ 13, 11, 11, 16, 16, 11, 11, 17, 17, 17, 16, 16, 16, 20, 20, 21, 17, 17, 8, 9, 11, 11, 11, /* 16 */ 13, 13, 13, 13, 16, 16, 14, 20, 18, 18, 17, 17, 13, 13, 16, 16, 16, 12, 12, 12, 10, 10, 12, 12, 12, 12, 13, 13, 14, 12, 14, 14, 12, 10, 10, /* 24 */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 15, 15, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 12, /* 32 */ 10, 10, 10, 12, 13, 13, 15, 15, 15, 15, 15, 15, 17, 15, 15, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, /* 40 */ 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 14, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, /* 48 */ 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 13, 13, 15, 16, 10, 10, 11, 11, 14, 14, 11, 11, 10, 10, 9, 8, /* 56 */ 17, 17, 17, 17, 17, 17, 20, 20, 20, 20, 20, 16, 16, 16, 20, 20, 20, 15, 15, 16, 16, 16, 17, 17, 17, 16, 17, 18, 18, /* 64 */ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 13, 15, 12, 15, 15, 13, 14, 15, 13, /* 72 */ 14, 14, 14, 12, 15, 15, 11, 11, 16, 14, 11, 11, 13, 11, 10, 10, 11, 11, 11, 11, 13, 13, 13, 13, /* 80 */ 12, 10, 12, 10, 14, 14, 14, 14, 12, 12, 12, 10, 12, 12, 21, 21, 10, 10, 13, 13, 14, 14, 16, 16, 18, 18, 17, 17, 19, 19, 19, 19, 19, /* 88 */ 12, 12, 16, 16, 12, 12, 15, 15, 19, 19, 14, 14, 14, 14, 15, 15, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 20, 20, 19, 19, 20, 20, /* 96 */ 15, 15, 16, 20, 20, 20, 20, 13, 13, 11, 11, 17, 17, 17, 15, 15, 13, 13, 12, 12, 18, 18, 19, 19, 17, 17, 19, 19, 19, 16, 16, /* 104 */ 10, 10, 11, 11, 11, 10, 10, 12, 12, 12, 11, 11, 11, 11, 9, 9, 12, 12, 10, 12, 14, 14, 14, 14, 14, 14, 15, 15, /* 112 */ 11, 11, 11, 8, 9, 9, 10, 10, 11, 11, 10, 10, 12, 12, 11, 12, 12, 17, 17, 15, 15, 12, 12, /* 120 */ 11, 11, 11, 11, 19, 18, 17, 18, 17, 10, 19, 19, 14, 12, 13, 12, 19, 19, 19, 18, 13, 12, 13, 12, 11, 11, 11, 11, /* 128 */ 8, 9, 8, 9, 9, 8, 8, 7, 8, 9, 8, 8, 8, 8, 10, 10, 8, 9, 10, 13, 10, 14, 10, 11, 9, 9, 9, 10, 10, 10, 10, 11, 10, 10, 9, 8, 10, 9, 8, 8, 8, 8, 9, 9, 8, 8, 8, 9, 11, 11, 10, 10, 9, 9, 9, 10, 10, 11, 11, 8, 10, 10, 9, 9, 9, 10, 11, 12 }; short int _awe_sf_gens[] = { /* Preset 0 */ 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,12800, 48,100, 52,-43, 54,1, 58,75 , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,14643, 48,100, 52,8, 53,1, 54,1, 58,81 , 8,9617, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,16954, 48,100, 52,4, 53,3, 54,1, 58,77 , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,19523, 48,100, 52,2, 53,2, 54,1, 58,83 , 8,10856, 34,-8800, 35,-799, 36,3417, 38,-148, 40,33, 43,20813, 48,100, 52,2, 53,4, 54,1, 58,89 , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,22610, 48,100, 52,29, 53,5, 54,1, 58,106 , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,23385, 48,100, 52,30, 53,6, 54,1, 58,111 , 8,10856, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 43,32604, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 1 */ , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,12800, 48,67, 52,-43, 54,1, 58,75 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,14643, 48,67, 52,8, 53,1, 54,1, 58,81 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,16954, 48,67, 52,4, 53,3, 54,1, 58,77 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,19523, 48,67, 52,2, 53,2, 54,1, 58,83 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,20813, 48,67, 52,2, 53,4, 54,1, 58,89 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,22610, 48,67, 52,29, 53,5, 54,1, 58,106 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,23385, 48,67, 52,30, 53,6, 54,1, 58,111 , 8,14400, 9,75, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,0, 43,32604, 48,67, 52,-48, 53,7, 54,1, 58,111 /* Preset 2 */ , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,14336, 48,100, 52,-43, 54,1, 58,75 , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,16185, 48,100, 52,8, 53,1, 54,1, 58,81 , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,18496, 48,100, 52,4, 53,3, 54,1, 58,77 , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,21065, 48,100, 52,2, 53,2, 54,1, 58,83 , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,24147, 48,100, 52,29, 53,5, 54,1, 58,106 , 8,14400, 11,112, 26,-8856, 27,-8358, 28,-1586, 30,0, 34,-8800, 35,-799, 36,4386, 38,-148, 40,33, 41,1, 43,32607, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 3 */ , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,12800, 48,150, 52,-35, 54,1, 58,75 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,14643, 48,150, 52,16, 53,1, 54,1, 58,81 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,16954, 48,150, 52,11, 53,3, 54,1, 58,77 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,19523, 48,150, 52,10, 53,2, 54,1, 58,83 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,20813, 48,150, 52,10, 53,4, 54,1, 58,89 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,22610, 48,150, 52,36, 53,5, 54,1, 58,106 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,23385, 48,150, 52,38, 53,6, 54,1, 58,111 , 17,-287, 34,-8856, 35,-799, 36,4386, 38,-148, 40,33, 41,2, 43,32604, 48,150, 52,-40, 53,7, 54,1, 58,111 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,12800, 48,150, 52,50, 54,1, 58,76 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,14643, 48,150, 52,2, 53,1, 54,1, 58,81 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,17466, 48,150, 52,-3, 53,3, 54,1, 58,77 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,19525, 48,150, 52,-4, 53,2, 54,1, 58,83 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,20813, 48,150, 52,-4, 53,4, 54,1, 58,89 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,22610, 48,150, 52,22, 53,5, 54,1, 58,106 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,23385, 48,150, 52,24, 53,6, 54,1, 58,111 , 17,146, 35,-799, 36,4386, 38,-148, 40,33, 41,3, 43,32604, 48,150, 52,46, 53,7, 54,1, 58,112 /* Preset 4 */ , 8,11151, 15,384, 34,-8856, 36,-386, 37,496, 38,-667, 41,4, 43,12288, 48,200, 52,21, 53,138, 54,1, 58,65 , 8,11151, 15,384, 34,-8856, 36,-261, 37,475, 38,-667, 41,4, 43,15409, 48,200, 52,21, 53,138, 54,1, 58,65 , 8,11151, 15,384, 34,-8856, 36,1200, 37,496, 38,-667, 41,4, 43,20285, 48,200, 52,21, 53,138, 54,1, 58,65 , 8,11151, 15,384, 34,-8856, 36,-386, 37,496, 38,-667, 41,4, 43,26449, 48,200, 52,29, 53,8, 54,1, 58,82 , 8,14400, 9,190, 15,384, 34,-8856, 36,-386, 37,496, 38,-667, 41,4, 43,32616, 48,200, 52,-48, 53,7, 54,1, 58,111 , 15,419, 34,-8800, 36,3565, 38,-667, 41,5, 43,15360, 48,200, 52,29, 53,149, 54,1, 58,76 , 15,419, 34,-8800, 36,3565, 38,-667, 41,5, 43,25149, 48,200, 52,-21, 53,127, 54,1, 58,76 , 15,419, 34,-8800, 36,3565, 38,-667, 41,5, 43,32611, 48,200, 52,-48, 53,7, 54,1, 58,111 /* Preset 5 */ , 8,5074, 11,6412, 29,65, 30,1017, 34,-8800, 36,4301, 38,-949, 41,6, 43,26368, 48,110, 52,29, 53,8, 54,1, 58,82 , 8,5074, 11,6412, 29,65, 30,1017, 34,-8800, 36,4301, 38,-949, 41,6, 43,32616, 48,110, 52,-48, 53,7, 54,1, 58,111 /* Preset 6 */ , 8,14400, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,2400, 37,947, 38,91, 41,7, 43,26624, 48,315, 52,-45, 53,10, 54,1, 58,82 , 8,14400, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-12000, 36,-12000, 41,7, 43,32617, 48,315, 52,-48, 53,7, 58,111 , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,178, 43,16896, 48,112, 52,44, 53,71, 54,1, 58,78 , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,178, 43,27459, 48,112, 52,-31, 53,72, 54,1, 58,85 , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,178, 43,32620, 48,112, 52,-48, 53,7, 54,1, 58,111 /* Preset 7 */ , 8,8083, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,3393, 37,937, 38,-3986, 41,8, 43,26368, 48,150, 52,29, 53,9, 54,1, 58,82 , 8,8083, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-12000, 36,-12000, 41,8, 43,32616, 48,150, 52,-48, 53,7, 58,111 /* Preset 8 */ , 8,9027, 9,24, 34,-8800, 35,-4372, 36,3049, 38,575, 41,9, 43,24064, 48,100, 52,33, 53,123, 54,1, 58,73 , 8,9499, 34,-8800, 36,3049, 38,575, 41,10, 43,27136, 48,100, 52,-21, 53,130, 54,1, 58,84 , 8,9499, 34,-8800, 36,3049, 38,575, 41,10, 43,32619, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 9 */ , 8,5841, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,413, 37,149, 38,-2050, 41,11, 43,15104, 48,100, 52,11, 53,146, 58,52 , 8,5841, 11,3487, 27,-693, 28,330, 29,412, 34,-8800, 35,-2470, 36,413, 37,149, 38,-2050, 41,11, 43,18748, 48,100, 52,11, 53,146, 58,52 , 8,9617, 34,-8800, 36,3049, 38,1591, 41,12, 43,27904, 48,100, 52,32, 53,145, 54,1, 58,88 , 8,9617, 34,-8800, 36,3049, 38,1591, 41,12, 43,32622, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 10 */ , 9,190, 11,3487, 27,-693, 28,330, 29,412, 34,-7656, 35,-2470, 36,1017, 37,937, 38,1035, 41,13, 43,15360, 48,120, 52,-21, 53,127, 54,1, 58,76 , 9,190, 11,3487, 27,-693, 28,330, 29,412, 34,-7656, 35,-2470, 36,1017, 37,937, 38,1035, 41,13, 43,25149, 48,120, 52,-21, 53,127, 54,1, 58,76 , 9,190, 11,3487, 27,-693, 28,330, 29,412, 34,-7656, 35,-2470, 36,1017, 37,937, 38,1035, 41,13, 43,32611, 48,120, 52,-48, 53,7, 54,1, 58,111 , 8,10325, 9,136, 11,7087, 30,2311, 33,-5572, 34,-5053, 36,813, 37,769, 38,213, 41,14, 43,15360, 48,120, 52,-21, 53,131, 54,1, 58,64 , 8,10325, 9,136, 11,7087, 30,2311, 33,-5572, 34,-8590, 36,813, 37,769, 38,213, 41,14, 43,22077, 48,120, 52,-21, 53,131, 54,1, 58,64 , 8,10325, 9,136, 11,7087, 30,2311, 33,-5572, 34,-8856, 36,813, 37,769, 38,213, 41,14, 43,32599, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 11 */ , 8,4779, 11,7087, 13,20, 15,250, 22,-646, 26,-8856, 27,-7972, 28,-386, 29,412, 30,1365, 34,-8856, 36,3049, 38,688, 41,15, 43,24064, 48,120, 52,24, 53,123, 54,1, 58,73 , 8,4779, 11,7087, 13,20, 15,250, 22,-646, 26,-8856, 27,-7972, 28,-386, 29,412, 30,1365, 34,-8856, 36,1544, 38,688, 41,15, 43,24064, 48,120, 52,24, 53,123, 54,1, 58,73 , 8,4779, 9,190, 11,7087, 13,20, 15,250, 22,-646, 26,-8856, 27,-7972, 28,-386, 29,412, 30,1365, 34,-8856, 36,4301, 38,688, 41,15, 43,32607, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 12 */ , 11,7087, 15,250, 26,-8856, 27,-7972, 30,1365, 34,-6772, 35,-3986, 36,2013, 37,989, 38,811, 41,16, 43,29440, 48,50, 52,29, 53,125, 54,1, 58,94 , 11,7087, 15,250, 26,-8856, 27,-7972, 30,1365, 34,-6772, 35,-3986, 36,2013, 37,989, 38,811, 41,16, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 13 */ , 34,-8800, 36,1544, 38,-24, 41,17, 48,67, 52,-45, 53,121, 58,98 , 34,-8800, 36,1544, 38,-24, 41,17, 43,32633, 48,67, 52,-48, 53,7, 58,111 /* Preset 14 */ , 8,10266, 34,-8856, 35,-1003, 36,4182, 38,1699, 41,18, 48,50, 52,50, 53,130, 54,1, 58,109 /* Preset 15 */ , 34,-8800, 35,-1132, 36,2198, 38,1145, 41,19, 43,29184, 48,150, 52,-32, 53,68, 54,1, 58,92 , 34,-8800, 35,-1132, 36,2198, 38,1145, 41,19, 43,32627, 48,150, 52,-48, 53,7, 54,1, 58,111 /* Preset 16 */ , 8,9617, 34,-8856, 35,-2968, 36,3784, 37,0, 38,-2786, 41,20, 43,22016, 48,217, 52,-15, 53,134, 54,1, 58,64 , 8,9617, 34,-8856, 35,-2968, 36,3784, 37,0, 38,-2786, 41,20, 43,32599, 48,217, 52,-48, 53,7, 54,1, 58,111 , 8,9617, 34,-8856, 35,241, 36,4037, 37,0, 38,-2786, 41,21, 43,28160, 48,217, 52,-15, 53,131, 54,1, 58,88 , 8,9617, 34,-8856, 35,-2968, 36,3784, 37,0, 38,-2786, 41,21, 43,32623, 48,217, 52,-48, 53,7, 54,1, 58,111 /* Preset 17 */ , 2,-1, 3,-1, 8,7906, 11,7087, 29,811, 34,-8800, 36,-1586, 37,0, 38,-2786, 41,22, 43,19200, 48,90, 52,-37, 53,132, 54,1, 58,91 , 2,-1, 3,-1, 8,7906, 11,7087, 29,811, 34,-8800, 36,-1586, 37,0, 38,-2786, 41,22, 43,31052, 48,90, 52,30, 53,133, 54,1, 58,100 , 8,7906, 11,7087, 29,811, 34,-8800, 36,-1586, 37,0, 38,-2786, 41,22, 43,32634, 48,90, 52,-48, 53,7, 54,1, 58,111 /* Preset 18 */ , 2,-1, 3,-1, 6,28, 8,7906, 11,7087, 15,419, 17,75, 24,-1374, 29,811, 34,-8800, 36,-1270, 37,0, 38,-2786, 41,23, 43,19200, 48,187, 52,-35, 53,132, 54,1, 58,91 , 6,28, 8,7906, 11,7087, 15,419, 17,75, 24,-1374, 29,811, 34,-8800, 36,-1270, 37,0, 38,-2786, 41,23, 43,31052, 48,187, 52,32, 53,133, 54,1, 58,100 , 6,28, 8,7906, 11,7087, 15,419, 17,75, 24,-1374, 29,811, 34,-8800, 36,-1270, 37,0, 38,-2786, 41,23, 43,32634, 48,187, 52,-48, 53,7, 54,1, 58,111 , 9,118, 10,450, 13,65, 15,482, 22,-2921, 34,-8800, 35,241, 36,4037, 37,0, 38,-2786, 41,24, 43,29184, 48,250, 52,5, 53,43, 54,1, 58,93 , 9,118, 10,450, 13,65, 15,482, 22,-2921, 34,-8800, 35,241, 36,4037, 37,0, 38,-2786, 41,24, 43,32627, 48,250, 52,-48, 53,7, 54,1, 58,111 /* Preset 19 */ , 8,14400, 13,-3, 22,-7925, 34,-1603, 37,0, 38,-667, 41,25, 43,28160, 48,77, 52,-20, 53,131, 54,1, 58,88 , 8,14400, 13,-3, 22,-7925, 34,-1603, 37,0, 38,-667, 41,25, 43,32623, 48,77, 52,-48, 53,7, 54,1, 58,111 , 7,-8, 8,10325, 9,30, 11,-112, 27,-6772, 30,4400, 34,-6772, 37,0, 38,-667, 41,26, 43,15360, 48,177, 52,-28, 53,24, 54,1, 58,65 , 7,-8, 8,10325, 9,30, 11,-112, 27,-6772, 30,4400, 34,-6772, 37,0, 38,-667, 41,26, 43,22333, 48,177, 52,-28, 53,24, 54,1, 58,65 , 7,-8, 8,10325, 9,190, 11,-112, 27,-6772, 30,4400, 34,-2911, 37,0, 38,-667, 41,26, 43,32600, 48,177, 52,-48, 53,7, 54,1, 58,111 /* Preset 20 */ , 2,-1, 3,-1, 34,-6530, 37,0, 38,-3986, 41,27, 43,21504, 48,157, 52,33, 53,46, 54,1, 58,92 , 2,-1, 3,-1, 34,-6530, 37,0, 38,-3986, 41,27, 43,25173, 48,157, 52,-15, 53,131, 54,1, 58,76 , 2,-1, 3,-1, 34,-6530, 37,0, 38,-3986, 41,27, 43,32611, 48,157, 52,-48, 53,7, 54,1, 58,111 , 34,-1382, 37,0, 38,-1224, 41,28, 43,28160, 48,157, 52,-20, 53,134, 54,1, 58,88 , 34,-1382, 37,0, 38,-1224, 41,28, 43,32623, 48,157, 52,-48, 53,7, 54,1, 58,111 /* Preset 21 */ , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,14080, 48,200, 52,-46, 53,87, 54,1, 58,76 , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,16952, 48,200, 52,-1, 53,88, 54,1, 58,81 , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,28483, 48,200, 52,15, 53,89, 54,1, 58,90 , 13,16, 22,-194, 34,-8800, 37,0, 38,-1378, 41,29, 43,32624, 48,200, 52,-48, 53,7, 54,1, 58,111 , 6,9, 24,-1297, 34,-955, 37,0, 38,-3986, 41,179, 43,25088, 48,200, 51,12, 52,-18, 53,79, 54,1, 58,76 , 6,9, 24,-1297, 34,-955, 37,0, 38,-3986, 41,179, 43,32611, 48,200, 51,12, 52,-46, 53,7, 54,1, 58,111 /* Preset 22 */ , 2,-1, 3,-1, 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,30, 43,28928, 48,105, 52,33, 53,46, 54,1, 58,92 , 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,30, 43,32626, 48,105, 52,-48, 53,7, 54,1, 58,111 /* Preset 23 */ , 2,-1, 3,-1, 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,31, 43,15104, 48,220, 52,-46, 53,87, 54,1, 58,76 , 2,-1, 3,-1, 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,31, 43,28476, 48,220, 52,15, 53,89, 54,1, 58,90 , 13,16, 22,-498, 34,-8800, 37,0, 38,-3986, 41,31, 43,32624, 48,220, 52,-48, 53,7, 54,1, 58,111 , 34,-955, 37,0, 38,-3986, 41,32, 43,25088, 48,220, 52,-20, 53,79, 54,1, 58,76 , 34,-955, 37,0, 38,-3986, 41,32, 43,32611, 48,220, 52,-48, 53,7, 54,1, 58,111 /* Preset 24 */ , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,14336, 48,100, 52,46, 53,80, 54,1, 58,70 , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,19769, 48,100, 52,-1, 53,81, 54,1, 58,77 , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,24910, 48,100, 52,32, 53,75, 54,1, 58,76 , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,4301, 38,-3986, 41,33, 43,32610, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 25 */ , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,3417, 38,-3986, 41,34, 43,18432, 48,135, 52,47, 53,74, 54,1, 58,74 , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,3417, 38,-3986, 41,34, 43,24905, 48,135, 52,32, 53,75, 54,1, 58,76 , 5,-8, 6,-8, 13,-1, 21,-3670, 22,-698, 24,1701, 34,-8800, 36,3417, 38,-3986, 41,34, 43,32610, 48,135, 52,-48, 53,7, 54,1, 58,111 /* Preset 26 */ , 6,-8, 8,9263, 13,-1, 21,-3670, 22,-698, 24,-837, 34,-8800, 36,2854, 37,895, 38,-3986, 41,35, 43,24576, 48,150, 53,76, 54,1, 58,74 , 6,-8, 8,9263, 13,-1, 21,-3670, 22,-698, 24,-837, 34,-8800, 36,2854, 37,895, 38,-3986, 41,35, 43,32609, 48,150, 52,-48, 53,7, 54,1, 58,111 , 8,10089, 13,-1, 22,-837, 34,-8800, 35,-1132, 36,3417, 37,601, 38,-3986, 41,36, 43,27904, 48,150, 52,-18, 53,82, 54,1, 58,87 , 8,10089, 13,-1, 22,-837, 34,-8800, 35,-1132, 36,3417, 37,601, 38,-3986, 41,36, 43,32622, 48,150, 52,-48, 53,7, 54,1, 58,111 /* Preset 27 */ , 15,462, 34,-8800, 35,-3172, 36,2626, 38,-3986, 41,37, 43,24320, 48,180, 52,7, 53,76, 54,1, 58,74 , 15,462, 34,-8800, 37,0, 38,-3986, 41,37, 43,32608, 48,180, 52,-4, 53,86, 54,1, 58,91 /* Preset 28 */ , 5,9, 8,14400, 22,-753, 34,-8800, 36,2941, 38,-3986, 41,38, 43,25088, 52,-46, 53,77, 54,1, 58,76 , 5,9, 8,14400, 22,-753, 34,-8800, 36,2941, 38,-3986, 41,38, 43,32611, 52,-48, 53,7, 54,1, 58,111 /* Preset 29 */ , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,15872, 48,202, 52,-45, 53,84, 54,1, 58,72 , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,16959, 48,202, 52,-35, 53,85, 54,1, 58,79 , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,26947, 48,202, 52,38, 53,83, 54,1, 58,84 , 34,-8800, 36,3667, 37,34, 38,-3986, 41,39, 43,32618, 48,202, 52,-48, 53,7, 54,1, 58,111 , 34,-8800, 35,-1132, 36,3667, 38,-3986, 41,40, 43,27904, 48,202, 52,-18, 53,82, 54,1, 58,87 , 34,-8800, 35,-1132, 36,3667, 38,-3986, 41,40, 43,32622, 48,202, 52,-48, 53,7, 54,1, 58,111 /* Preset 30 */ , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,15872, 48,150, 52,-45, 53,84, 54,1, 58,72 , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,16959, 48,150, 52,-35, 53,85, 54,1, 58,79 , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,18499, 48,150, 52,38, 53,83, 54,1, 58,84 , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,29001, 48,150, 52,-4, 53,86, 54,1, 58,91 , 34,-8800, 36,5151, 37,916, 38,-3986, 41,41, 43,32626, 48,150, 52,-48, 53,7, 54,1, 58,111 /* Preset 31 */ , 2,-1, 3,-1, 34,-8800, 35,-1344, 36,5151, 37,916, 38,-2420, 41,42, 43,29696, 48,50, 52,8, 53,78, 54,1, 58,85 , 34,-8800, 35,-1344, 36,5151, 37,916, 38,-2420, 41,42, 43,32629, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 32 */ , 34,-8800, 36,2837, 38,-1378, 41,43, 43,22272, 48,100, 52,44, 53,61, 54,1, 58,66 , 34,-8800, 36,2521, 38,1591, 41,43, 43,28248, 48,100, 52,25, 53,69, 54,1, 58,89 , 34,-8800, 36,2837, 38,-1378, 41,43, 43,32623, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 33 */ , 8,8024, 11,7087, 28,-2786, 34,-8800, 36,2521, 38,-1378, 41,44, 43,21504, 48,157, 53,62, 54,1, 58,62 , 8,8024, 11,7087, 28,-2786, 34,-8800, 36,2521, 38,1591, 41,44, 43,28245, 48,157, 52,25, 53,69, 54,1, 58,89 , 8,8024, 11,7087, 28,-2786, 34,-8800, 36,2521, 38,-1378, 41,44, 43,32623, 48,157, 52,-48, 53,7, 54,1, 58,111 /* Preset 34 */ , 8,7552, 9,18, 11,7087, 28,0, 34,-8800, 36,5254, 37,212, 38,-1224, 41,45, 43,22784, 48,120, 52,-20, 53,67, 54,1, 58,67 , 8,7552, 9,18, 11,7087, 28,0, 34,-8800, 36,5254, 37,212, 38,-1224, 41,45, 43,28250, 48,120, 52,25, 53,69, 54,1, 58,89 , 8,7552, 9,18, 11,7087, 28,0, 34,-8800, 36,5254, 37,212, 38,-1224, 41,45, 43,32623, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 35 */ , 8,7434, 9,18, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-667, 41,46, 43,20736, 48,75, 52,33, 53,63, 54,1, 58,60 , 8,7434, 9,18, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-667, 41,46, 43,28242, 48,75, 52,25, 53,69, 54,1, 58,89 , 8,7434, 9,18, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-667, 41,46, 43,32623, 48,75, 52,-48, 53,7, 54,1, 58,111 /* Preset 36 */ , 2,-1, 3,-1, 8,8201, 11,7087, 28,-1586, 34,-8800, 35,-3172, 36,6000, 37,979, 38,-3067, 41,47, 43,18432, 48,120, 52,-10, 53,64, 54,1, 58,50 , 8,7139, 11,4050, 28,-1586, 34,-8800, 35,-3172, 36,6000, 37,979, 38,-3067, 41,47, 43,28233, 48,120, 52,29, 53,9, 54,1, 58,82 , 8,8201, 11,7087, 28,-1586, 34,-8800, 35,-3172, 36,6000, 37,979, 38,-3067, 41,47, 43,32623, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 37 */ , 8,8791, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-3343, 41,48, 43,22528, 48,152, 52,25, 53,65, 54,1, 58,67 , 8,8791, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-3343, 41,48, 43,28249, 48,152, 52,25, 53,69, 54,1, 58,89 , 8,8791, 11,7087, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-3343, 41,48, 43,32623, 48,152, 52,-48, 53,7, 54,1, 58,111 /* Preset 38 */ , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,16640, 48,70, 52,4, 53,66, 54,1, 58,44 , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,27970, 48,70, 52,-1, 53,128, 54,1, 58,87 , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,32622, 48,70, 52,-48, 53,7, 54,1, 58,111 , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,26178, 48,70, 52,2, 53,135, 54,1, 58,81 , 8,4956, 11,6412, 27,-6772, 28,-2786, 34,-8800, 36,6000, 37,979, 38,-2821, 41,49, 43,32615, 48,70, 52,-48, 53,7, 54,1, 58,111 /* Preset 39 */ , 8,9145, 11,6412, 27,-6772, 28,-884, 34,-8800, 36,6000, 37,979, 38,-802, 41,50, 43,20736, 48,157, 52,35, 53,63, 54,1, 58,60 , 8,9145, 11,6412, 27,-6772, 28,-884, 34,-8800, 36,6000, 37,979, 38,-802, 41,50, 43,28242, 48,157, 52,25, 53,69, 54,1, 58,89 , 8,9145, 11,6412, 27,-6772, 28,-884, 34,-8800, 36,6000, 37,979, 38,-802, 41,50, 43,32623, 48,157, 52,-48, 53,7, 54,1, 58,111 , 8,8024, 9,63, 11,5287, 27,-6772, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-802, 41,51, 43,22784, 48,120, 52,-15, 53,67, 54,1, 58,67 , 8,8024, 9,63, 11,5287, 27,-6772, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-802, 41,51, 43,28250, 48,120, 52,25, 53,69, 54,1, 58,89 , 8,8024, 9,63, 11,5287, 27,-6772, 28,-1586, 34,-8800, 36,6000, 37,979, 38,-802, 41,51, 43,32623, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 40 */ , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,17920, 48,120, 52,30, 53,55, 54,1, 58,87 , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,19015, 48,120, 52,15, 53,56, 54,1, 58,90 , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,20043, 48,120, 52,-45, 53,57, 54,1, 58,94 , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,21071, 48,120, 52,24, 53,58, 54,1, 58,98 , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,31571, 48,120, 52,15, 53,59, 54,1, 58,102 , 5,19, 8,10561, 21,-2332, 22,-837, 34,-7972, 36,3975, 37,0, 38,-667, 41,52, 43,32636, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 41 */ , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-2803, 36,3975, 37,0, 38,-667, 41,53, 43,16640, 48,100, 52,30, 53,55, 54,1, 58,87 , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,17730, 48,100, 52,15, 53,56, 54,1, 58,90 , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,18758, 48,100, 52,-45, 53,57, 54,1, 58,94 , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,19786, 48,100, 52,24, 53,58, 54,1, 58,98 , 2,-1, 3,-1, 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,31566, 48,100, 52,15, 53,59, 54,1, 58,102 , 5,19, 21,-2332, 22,-837, 34,-6688, 36,3975, 37,0, 38,-667, 41,53, 43,32636, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 42 */ , 5,19, 21,-2332, 22,-837, 34,-2653, 37,0, 38,-542, 41,54, 43,13568, 48,120, 52,32, 53,52, 54,1, 58,76 , 5,19, 21,-2332, 22,-837, 34,-2653, 37,0, 38,-542, 41,54, 43,26934, 48,120, 52,38, 53,53, 54,1, 58,84 , 5,19, 21,-2332, 22,-837, 34,-2653, 37,0, 38,-542, 41,54, 43,32618, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 43 */ , 5,19, 21,-2332, 22,-837, 34,-8800, 37,0, 38,-667, 41,55, 43,21760, 48,140, 52,32, 53,54, 54,1, 58,64 , 5,19, 21,-2332, 22,-837, 34,-5447, 37,0, 38,-667, 41,55, 43,26966, 48,140, 52,38, 53,53, 54,1, 58,84 , 5,19, 21,-2332, 22,-837, 34,-8800, 37,0, 38,-667, 41,55, 43,32618, 48,140, 52,-48, 53,7, 54,1, 58,111 /* Preset 44 */ , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,15104, 48,67, 52,33, 53,48, 54,1, 58,74 , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,18492, 48,67, 52,50, 53,49, 54,1, 58,88 , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,29513, 48,67, 52,36, 53,50, 54,1, 58,94 , 5,19, 13,30, 21,-2332, 22,460, 34,-8800, 37,0, 38,-405, 41,56, 43,32628, 48,67, 52,-48, 53,7, 54,1, 58,111 /* Preset 45 */ , 5,-8, 13,-1, 21,-2332, 22,-837, 34,-8800, 36,1092, 38,213, 41,57, 43,29440, 48,80, 52,3, 53,60, 54,1, 58,91 , 5,-8, 13,-1, 21,-2332, 22,-837, 34,-8800, 36,1092, 38,213, 41,57, 43,32628, 48,80, 52,-41, 53,7, 54,1, 58,111 /* Preset 46 */ , 34,-8800, 36,2521, 38,1591, 41,58, 43,28160, 48,80, 52,25, 53,69, 54,1, 58,89 , 34,-8800, 36,2521, 38,1591, 41,58, 43,32623, 48,80, 52,-48, 53,7, 54,1, 58,111 /* Preset 47 */ , 34,-8856, 35,-1066, 36,2288, 38,1482, 41,59, 43,12032, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,2265, 38,1017, 41,59, 43,12336, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,2217, 38,-148, 41,59, 43,13105, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,2013, 38,813, 41,59, 43,14132, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,2118, 38,701, 41,59, 43,15160, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,2013, 38,582, 41,59, 43,18236, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,1654, 38,-148, 41,59, 43,25928, 48,127, 52,50, 53,112, 54,1, 58,80 , 34,-8856, 35,-1066, 36,2118, 38,-148, 41,59, 43,32614, 48,127, 52,-48, 53,7, 54,1, 58,111 /* Preset 48 */ , 8,9853, 34,-8800, 37,0, 38,-24, 41,60, 43,15104, 48,90, 52,29, 53,48, 54,1, 58,74 , 8,11033, 34,-8800, 37,0, 38,-24, 41,60, 43,18492, 48,90, 52,50, 53,49, 54,1, 58,88 , 8,11033, 34,-8800, 37,0, 38,-24, 41,60, 43,29513, 48,90, 52,36, 53,50, 54,1, 58,94 , 8,11033, 34,-8800, 37,0, 38,-24, 41,60, 43,32628, 48,90, 52,-48, 53,7, 54,1, 58,111 /* Preset 49 */ , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,15104, 48,100, 52,29, 53,48, 54,1, 58,74 , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,18492, 48,100, 52,50, 53,49, 54,1, 58,88 , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,29513, 48,100, 52,36, 53,50, 54,1, 58,94 , 8,11682, 34,-1500, 37,0, 38,1035, 41,61, 43,32628, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 50 */ , 34,-5152, 37,0, 38,338, 41,62, 43,29440, 48,75, 52,4, 53,51, 54,1, 58,94 , 34,-5152, 37,0, 38,338, 41,62, 43,32628, 48,75, 52,-48, 53,7, 54,1, 58,111 /* Preset 51 */ , 7,-130, 11,112, 30,2013, 34,-2266, 37,0, 38,1591, 41,63, 43,29440, 48,45, 52,8, 53,51, 54,1, 58,94 , 7,-130, 11,112, 30,2013, 34,-2266, 37,0, 38,1591, 41,63, 43,32628, 48,45, 52,-48, 53,7, 54,1, 58,111 , 8,7670, 9,100, 11,7087, 28,0, 29,811, 30,1782, 34,-2266, 37,0, 38,1591, 41,64, 43,29696, 48,52, 53,51, 54,1, 58,94 , 8,7670, 9,100, 11,7087, 28,0, 29,811, 30,1782, 34,-2266, 37,0, 38,1591, 41,64, 43,32629, 48,52, 52,-48, 53,7, 54,1, 58,111 /* Preset 52 */ , 34,-1684, 37,0, 38,213, 41,65, 43,30464, 48,40, 52,10, 53,142, 54,1, 58,98 , 34,-1684, 37,0, 38,213, 41,65, 43,32632, 48,40, 52,-48, 53,7, 54,1, 58,111 , 9,69, 34,-1684, 37,0, 38,213, 41,66, 43,27392, 48,40, 52,-28, 53,143, 54,1, 58,85 , 9,69, 34,-1684, 37,0, 38,213, 41,66, 43,32620, 48,40, 52,-48, 53,7, 54,1, 58,111 /* Preset 53 */ , 8,11505, 9,42, 34,-2968, 36,3462, 37,97, 38,-1079, 41,67, 43,23552, 48,100, 51,1, 52,-15, 53,43, 54,1, 58,70 , 8,11505, 9,42, 34,-2968, 36,3462, 37,97, 38,-1079, 41,67, 43,32605, 48,100, 51,1, 52,-48, 53,7, 54,1, 58,111 , 34,-8800, 36,3462, 37,191, 38,-1079, 41,68, 43,25856, 48,100, 52,-28, 53,147, 54,1, 58,79 , 34,-8800, 36,3462, 37,191, 38,-1079, 41,68, 43,32614, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 54 */ , 34,-11958, 37,34, 38,338, 41,69, 43,27392, 48,40, 52,-25, 53,143, 54,1, 58,85 , 34,-11958, 37,34, 38,338, 41,69, 43,32620, 48,40, 52,-48, 53,7, 54,1, 58,111 /* Preset 55 */ , 34,-8800, 36,-3986, 37,0, 38,1482, 41,70, 43,30464, 52,35, 53,124, 58,98 , 34,-8800, 37,0, 38,1482, 41,70, 43,32632, 52,-48, 53,7, 58,111 /* Preset 56 */ , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,16384, 48,52, 52,-43, 53,33, 54,1, 58,84 , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,17729, 48,52, 52,-20, 53,29, 54,1, 58,88 , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,19014, 48,52, 52,-1, 53,30, 54,1, 58,93 , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,20299, 48,52, 52,24, 53,31, 54,1, 58,98 , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,32080, 48,52, 52,-4, 53,32, 54,1, 58,103 , 5,9, 9,42, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,23, 38,-1079, 41,71, 43,32638, 48,52, 52,-48, 53,7, 54,1, 58,111 /* Preset 57 */ , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,13312, 48,50, 52,-7, 53,34, 54,1, 58,70 , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,15157, 48,50, 52,33, 53,35, 54,1, 58,80 , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,16444, 48,50, 52,-3, 53,36, 54,1, 58,84 , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,28481, 48,50, 52,16, 53,37, 54,1, 58,90 , 5,9, 8,5251, 11,7087, 21,-2332, 22,-837, 26,-8856, 28,3841, 29,496, 30,3488, 34,-8856, 36,4301, 37,23, 38,-1079, 41,72, 43,32624, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 58 */ , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-1224, 41,73, 43,22016, 48,50, 52,38, 53,38, 54,1, 58,65 , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-1224, 41,73, 43,28503, 48,50, 52,16, 53,37, 54,1, 58,90 , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-1224, 41,73, 43,32624, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 59 */ , 5,9, 8,5251, 11,6862, 21,-2332, 22,-837, 26,-8856, 28,4054, 29,496, 30,3488, 34,-8856, 36,4301, 37,55, 38,-1224, 41,74, 43,16640, 48,82, 52,44, 53,39, 54,1, 58,78 , 5,9, 8,5251, 11,6862, 21,-2332, 22,-837, 26,-8856, 28,4054, 29,496, 30,3488, 34,-8856, 36,4301, 37,55, 38,-1224, 41,74, 43,28738, 48,82, 52,-40, 53,40, 54,1, 58,90 , 5,9, 8,5251, 11,6862, 21,-2332, 22,-837, 26,-8856, 28,4054, 29,496, 30,3488, 34,-8856, 36,4301, 37,55, 38,-1224, 41,74, 43,32625, 48,82, 52,-48, 53,7, 54,1, 58,111 /* Preset 60 */ , 2,1, 3,1, 11,6862, 28,4054, 34,-8590, 36,4301, 37,149, 38,-24, 41,75, 43,28416, 48,30, 52,15, 53,22, 54,1, 58,90 , 2,1, 3,1, 11,6862, 28,4054, 34,-8590, 36,4301, 37,149, 38,-24, 41,75, 43,32624, 48,30, 52,-48, 53,7, 54,1, 58,111 /* Preset 61 */ , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-949, 41,76, 43,18176, 48,120, 52,-35, 53,27, 54,1, 58,77 , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-949, 41,76, 43,29768, 48,120, 52,47, 53,28, 54,1, 58,95 , 5,9, 11,6862, 21,-2332, 22,-837, 28,4054, 34,-8856, 36,4301, 37,55, 38,-949, 41,76, 43,32629, 48,120, 52,-48, 53,7, 54,1, 58,111 , 5,9, 11,6862, 21,-2400, 22,-926, 28,4054, 33,-6772, 34,-8856, 36,4301, 37,55, 38,-949, 41,77, 43,18176, 48,120, 52,-26, 53,27, 54,1, 58,77 , 5,9, 11,6862, 21,-2400, 22,-926, 28,4054, 33,-6772, 34,-8856, 36,4301, 37,55, 38,-949, 41,77, 43,29768, 48,120, 52,-43, 53,28, 54,1, 58,94 , 5,9, 11,6862, 21,-2400, 22,-926, 28,4054, 33,-6772, 34,-8856, 36,4301, 37,55, 38,-949, 41,77, 43,32629, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 62 */ , 8,9971, 9,66, 11,7087, 27,-4372, 28,4054, 30,2919, 34,-8856, 36,4301, 37,55, 38,-1224, 41,78, 43,27904, 48,30, 53,128, 54,1, 58,87 , 8,9971, 9,66, 11,7087, 27,-4372, 28,4054, 30,2919, 34,-8856, 36,4301, 37,55, 38,-1224, 41,78, 43,32622, 48,30, 52,-48, 53,7, 54,1, 58,111 /* Preset 63 */ , 8,6195, 9,21, 11,7087, 27,-7972, 28,4054, 29,989, 30,2641, 34,-8856, 36,4301, 37,0, 38,-1079, 41,79, 43,27648, 48,30, 52,2, 53,128, 54,1, 58,87 , 8,6195, 9,21, 11,7087, 27,-7972, 28,4054, 29,989, 30,2641, 34,-8856, 36,4301, 37,0, 38,-1079, 41,79, 43,32621, 48,30, 52,-48, 53,7, 54,1, 58,111 /* Preset 64 */ , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,14336, 48,30, 52,36, 53,11, 54,1, 58,71 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,14905, 48,30, 52,-45, 53,12, 54,1, 58,74 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,16699, 48,30, 52,5, 53,13, 54,1, 58,76 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,18498, 48,30, 52,29, 53,14, 54,1, 58,82 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,19529, 48,30, 52,-3, 53,15, 54,1, 58,84 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,22093, 48,30, 52,-4, 53,16, 54,1, 58,91 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,29527, 48,30, 52,29, 53,17, 54,1, 58,94 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,86, 38,-3986, 41,80, 43,32628, 48,30, 52,-48, 53,7, 54,1, 58,111 /* Preset 65 */ , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,13568, 48,70, 52,36, 53,11, 54,1, 58,71 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,14646, 48,70, 52,-45, 53,12, 54,1, 58,74 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,15930, 48,70, 52,5, 53,13, 54,1, 58,76 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,17727, 48,70, 52,29, 53,14, 54,1, 58,82 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,18758, 48,70, 52,-3, 53,15, 54,1, 58,84 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,20810, 48,70, 52,-4, 53,16, 54,1, 58,91 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,29522, 48,70, 52,29, 53,17, 54,1, 58,94 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,81, 43,32628, 48,70, 52,-48, 53,7, 54,1, 58,111 /* Preset 66 */ , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,13056, 48,79, 52,36, 53,11, 54,1, 58,71 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,13876, 48,79, 52,-45, 53,12, 54,1, 58,74 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,14903, 48,79, 52,5, 53,13, 54,1, 58,76 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,16443, 48,79, 52,29, 53,14, 54,1, 58,82 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,17473, 48,79, 52,-3, 53,15, 54,1, 58,84 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,19013, 48,79, 52,-4, 53,16, 54,1, 58,91 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,29515, 48,79, 52,29, 53,17, 54,1, 58,94 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,44, 38,-3986, 41,82, 43,32628, 48,79, 52,-48, 53,7, 54,1, 58,111 /* Preset 67 */ , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,13056, 48,50, 52,-45, 53,12, 54,1, 58,74 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,14388, 48,50, 52,5, 53,13, 54,1, 58,76 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,15161, 48,50, 52,29, 53,14, 54,1, 58,82 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,16444, 48,50, 52,-3, 53,15, 54,1, 58,84 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,17473, 48,50, 52,-4, 53,16, 54,1, 58,91 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,29509, 48,50, 52,29, 53,17, 54,1, 58,94 , 5,9, 21,-2332, 22,-837, 34,-8856, 37,55, 38,-3986, 41,83, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 68 */ , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,16128, 48,75, 52,33, 53,18, 54,1, 58,80 , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,17472, 48,75, 52,38, 53,19, 54,1, 58,84 , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,27973, 48,75, 52,32, 53,20, 54,1, 58,88 , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,84, 43,32622, 48,75, 52,-48, 53,7, 54,1, 58,111 /* Preset 69 */ , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,85, 43,25856, 48,62, 52,-35, 53,21, 54,1, 58,79 , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,85, 43,32614, 48,62, 52,-48, 53,7, 58,111 /* Preset 70 */ , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,86, 43,22528, 48,62, 52,41, 53,23, 54,1, 58,67 , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,86, 43,25945, 48,62, 52,-35, 53,21, 54,1, 58,79 , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,86, 43,32614, 48,62, 52,-48, 53,7, 54,1, 58,111 /* Preset 71 */ , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,87, 43,17664, 48,62, 53,25, 54,1, 58,74 , 2,-1, 3,-1, 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,87, 43,25926, 48,62, 52,49, 53,26, 54,1, 58,80 , 5,9, 21,-2332, 22,-837, 34,-8800, 37,55, 38,-3986, 41,87, 43,32614, 48,62, 52,-48, 53,7, 54,1, 58,111 /* Preset 72 */ , 5,9, 21,-2332, 22,-837, 34,-8800, 36,2941, 37,86, 38,-3986, 41,88, 43,28416, 48,90, 52,-28, 53,24, 54,1, 58,89 , 5,9, 21,-2332, 22,-837, 34,-8800, 36,2941, 37,86, 38,-3986, 41,88, 43,32624, 48,90, 52,-48, 53,7, 54,1, 58,111 , 2,-3, 3,-3, 8,9853, 34,-3151, 36,4280, 37,86, 38,-3986, 41,89, 43,28928, 48,90, 52,33, 53,41, 54,1, 58,92 , 8,9853, 34,-3151, 36,4280, 37,86, 38,-3986, 41,89, 43,32626, 48,90, 52,-48, 53,7, 54,1, 58,111 /* Preset 73 */ , 5,9, 9,106, 21,-2332, 22,-837, 34,-4899, 35,-3172, 36,3049, 37,34, 38,-3986, 41,90, 43,28416, 52,-28, 53,24, 54,1, 58,89 , 5,9, 9,106, 21,-2332, 22,-837, 34,-4899, 35,-3172, 36,3049, 37,34, 38,-3986, 41,90, 43,32624, 52,-48, 53,7, 54,1, 58,111 , 9,97, 34,-8800, 37,34, 38,-3986, 41,91, 43,26368, 48,240, 52,-1, 53,43, 54,1, 58,81 , 9,97, 34,-8800, 37,34, 38,-3986, 41,91, 43,32616, 48,240, 52,-48, 53,7, 54,1, 58,111 /* Preset 74 */ , 2,-3, 3,-3, 5,9, 21,-2332, 22,-837, 34,-8856, 36,4280, 37,34, 38,-3986, 41,92, 43,28928, 48,52, 52,33, 53,41, 54,1, 58,92 , 5,9, 21,-2332, 22,-837, 34,-8856, 36,4280, 37,34, 38,-3986, 41,92, 43,32626, 48,52, 52,-48, 53,7, 54,1, 58,111 /* Preset 75 */ , 34,-8856, 36,4077, 37,34, 38,-3986, 41,93, 43,26368, 48,142, 52,-1, 53,43, 54,1, 58,81 , 34,-8856, 36,4077, 37,34, 38,-3986, 41,93, 43,32616, 48,142, 52,-48, 53,7, 54,1, 58,111 , 2,-3, 3,-3, 34,-8856, 36,3462, 37,34, 38,-3986, 41,94, 43,28928, 48,142, 52,40, 53,41, 54,1, 58,92 , 34,-8856, 36,3462, 37,34, 38,-3986, 41,94, 43,32626, 48,142, 52,-48, 53,7, 54,1, 58,111 /* Preset 76 */ , 34,-8800, 36,1317, 37,0, 38,-3986, 41,95, 43,23296, 48,180, 52,38, 53,42, 58,70 , 34,-8800, 36,1317, 37,0, 38,-3986, 41,95, 43,32604, 48,180, 52,-48, 53,7, 58,111 , 34,-8856, 36,4077, 37,0, 38,-3986, 41,96, 43,26368, 48,180, 52,-7, 53,43, 54,1, 58,81 , 34,-8856, 36,4077, 37,0, 38,-3986, 41,96, 43,32616, 48,180, 52,-48, 53,7, 54,1, 58,111 /* Preset 77 */ , 34,-8800, 36,2521, 37,13, 38,-3986, 41,97, 43,26368, 48,180, 52,-7, 53,43, 54,1, 58,81 , 34,-8800, 36,2521, 37,13, 38,-3986, 41,97, 43,32616, 48,180, 52,-48, 53,7, 54,1, 58,111 /* Preset 78 */ , 5,9, 21,-2203, 22,-1019, 34,-4870, 37,13, 38,-3986, 41,98, 43,27392, 48,67, 52,24, 53,44, 54,1, 58,86 , 5,9, 21,-2203, 22,-1019, 34,-4870, 37,13, 38,-3986, 41,98, 43,32620, 48,67, 52,-48, 53,7, 54,1, 58,111 /* Preset 79 */ , 5,9, 21,-2203, 22,-1019, 34,-8800, 37,23, 38,-3986, 41,99, 43,27392, 48,52, 52,24, 53,44, 54,1, 58,86 , 5,9, 21,-2203, 22,-1019, 34,-8800, 37,23, 38,-3986, 41,99, 43,32620, 48,52, 52,-48, 53,7, 54,1, 58,111 /* Preset 80 */ , 2,-3, 3,-3, 34,-11958, 37,23, 38,-3986, 41,101, 43,25856, 48,180, 52,-32, 53,129, 54,1, 58,79 , 34,-11958, 37,23, 38,-3986, 41,101, 43,32614, 48,180, 52,-48, 53,7, 54,1, 58,111 , 2,-3, 3,-3, 34,-11958, 37,23, 38,-3986, 41,102, 43,25856, 48,180, 52,-39, 53,129, 54,1, 58,79 , 34,-11958, 37,23, 38,-3986, 41,102, 43,32614, 48,180, 52,-48, 53,7, 54,1, 58,111 /* Preset 81 */ , 8,10325, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,103, 43,27904, 48,60, 52,-1, 53,128, 54,1, 58,87 , 8,10325, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,103, 43,32622, 48,60, 52,-48, 53,7, 54,1, 58,111 , 8,10915, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,104, 43,26112, 48,120, 52,2, 53,135, 54,1, 58,81 , 8,10915, 9,81, 11,7087, 28,-1586, 34,-11958, 37,23, 38,-3986, 41,104, 43,32615, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 82 */ , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,180, 43,23296, 48,50, 52,38, 53,42, 58,70 , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,180, 43,32604, 48,50, 52,-48, 53,7, 58,111 , 2,-3, 3,-3, 34,-8856, 37,23, 38,-3986, 41,106, 43,25856, 48,135, 52,-32, 53,129, 54,1, 58,79 , 34,-8856, 37,23, 38,-3986, 41,106, 43,32614, 48,135, 52,-48, 53,7, 54,1, 58,111 /* Preset 83 */ , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,105, 43,23296, 48,180, 52,38, 53,42, 58,70 , 15,466, 30,813, 34,-11958, 36,1317, 37,23, 38,-3986, 41,105, 43,32604, 48,180, 52,-48, 53,7, 58,111 , 7,919, 8,4602, 9,33, 11,4612, 15,497, 26,-5407, 27,413, 28,6000, 29,0, 30,2013, 34,-8856, 37,23, 38,-3986, 41,107, 43,26112, 48,82, 51,-9, 52,2, 53,135, 54,1, 58,81 , 7,919, 8,4602, 9,33, 11,4612, 15,497, 26,-5407, 27,413, 28,6000, 29,0, 30,2013, 34,-8856, 37,23, 38,-3986, 41,107, 43,32615, 48,82, 51,-9, 52,-48, 53,7, 54,1, 58,111 /* Preset 84 */ , 34,-8800, 37,23, 38,-3986, 41,108, 43,27648, 48,135, 52,10, 53,128, 54,1, 58,87 , 34,-8800, 37,23, 38,-3986, 41,108, 43,32621, 48,135, 52,-48, 53,7, 54,1, 58,111 , 7,-149, 29,580, 34,-8800, 37,23, 38,-3986, 41,109, 43,26112, 48,277, 51,-1, 52,-15, 53,9, 54,1, 58,80 , 7,-149, 29,580, 34,-8800, 37,23, 38,-3986, 41,109, 43,32615, 48,277, 51,-1, 52,-24, 53,7, 54,1, 58,111 /* Preset 85 */ , 5,47, 15,497, 22,-78, 34,-6772, 36,4077, 37,23, 38,-3986, 41,110, 43,26368, 48,82, 52,-1, 53,43, 54,1, 58,81 , 5,47, 15,497, 22,-78, 34,-6772, 36,4077, 37,23, 38,-3986, 41,110, 43,32616, 48,82, 52,-48, 53,7, 54,1, 58,111 , 5,-8, 6,9, 9,33, 15,497, 22,-42, 24,29, 34,-8800, 37,23, 38,-3986, 41,111, 43,30464, 48,82, 52,5, 53,142, 54,1, 58,98 , 5,-8, 6,9, 9,33, 15,497, 22,-42, 24,29, 34,-8800, 37,23, 38,-3986, 41,111, 43,32632, 48,82, 52,-48, 53,7, 54,1, 58,111 /* Preset 86 */ , 8,4484, 9,150, 11,7087, 15,435, 28,1365, 29,727, 30,4400, 34,-6772, 36,3770, 37,23, 38,-3986, 41,112, 43,27904, 48,30, 52,-1, 53,128, 54,1, 58,87 , 8,4484, 9,150, 11,7087, 15,435, 28,1365, 29,727, 30,4400, 34,-6772, 36,3770, 37,23, 38,-3986, 41,112, 43,32622, 48,30, 52,-48, 53,7, 54,1, 58,111 , 8,4602, 9,190, 11,7087, 15,497, 28,1515, 29,706, 30,4400, 34,-8800, 37,23, 38,-3986, 41,113, 43,27392, 48,30, 52,2, 53,135, 54,1, 58,86 , 8,4602, 9,190, 11,7087, 15,497, 28,1515, 29,706, 30,4400, 34,-8800, 37,23, 38,-3986, 41,113, 43,32620, 48,30, 52,-48, 53,7, 54,1, 58,111 /* Preset 87 */ , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,16640, 48,50, 52,8, 53,66, 54,1, 58,44 , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,27970, 48,50, 52,-1, 53,128, 54,1, 58,87 , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,32622, 48,50, 52,-48, 53,7, 54,1, 58,111 , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,26178, 48,50, 52,2, 53,135, 54,1, 58,81 , 8,4956, 9,36, 11,5175, 15,497, 21,-2084, 22,-780, 28,0, 29,601, 30,1365, 34,-8856, 37,23, 38,-3986, 41,114, 43,32615, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 88 */ , 8,11328, 15,466, 34,-2653, 37,23, 38,688, 41,115, 43,29440, 48,60, 52,13, 53,51, 54,1, 58,94 , 8,11328, 15,466, 34,-2653, 37,23, 38,688, 41,115, 43,32628, 48,60, 52,-48, 53,7, 54,1, 58,111 , 8,9263, 9,15, 11,2362, 15,482, 28,1654, 30,2484, 34,-8800, 36,3153, 38,688, 41,116, 43,26368, 48,82, 52,29, 53,8, 54,1, 58,82 , 8,9263, 9,15, 11,2362, 15,482, 28,1654, 30,2484, 34,-8800, 36,3153, 38,688, 41,116, 43,32616, 48,82, 52,-48, 53,7, 54,1, 58,111 /* Preset 89 */ , 8,8555, 15,466, 34,-500, 37,23, 38,1482, 41,117, 43,29440, 48,60, 52,10, 53,51, 54,1, 58,94 , 8,8555, 15,466, 34,-500, 37,23, 38,1482, 41,117, 43,32628, 48,60, 52,-48, 53,7, 54,1, 58,111 /* Preset 90 */ , 7,-243, 8,11505, 9,9, 15,466, 26,-6772, 34,-8800, 37,23, 38,338, 41,118, 43,27648, 48,140, 52,2, 53,128, 54,1, 58,87 , 7,-243, 8,11505, 9,9, 15,466, 26,-6772, 34,-8800, 37,23, 38,338, 41,118, 43,32621, 48,140, 52,-48, 53,7, 54,1, 58,111 , 7,-8, 8,11387, 9,97, 11,-4275, 15,482, 25,-12421, 26,413, 28,315, 30,3621, 34,-8800, 37,23, 38,338, 41,119, 43,26112, 48,140, 52,11, 53,135, 54,1, 58,81 , 7,-8, 8,11387, 9,97, 11,-4275, 15,482, 25,-12421, 26,413, 28,315, 30,3621, 34,-8800, 37,23, 38,338, 41,119, 43,32615, 48,140, 52,-48, 53,7, 54,1, 58,111 /* Preset 91 */ , 5,28, 9,24, 15,466, 22,-42, 34,-8856, 37,23, 38,1262, 41,120, 43,25088, 48,150, 52,-20, 53,136, 54,1, 58,76 , 5,28, 9,24, 15,466, 22,-42, 34,-8856, 37,23, 38,1262, 41,120, 43,32611, 48,150, 52,-48, 53,7, 54,1, 58,111 , 5,19, 9,24, 15,482, 22,180, 34,-8590, 37,23, 38,1262, 41,121, 43,30464, 48,150, 52,5, 53,142, 54,1, 58,98 , 5,19, 9,24, 15,482, 22,180, 34,-8590, 37,23, 38,1262, 41,121, 43,32632, 48,150, 52,-48, 53,7, 54,1, 58,111 /* Preset 92 */ , 8,7552, 15,466, 25,-7592, 29,0, 34,-6530, 35,133, 36,4400, 38,1591, 41,122, 43,24832, 48,180, 52,36, 53,149, 54,1, 58,76 , 8,7552, 15,466, 25,-7592, 29,0, 34,-6530, 35,133, 36,4400, 38,1591, 41,122, 43,32610, 48,180, 52,-48, 53,7, 54,1, 58,111 , 8,10561, 15,482, 25,-7972, 27,-3172, 28,2715, 34,-5958, 36,2837, 37,139, 38,1916, 41,123, 43,25088, 48,180, 52,-20, 53,137, 54,1, 58,76 , 8,10561, 15,482, 25,-7972, 27,-3172, 28,2715, 34,-5958, 36,2837, 37,139, 38,1916, 41,123, 43,32611, 48,180, 52,-48, 53,7, 54,1, 58,111 /* Preset 93 */ , 8,6018, 9,81, 11,5062, 15,466, 28,3158, 30,4400, 34,-6013, 36,4400, 38,1699, 41,124, 43,21760, 48,180, 52,32, 53,54, 54,1, 58,64 , 8,6018, 9,81, 11,5062, 15,466, 28,3158, 30,4400, 34,-6013, 36,4400, 38,1699, 41,124, 43,24918, 48,180, 52,36, 53,149, 54,1, 58,76 , 8,6018, 9,81, 11,5062, 15,466, 28,3158, 30,4400, 34,-6013, 36,4400, 38,1699, 41,124, 43,32610, 48,180, 52,-48, 53,7, 54,1, 58,111 , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,2837, 37,811, 38,1699, 41,125, 43,16384, 48,180, 52,32, 53,75, 54,1, 58,64 , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,3049, 37,811, 38,1699, 41,125, 43,19521, 48,180, 52,32, 53,75, 54,1, 58,64 , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,2837, 37,811, 38,1699, 41,125, 43,21837, 48,180, 52,32, 53,75, 54,1, 58,64 , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,5817, 37,811, 38,1699, 41,125, 43,25174, 48,180, 52,-20, 53,137, 54,1, 58,76 , 8,5782, 9,78, 11,5287, 15,482, 28,3043, 30,4400, 34,652, 35,-4372, 36,5817, 37,811, 38,1699, 41,125, 43,32611, 48,180, 52,-48, 53,7, 54,1, 58,111 /* Preset 94 */ , 5,9, 8,7788, 9,129, 10,168, 11,7087, 22,-3357, 27,-7972, 28,1365, 30,2679, 34,-1857, 36,6000, 37,76, 38,1035, 41,126, 43,27904, 48,150, 52,-4, 53,128, 54,1, 58,87 , 5,9, 8,7788, 9,129, 10,168, 11,7087, 22,-3357, 27,-7972, 28,1365, 30,2679, 34,-1857, 36,6000, 37,76, 38,1035, 41,126, 43,32622, 48,150, 52,-48, 53,7, 54,1, 58,111 , 5,9, 8,7552, 9,24, 10,168, 11,4387, 22,-3357, 28,1365, 30,2715, 34,-5958, 36,6000, 37,76, 38,1035, 41,127, 43,27904, 48,150, 52,-4, 53,128, 54,1, 58,87 , 5,9, 8,7552, 9,24, 10,168, 11,4387, 22,-3357, 28,1365, 30,2715, 34,-5958, 36,6000, 37,76, 38,1035, 41,127, 43,32622, 48,150, 52,-48, 53,7, 54,1, 58,111 /* Preset 95 */ , 8,4484, 9,100, 11,7087, 15,466, 25,-3403, 26,4272, 28,2311, 29,506, 30,4400, 34,-2010, 36,4258, 37,0, 38,1916, 41,128, 43,27648, 48,200, 52,7, 53,128, 54,1, 58,87 , 8,4484, 9,100, 11,7087, 15,466, 25,-3403, 26,4272, 28,2311, 29,506, 30,4400, 34,-2010, 36,4258, 37,0, 38,1916, 41,128, 43,32621, 48,200, 52,-48, 53,7, 54,1, 58,111 /* Preset 96 */ , 8,6726, 9,9, 11,3937, 28,2217, 30,3043, 34,-6772, 36,4800, 38,2025, 41,129, 43,27904, 48,157, 52,-4, 53,128, 54,1, 58,87 , 8,6726, 9,9, 11,3937, 28,2217, 30,3043, 34,-6772, 36,4800, 38,2025, 41,129, 43,32622, 48,157, 52,-48, 53,7, 54,1, 58,111 , 7,1144, 9,109, 26,-8856, 28,813, 30,4400, 34,-3151, 36,4800, 38,2240, 41,130, 48,157, 51,-16, 52,-24, 53,122, 54,1, 56,50, 58,82 /* Preset 97 */ , 8,7080, 9,72, 11,3712, 15,466, 26,-2621, 28,315, 29,811, 30,4197, 34,-217, 36,4756, 37,86, 38,2025, 41,131, 43,28672, 48,142, 51,3, 52,-14, 53,128, 54,1, 58,90 , 8,7080, 9,72, 11,3712, 15,466, 26,-2621, 28,315, 29,811, 30,4197, 34,-217, 36,4756, 37,86, 38,2025, 41,131, 43,32625, 48,142, 51,1, 52,-48, 53,7, 54,1, 58,111 , 8,7316, 9,60, 11,4162, 15,482, 26,-2084, 28,315, 29,769, 30,4103, 34,-217, 36,4756, 37,86, 38,2025, 41,132, 43,26880, 48,142, 51,3, 52,-14, 53,128, 54,1, 58,83 , 8,7316, 9,60, 11,4162, 15,482, 26,-2084, 28,315, 29,769, 30,4103, 34,-217, 36,4756, 37,86, 38,2025, 41,132, 43,32618, 48,142, 51,1, 52,-48, 53,7, 54,1, 58,111 /* Preset 98 */ , 8,10443, 15,466, 34,-8800, 35,-4372, 36,3049, 38,1482, 41,133, 43,24064, 48,187, 52,29, 53,123, 54,1, 58,73 , 8,10443, 15,466, 34,-8800, 35,-4372, 36,3049, 38,1482, 41,133, 43,32607, 48,187, 52,-48, 53,7, 54,1, 58,111 , 15,482, 34,-8800, 36,3049, 38,1811, 41,134, 43,30208, 48,187, 52,-45, 53,130, 54,1, 58,96 , 15,482, 34,-8800, 36,3049, 38,1811, 41,134, 43,32631, 48,187, 52,-48, 53,7, 54,1, 58,111 /* Preset 99 */ , 8,7906, 9,15, 11,7087, 15,466, 28,1200, 30,1200, 34,-8800, 36,1980, 37,86, 38,-281, 41,135, 43,18432, 48,130, 52,47, 53,74, 54,1, 58,74 , 8,7906, 9,15, 11,7087, 15,466, 28,1200, 30,1200, 34,-8800, 36,1980, 37,86, 38,-281, 41,135, 43,24905, 48,130, 52,32, 53,75, 54,1, 58,76 , 8,7906, 9,15, 11,7087, 15,466, 28,1200, 30,1200, 34,-8800, 36,1980, 37,86, 38,-281, 41,135, 43,32610, 48,130, 52,-48, 53,7, 54,1, 58,111 , 6,28, 15,482, 21,-3670, 22,-866, 34,-8800, 36,3667, 37,86, 38,1591, 41,136, 43,29440, 48,130, 52,4, 53,51, 54,1, 58,94 , 6,28, 15,482, 21,-3670, 22,-866, 34,-8800, 36,3667, 37,86, 38,1591, 41,136, 43,32628, 48,130, 52,-48, 53,7, 54,1, 58,111 /* Preset 100 */ , 5,66, 15,466, 22,460, 34,-11958, 36,2733, 38,1699, 41,137, 43,27392, 48,130, 52,-32, 53,143, 54,1, 58,85 , 5,66, 15,466, 22,460, 34,-11958, 36,2733, 38,1699, 41,137, 43,32620, 48,130, 52,-48, 53,7, 54,1, 58,111 , 8,14400, 15,482, 34,-11958, 36,2733, 38,1699, 41,138, 43,29440, 48,130, 52,4, 53,51, 54,1, 58,94 , 8,14400, 15,482, 34,-11958, 36,2733, 38,1699, 41,138, 43,32628, 48,130, 52,-48, 53,7, 54,1, 58,111 /* Preset 101 */ , 8,4602, 9,54, 11,6075, 15,466, 26,4284, 27,-4870, 28,813, 30,3488, 34,2382, 37,0, 38,2345, 41,139, 43,27392, 48,200, 52,-32, 53,143, 54,1, 58,85 , 8,4602, 9,54, 11,6075, 15,466, 26,4284, 27,-4870, 28,813, 30,3488, 34,2382, 37,0, 38,2345, 41,139, 43,32620, 48,200, 52,-48, 53,7, 54,1, 58,111 , 8,4602, 9,94, 11,5737, 15,466, 26,4284, 27,-2203, 28,3343, 30,3578, 34,2382, 37,0, 38,2345, 41,140, 43,27392, 48,200, 51,32, 52,-32, 53,143, 54,1, 58,85 , 8,4602, 9,94, 11,5737, 15,466, 26,4284, 27,-2203, 28,3343, 30,3578, 34,2382, 37,0, 38,2345, 41,140, 43,32620, 48,200, 51,32, 52,-48, 53,7, 54,1, 58,111 /* Preset 102 */ , 8,5310, 9,103, 11,7087, 15,466, 28,-884, 29,727, 30,2982, 34,-7972, 37,0, 38,1372, 41,141, 43,30464, 48,60, 52,5, 53,142, 54,1, 58,98 , 8,5310, 9,103, 11,7087, 15,466, 28,-884, 29,727, 30,2982, 34,-7972, 37,0, 38,1372, 41,141, 43,32632, 48,60, 52,-48, 53,7, 54,1, 58,111 , 5,28, 8,4602, 9,75, 11,6412, 15,482, 22,460, 26,-116, 28,1782, 30,-2786, 34,-81, 36,3358, 38,1372, 41,142, 43,27392, 48,60, 52,-32, 53,143, 54,1, 58,85 , 5,28, 8,4602, 9,75, 11,6412, 15,482, 22,460, 26,-116, 28,1782, 30,-2786, 34,-81, 36,3358, 38,1372, 41,142, 43,32620, 48,60, 52,-48, 53,7, 54,1, 58,111 /* Preset 103 */ , 5,19, 8,6490, 9,24, 11,6637, 15,466, 22,-753, 28,-1586, 30,2484, 34,-5186, 35,-3172, 36,3462, 38,1591, 41,143, 43,24320, 48,210, 52,5, 53,76, 54,1, 58,74 , 8,7906, 9,18, 11,3487, 15,482, 28,0, 30,3186, 34,-5186, 37,0, 38,1591, 41,144, 43,27904, 48,210, 52,-4, 53,128, 54,1, 58,87 , 8,7906, 9,18, 11,3487, 15,482, 28,0, 30,3186, 34,-5186, 37,0, 38,1591, 41,144, 43,32622, 48,210, 52,-48, 53,7, 54,1, 58,111 /* Preset 104 */ , 34,-8800, 36,5003, 38,1035, 41,145, 43,27648, 48,60, 52,30, 53,73, 54,1, 58,87 , 34,-8800, 36,5003, 38,1035, 41,145, 43,32621, 48,60, 52,-48, 53,7, 54,1, 58,111 /* Preset 105 */ , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,146, 43,16896, 48,60, 52,44, 53,71, 54,1, 58,78 , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,146, 43,27459, 48,60, 52,-31, 53,72, 54,1, 58,85 , 34,-8800, 35,-2544, 36,1544, 38,-542, 41,146, 43,32620, 48,60, 52,-48, 53,7, 54,1, 58,111 /* Preset 106 */ , 8,10561, 34,-8800, 37,0, 38,-281, 41,147, 43,28416, 48,30, 52,-28, 53,113, 58,89 , 8,10561, 34,-8800, 37,0, 38,-281, 41,147, 43,32624, 48,30, 52,-48, 53,7, 58,111 , 8,6726, 34,-5053, 35,-2544, 36,1544, 38,-281, 41,148, 43,16640, 48,30, 52,44, 53,71, 54,1, 58,78 , 8,6726, 34,-5053, 35,-2544, 36,1544, 38,-281, 41,148, 43,27458, 48,30, 52,-31, 53,72, 54,1, 58,85 , 8,6726, 34,-5053, 35,-2544, 36,1544, 38,-281, 41,148, 43,32620, 48,30, 52,-48, 53,7, 54,1, 58,111 /* Preset 107 */ , 34,-8800, 35,-3172, 36,2412, 38,213, 41,149, 43,27392, 48,60, 52,24, 53,70, 54,1, 58,86 , 34,-8800, 35,-3172, 36,2412, 38,213, 41,149, 43,32620, 48,60, 52,-48, 53,7, 54,1, 58,111 /* Preset 108 */ , 9,96, 34,-8800, 36,256, 38,688, 41,150, 43,25088, 48,37, 52,-20, 53,127, 54,1, 58,76 , 9,96, 34,-8800, 36,256, 38,688, 41,150, 43,32611, 48,37, 52,-48, 53,7, 54,1, 58,111 , 34,-8800, 37,0, 38,811, 41,151, 43,30720, 48,37, 52,-39, 53,113, 58,98 , 34,-8800, 37,0, 38,811, 41,151, 43,32633, 48,37, 52,-48, 53,7, 58,111 /* Preset 109 */ , 2,-3, 3,-3, 34,-11958, 37,23, 38,-667, 41,152, 43,14592, 48,50, 52,-14, 53,45, 54,1, 58,62 , 2,-3, 3,-3, 34,-11958, 37,23, 38,-667, 41,152, 43,29498, 48,50, 52,32, 53,47, 54,1, 58,94 , 34,-11958, 37,23, 38,-667, 41,152, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 , 2,-3, 3,-3, 34,-11958, 37,23, 38,-667, 41,153, 43,14592, 48,50, 52,-6, 53,45, 54,1, 58,62 /* Preset 110 */ , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,17920, 48,100, 52,30, 53,55, 54,1, 58,87 , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,19015, 48,100, 52,15, 53,56, 54,1, 58,90 , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,20043, 48,100, 52,-45, 53,57, 54,1, 58,94 , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,21071, 48,100, 52,24, 53,58, 54,1, 58,98 , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,31571, 48,100, 52,15, 53,59, 54,1, 58,102 , 5,9, 21,-1675, 22,-780, 34,-8800, 36,3975, 37,13, 38,-667, 41,154, 43,32636, 48,100, 52,-48, 53,7, 54,1, 58,111 /* Preset 111 */ , 5,9, 21,-1675, 22,-780, 34,-8856, 35,-7972, 36,3684, 37,76, 38,-802, 41,155, 43,29440, 48,50, 52,29, 53,47, 54,1, 58,94 , 5,9, 21,-1675, 22,-780, 34,-8856, 35,-7972, 36,3684, 37,76, 38,-802, 41,155, 43,32628, 48,50, 52,-48, 53,7, 54,1, 58,111 /* Preset 112 */ , 34,-8800, 36,968, 37,412, 38,1035, 41,156, 43,19456, 48,60, 52,29, 53,138, 54,1, 58,84 , 34,-8800, 36,968, 37,412, 38,1035, 41,156, 43,28237, 48,60, 52,7, 53,139, 54,1, 58,89 , 34,-8800, 36,968, 37,412, 38,1035, 41,156, 43,32623, 48,60, 52,-48, 53,7, 54,1, 58,111 , 34,-8800, 36,-125, 38,-148, 41,157, 48,60, 52,19, 53,114, 58,107 /* Preset 113 */ , 34,-8800, 36,372, 38,-148, 41,158, 43,29696, 48,120, 52,50, 53,114, 58,95 , 34,-8800, 36,372, 38,-148, 41,158, 43,32629, 48,120, 52,-48, 53,7, 58,111 , 34,-8800, 36,372, 38,-148, 41,159, 43,22016, 48,120, 52,-23, 53,127, 54,1, 58,64 , 34,-8800, 36,372, 38,-148, 41,159, 43,32599, 48,120, 52,-48, 53,7, 54,1, 58,111 /* Preset 114 */ , 34,-8800, 35,-2400, 36,1035, 38,1035, 41,160, 43,27904, 48,60, 52,32, 53,109, 54,1, 58,88 , 34,-8800, 35,-2400, 36,1035, 38,1035, 41,160, 43,32622, 48,60, 52,-48, 53,7, 54,1, 58,111 /* Preset 115 */ , 34,-11958, 36,-386, 38,-1378, 41,161, 43,31744, 51,-16, 52,-10, 53,113, 56,50, 58,102 , 34,-11958, 36,-386, 38,-1378, 41,161, 43,32637, 51,-16, 52,-11, 53,7, 56,50, 58,111 /* Preset 116 */ , 34,-8800, 36,1365, 38,-148, 41,162, 43,29952, 48,130, 51,-5, 52,-12, 53,95, 54,1, 56,50, 58,95 , 34,-8800, 36,1365, 38,-148, 41,162, 43,32630, 48,130, 51,-5, 52,-24, 53,7, 54,1, 56,50, 58,111 , 34,-8800, 36,1365, 38,338, 41,163, 48,130, 51,-11, 52,25, 53,112, 54,1, 56,50, 58,107 /* Preset 117 */ , 34,-8800, 36,2837, 38,918, 41,164, 43,26624, 48,105, 51,-4, 52,-12, 53,95, 54,1, 56,50, 58,83 , 34,-8800, 36,2837, 38,918, 41,164, 43,32617, 48,105, 51,-4, 52,-24, 53,7, 54,1, 56,50, 58,112 /* Preset 118 */ , 7,516, 28,-386, 29,874, 30,4400, 34,-8800, 35,-4372, 36,372, 38,-949, 41,165, 43,26368, 48,120, 51,-12, 52,-12, 53,95, 54,1, 56,50, 58,81 , 7,516, 28,-386, 29,874, 30,4400, 34,-8800, 35,-4372, 36,372, 38,-949, 41,165, 43,32616, 48,120, 51,-12, 52,-24, 53,7, 54,1, 56,50, 58,111 , 7,591, 28,-2786, 30,-1586, 34,-8800, 36,736, 38,-949, 41,166, 43,28416, 48,120, 51,-12, 52,-14, 53,127, 54,1, 56,50, 58,89 , 7,591, 28,-2786, 30,-1586, 34,-8800, 36,736, 38,-949, 41,166, 43,32624, 48,120, 51,-12, 52,-24, 53,7, 54,1, 56,50, 58,111 /* Preset 119 */ , 34,915, 36,-2143, 38,-7053, 41,167, 43,28672, 48,7, 51,-6, 52,23, 53,115, 54,1, 56,50, 58,91 , 34,915, 36,-2143, 38,-7053, 41,167, 43,32625, 48,7, 51,-6, 52,-24, 53,7, 54,1, 56,50, 58,111 /* Preset 120 */ , 9,190, 34,-8800, 37,0, 38,-2197, 41,168, 43,26368, 51,-12, 52,-3, 53,148, 56,50, 58,81 , 9,190, 34,-8800, 37,0, 38,-2197, 41,168, 43,32616, 51,-12, 52,-24, 53,7, 56,50, 58,111 /* Preset 121 */ , 34,-8800, 36,2626, 38,-949, 41,169, 43,23296, 48,282, 51,-5, 52,19, 53,42, 56,50, 58,70 , 34,-8800, 36,2626, 38,-949, 41,169, 43,32604, 48,282, 51,-5, 52,-24, 53,7, 56,50, 58,111 /* Preset 122 */ , 0,500, 8,4602, 9,57, 11,3937, 26,2866, 27,-2332, 28,2484, 30,3533, 34,1776, 35,998, 36,2412, 38,1699, 41,170, 43,27904, 52,9, 53,140, 54,1, 56,50, 58,88 , 8,4602, 9,57, 11,3937, 26,2866, 27,-2332, 28,2484, 30,3533, 34,1776, 35,998, 36,2412, 38,1699, 41,170, 43,32622, 52,-24, 53,7, 54,1, 56,50, 58,111 , 8,5310, 9,57, 11,2587, 26,2866, 27,-2332, 28,3043, 30,3578, 34,-3986, 36,3358, 38,1699, 41,170, 43,30720, 52,9, 53,140, 54,1, 56,50, 58,99 , 8,4602, 9,57, 11,3937, 26,2866, 27,-2332, 28,2484, 30,3533, 34,1776, 35,998, 36,2412, 38,1699, 41,170, 43,32633, 52,-24, 53,7, 54,1, 56,50, 58,111 /* Preset 123 */ , 5,-55, 7,-599, 9,160, 21,-544, 22,460, 26,-2902, 30,3823, 34,-1382, 36,1092, 38,-386, 41,171, 43,32639, 48,50, 53,127, 54,1, 56,50, 58,51 , 34,-8800, 35,-12000, 36,-12000, 41,171, 43,32612, 48,50, 52,-24, 53,7, 56,50, 58,111 , 5,-599, 7,-599, 9,160, 21,-544, 22,460, 26,-1702, 28,-1586, 34,-1382, 35,-2701, 36,-884, 37,916, 38,315, 41,171, 43,32639, 48,50, 53,127, 54,1, 56,50, 58,35 , 5,-599, 7,-599, 9,160, 21,-3172, 22,460, 26,-1702, 28,-1586, 34,-8856, 35,-2701, 36,5382, 37,916, 38,1958, 41,171, 43,21248, 48,50, 53,127, 54,1, 56,50, 58,35 /* Preset 124 */ , 2,-30, 3,32, 9,103, 37,0, 38,-1079, 41,172, 43,27392, 48,105, 51,-3, 52,17, 53,141, 54,1, 56,50, 58,86 , 9,103, 37,0, 38,-1079, 41,172, 43,32620, 48,105, 51,-3, 52,-24, 53,7, 54,1, 56,50, 58,111 , 2,-30, 3,32, 9,112, 37,0, 38,-1079, 41,173, 43,27392, 48,105, 52,16, 53,141, 54,3, 56,50, 58,85 , 9,103, 37,0, 38,-1079, 41,173, 43,32620, 48,105, 51,-3, 52,-24, 53,7, 54,1, 56,50, 58,111 /* Preset 125 */ , 5,591, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 43,15104, 48,172, 51,-12, 52,9, 53,140, 54,1, 56,50, 58,85 , 5,591, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 43,27196, 48,172, 51,-12, 52,9, 53,140, 54,1, 56,50, 58,85 , 5,591, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 43,32619, 48,172, 51,-12, 52,-24, 53,7, 54,1, 56,50, 58,111 , 5,47, 8,4838, 9,9, 10,3543, 13,118, 22,258, 34,542, 36,3565, 37,0, 38,-148, 41,174, 48,172, 51,-24, 52,2, 53,142, 54,1, 56,50, 58,127 /* Preset 126 */ , 17,217, 34,1587, 37,0, 38,-148, 41,175, 43,28416, 48,45, 51,-8, 52,23, 53,117, 54,1, 56,50, 58,98 , 34,1587, 37,0, 38,-148, 41,175, 43,32624, 48,45, 51,-8, 52,-24, 53,7, 54,1, 56,50, 58,111 , 17,-287, 34,1587, 37,0, 38,-148, 41,175, 43,31744, 48,45, 51,-8, 52,23, 53,117, 54,1, 56,50, 58,103 , 34,1587, 37,0, 38,-148, 41,175, 43,32637, 48,45, 51,-8, 52,-24, 53,7, 54,1, 56,50, 58,111 /* Preset 127 */ , 17,-216, 34,-11958, 37,0, 38,-148, 41,176, 43,29184, 51,-12, 52,17, 53,93, 56,50, 58,93 , 17,-216, 34,-11958, 37,0, 38,-148, 41,176, 43,32627, 51,-12, 52,-24, 53,7, 56,50, 58,111 , 17,288, 34,-11958, 37,0, 38,-148, 41,176, 43,29952, 51,-12, 52,17, 53,93, 56,50, 58,96 , 17,288, 34,-11958, 37,0, 38,-148, 41,176, 43,32630, 51,-12, 52,-24, 53,7, 56,50, 58,111 /* Preset 128 */ , 36,-3986, 38,-148, 41,177, 43,6939, 48,142, 52,-31, 53,90, 58,45 , 36,-125, 38,-542, 41,177, 43,7196, 48,142, 52,19, 53,140, 54,1, 58,51 , 36,-2332, 38,-148, 41,177, 43,7196, 48,142, 52,-48, 53,94, 58,54 , 37,0, 38,-148, 41,177, 43,7453, 48,112, 52,-48, 53,96, 57,7, 58,57 , 37,0, 38,-148, 41,177, 43,7710, 48,112, 52,-12, 53,148, 57,7, 58,42 , 37,0, 38,-2197, 41,177, 43,7967, 48,37, 52,4, 53,111, 58,42 , 35,-1461, 37,0, 38,-2197, 41,177, 43,8224, 48,127, 53,146, 58,31 , 36,-5572, 38,-5853, 41,177, 43,8481, 52,-48, 53,94, 58,51 , 36,-1919, 38,-2197, 41,177, 43,8738, 48,127, 52,-48, 53,94, 58,51 , 36,1872, 38,-2197, 41,177, 43,8738, 48,127, 52,-34, 53,139, 54,1, 58,44 , 36,1763, 38,-2050, 41,177, 43,8995, 48,30, 52,2, 53,92, 58,50 , 37,0, 38,-1867, 41,177, 43,9252, 48,7, 52,24, 53,92, 58,48 , 36,-1586, 38,-1378, 41,177, 43,9509, 48,135, 52,-48, 53,94, 58,56 , 36,736, 38,811, 41,177, 43,9766, 48,45, 52,-43, 53,144, 58,56 , 17,-216, 36,-521, 38,-802, 41,177, 43,10023, 48,90, 52,-21, 53,117, 54,1, 58,46 , 17,-216, 36,-261, 38,-542, 41,177, 43,10023, 48,90, 52,47, 53,117, 54,1, 58,79 , 36,372, 38,213, 41,177, 43,10280, 48,112, 52,8, 53,144, 58,52 , 36,-386, 38,-1079, 41,177, 43,10280, 48,112, 52,-48, 53,95, 54,1, 58,51 , 17,-216, 36,1872, 38,1591, 41,177, 43,10537, 48,112, 52,18, 53,95, 54,1, 58,69 , 17,146, 35,-7972, 36,-1586, 37,989, 38,-1079, 41,177, 43,10794, 48,100, 52,-37, 53,150, 54,1, 57,1, 58,50 , 17,-74, 36,1654, 38,1372, 41,177, 43,11051, 48,67, 52,-25, 53,95, 54,1, 58,68 , 17,146, 34,-7390, 35,-7972, 36,-12000, 37,989, 38,-3067, 41,177, 43,11308, 48,67, 52,-46, 53,150, 54,1, 57,1, 58,52 , 17,-74, 36,1426, 38,1145, 41,177, 43,11565, 48,67, 52,-25, 53,95, 54,1, 58,67 , 17,75, 36,2198, 38,1145, 41,177, 43,11822, 48,45, 52,-17, 53,150, 54,1, 57,1, 58,54 , 36,1317, 38,1035, 41,177, 43,12079, 48,52, 52,-4, 53,95, 54,1, 58,66 , 36,1200, 38,1145, 41,177, 43,12336, 48,67, 52,40, 53,95, 54,1, 58,63 , 17,146, 36,1980, 38,1699, 41,177, 43,12593, 52,47, 53,115, 54,1, 58,68 , 17,288, 36,856, 38,575, 41,177, 43,12850, 48,90, 52,-25, 53,95, 54,1, 58,61 , 17,-216, 36,1763, 38,1482, 41,177, 43,13107, 48,142, 52,-7, 53,151, 54,1, 58,59 , 17,-145, 36,1980, 38,1262, 41,177, 43,13364, 48,75, 52,47, 53,119, 54,1, 58,74 , 17,-216, 36,1426, 38,1035, 41,177, 43,13621, 48,90, 52,8, 53,118, 54,1, 58,71 , 17,146, 35,-4372, 36,1200, 38,2345, 41,177, 43,13878, 48,52, 52,35, 53,97, 54,3, 58,70 , 17,-74, 36,1654, 38,1372, 41,177, 43,14135, 48,90, 52,47, 53,115, 54,1, 58,65 , 17,146, 35,-4372, 36,619, 38,2345, 41,177, 43,14392, 48,202, 52,-14, 53,98, 58,72 , 17,-216, 36,1654, 38,1372, 41,177, 43,14649, 52,47, 53,115, 54,1, 58,74 , 17,-429, 36,1654, 38,811, 41,177, 43,14906, 53,99, 54,1, 58,82 , 17,-287, 36,1763, 38,1482, 41,177, 43,15163, 48,165, 52,18, 53,151, 54,1, 58,66 , 17,358, 35,-3670, 36,0, 38,-1702, 41,177, 43,15420, 52,21, 53,100, 58,78 , 17,217, 36,0, 38,-1079, 41,177, 43,15677, 52,-18, 53,101, 58,77 , 17,-287, 36,0, 38,-667, 41,177, 43,15934, 52,43, 53,102, 58,82 , 17,-429, 36,-261, 38,-1702, 41,177, 43,16191, 52,-46, 53,103, 58,85 , 17,-429, 36,-125, 38,-1224, 41,177, 43,16448, 52,21, 53,104, 58,83 , 17,217, 36,619, 38,-24, 41,177, 43,16705, 52,50, 53,112, 54,1, 58,89 , 17,288, 36,619, 38,-24, 41,177, 43,16962, 52,50, 53,112, 54,1, 58,95 , 17,-287, 36,-261, 38,-2050, 41,177, 43,17219, 52,50, 53,114, 58,85 , 17,-287, 36,-261, 38,-667, 41,177, 43,17476, 52,50, 53,114, 58,91 , 17,-358, 36,0, 38,-1224, 41,177, 43,17733, 52,-14, 53,105, 58,85 , 17,-358, 36,813, 38,-7053, 41,177, 43,17990, 48,90, 52,27, 53,106, 58,83 , 17,217, 35,-2701, 38,-7053, 41,177, 43,18247, 48,210, 52,36, 53,107, 54,1, 57,2, 58,87 , 17,217, 35,-1034, 38,-7053, 41,177, 43,18504, 48,157, 52,36, 53,107, 54,1, 57,2, 58,91 , 17,288, 36,1200, 38,-2050, 41,177, 43,18761, 48,180, 52,-25, 53,108, 57,3, 58,90 , 17,358, 36,1317, 38,-1224, 41,177, 43,19018, 48,90, 52,-46, 53,110, 57,3, 58,102 , 17,288, 36,-386, 38,-949, 41,177, 43,19275, 48,45, 52,40, 53,116, 58,100 , 17,358, 36,-3986, 38,-7053, 41,177, 43,19532, 48,37, 52,-45, 53,113, 58,104 , 17,288, 36,-2544, 38,-7053, 41,177, 43,19789, 48,37, 52,-45, 53,113, 58,111 , 17,-216, 36,0, 38,-2197, 41,177, 43,20046, 48,150, 52,35, 53,120, 57,4, 58,87 , 17,-216, 36,0, 38,-2821, 41,177, 43,20303, 48,67, 52,35, 53,120, 57,4, 58,105 , 17,-429, 36,-667, 38,-4653, 41,177, 43,20560, 48,277, 52,-32, 53,126, 54,1, 57,5, 58,88 , 17,-358, 36,968, 38,455, 41,177, 43,20817, 48,217, 52,-42, 53,126, 54,1, 57,5, 58,89 , 17,288, 36,-386, 38,-2420, 41,177, 43,21074, 52,-14, 53,105, 58,95 , 17,358, 34,-2514, 36,619, 38,338, 41,177, 43,21331, 52,4, 53,97, 54,3, 58,104 , 17,358, 34,-6688, 36,619, 38,-148, 41,177, 43,21331, 52,47, 53,119, 54,1, 58,73 , 17,288, 36,1200, 38,-148, 41,177, 43,21588, 52,-12, 53,91, 54,1, 58,105 , 17,-429, 36,-1586, 38,-949, 41,177, 43,21845, 48,285, 52,21, 53,100, 58,89 , 17,-429, 36,-1586, 37,0, 38,-949, 41,177, 43,21845, 48,285, 53,146, 58,71 , 17,-358, 36,813, 38,-667, 41,177, 43,22102, 48,202, 52,-18, 53,101, 57,6, 58,104 , 17,-429, 36,1872, 38,1035, 41,177, 43,22359, 48,165, 52,-25, 53,95, 54,1, 57,6, 58,113 , 17,-429, 36,-1586, 37,380, 38,1035, 41,177, 43,22359, 48,165, 52,50, 53,112, 54,1, 57,6, 58,125 }; int _awe_sf_sample_data[] = { 494, 11149, 17721, 17725, 17771, 35408, 39898, 39901, 65209, 86715, 86778, 86782, 39947, 55375, 65159, 65163, 86828, 93676, 93802, 93807, 93853, 99946, 99994, 99998, 100044, 104192, 104246, 104507, 104553, 107516, 109947, 109951 , 494, 11149, 17721, 17725, 17771, 35408, 39898, 39901, 65209, 86715, 86778, 86782, 39947, 55375, 65159, 65163, 86828, 93676, 93802, 93807, 93853, 99946, 99994, 99998, 100044, 104192, 104246, 104507, 104553, 107516, 109947, 109951 , 494, 11149, 17721, 17725, 17771, 35408, 39898, 39901, 65209, 86715, 86778, 86782, 39947, 55375, 65159, 65163, 93853, 99946, 99994, 99998, 104553, 107516, 109947, 109951 , 494, 11149, 17721, 17725, 17771, 35408, 39898, 39901, 65209, 86715, 86778, 86782, 39947, 55375, 65159, 65163, 86828, 93676, 93802, 93807, 93853, 99946, 99994, 99998, 100044, 104192, 104246, 104507, 104553, 107516, 109947, 109951, 494, 11149, 17721, 17725, 17771, 35408, 39898, 39901, 65209, 86715, 86778, 86782, 39947, 55375, 65159, 65163, 86828, 93676, 93802, 93807, 93853, 99946, 99994, 99998, 100044, 104192, 104246, 104507, 104553, 107516, 109947, 109951 , 458744, 458761, 458809, 458813, 458744, 458761, 458809, 458813, 458744, 458761, 458809, 458813, 109997, 111117, 111165, 111169, 104553, 107516, 109947, 109951, 497937, 497944, 498216, 498220, 430271, 430340, 430406, 430410, 104553, 107516, 109947, 109951 , 109997, 111117, 111165, 111169, 104553, 107516, 109947, 109951 , 114245, 115539, 115631, 115635, 104553, 107516, 109947, 109951, 259435, 262219, 262280, 262284, 262330, 265870, 265909, 265912, 104553, 107516, 109947, 109951 , 111215, 114051, 114195, 114199, 104553, 107516, 109947, 109951 , 421857, 422553, 422634, 422638, 446722, 451551, 452134, 452138, 104553, 107516, 109947, 109951 , 491098, 491105, 491166, 491170, 491098, 491105, 491166, 491170, 490837, 490844, 491048, 491052, 104553, 107516, 109947, 109951 , 430271, 430340, 430406, 430410, 430271, 430340, 430406, 430410, 104553, 107516, 109947, 109951, 452184, 452253, 452319, 452323, 452184, 452253, 452319, 452323, 104553, 107516, 109947, 109951 , 421857, 422553, 422634, 422638, 421857, 422553, 422634, 422638, 104553, 107516, 109947, 109951 , 427295, 428083, 428107, 428111, 104553, 107516, 109947, 109951 , 419807, 419814, 420783, 420786, 104553, 107516, 109947, 109951 , 446722, 451551, 452134, 452138 , 246278, 250056, 250108, 250112, 104553, 107516, 109947, 109951 , 458074, 458143, 458209, 458213, 104553, 107516, 109947, 109951, 452184, 452253, 452319, 452323, 104553, 107516, 109947, 109951 , 452369, 454984, 455039, 455043, 455089, 457990, 458024, 458028, 104553, 107516, 109947, 109951 , 452369, 454984, 455039, 455043, 455089, 457990, 458024, 458028, 104553, 107516, 109947, 109951, 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951 , 452184, 452253, 452319, 452323, 104553, 107516, 109947, 109951, 131469, 132834, 132896, 132900, 131469, 132834, 132896, 132900, 104553, 107516, 109947, 109951 , 181530, 182445, 182499, 182503, 452184, 452253, 452319, 452323, 104553, 107516, 109947, 109951, 458074, 458143, 458209, 458213, 104553, 107516, 109947, 109951 , 298212, 299191, 299256, 299260, 299306, 299872, 299922, 299925, 299971, 300795, 300825, 300828, 104553, 107516, 109947, 109951, 282298, 282367, 282433, 282437, 104553, 107516, 109947, 109951 , 181530, 182445, 182499, 182503, 104553, 107516, 109947, 109951 , 298212, 299191, 299256, 299260, 299971, 300795, 300825, 300828, 104553, 107516, 109947, 109951, 282298, 282367, 282433, 282437, 104553, 107516, 109947, 109951 , 282483, 286210, 286307, 286311, 286357, 291482, 291545, 291549, 273246, 279414, 279482, 279486, 104553, 107516, 109947, 109951 , 268319, 273119, 273196, 273200, 273246, 279414, 279482, 279486, 104553, 107516, 109947, 109951 , 279532, 280933, 281008, 281012, 104553, 107516, 109947, 109951, 291595, 291604, 291709, 291713, 104553, 107516, 109947, 109951 , 279532, 280933, 281008, 281012, 296401, 297994, 298162, 298166 , 281058, 281824, 281889, 281893, 104553, 107516, 109947, 109951 , 293047, 294792, 294874, 294878, 294924, 296296, 296351, 296355, 291759, 292954, 292997, 293001, 104553, 107516, 109947, 109951, 291595, 291604, 291709, 291713, 104553, 107516, 109947, 109951 , 293047, 294792, 294874, 294878, 294924, 296296, 296351, 296355, 291759, 292954, 292997, 293001, 296401, 297994, 298162, 298166, 104553, 107516, 109947, 109951 , 281939, 282238, 282248, 282252, 104553, 107516, 109947, 109951 , 236031, 237439, 237561, 237565, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 237611, 238361, 238511, 238515, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 246108, 246117, 246228, 246232, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 238561, 240726, 240897, 240901, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 240947, 242765, 243063, 243067, 111215, 114051, 114195, 114199, 104553, 107516, 109947, 109951 , 243113, 245458, 245572, 245576, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 245622, 245631, 246058, 246062, 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 458259, 458274, 458324, 458328, 104553, 107516, 109947, 109951 , 238561, 240726, 240897, 240901, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951, 246108, 246117, 246228, 246232, 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 226907, 228598, 228634, 228638, 228684, 230386, 230446, 230450, 230496, 231531, 231577, 231581, 231627, 232659, 232697, 232701, 232747, 234316, 234376, 234380, 104553, 107516, 109947, 109951 , 226907, 228598, 228634, 228638, 228684, 230386, 230446, 230450, 230496, 231531, 231577, 231581, 231627, 232659, 232697, 232701, 232747, 234316, 234376, 234380, 104553, 107516, 109947, 109951 , 223282, 224409, 224477, 224481, 224527, 225326, 225369, 225373, 104553, 107516, 109947, 109951 , 225419, 226721, 226857, 226861, 224527, 225326, 225369, 225373, 104553, 107516, 109947, 109951 , 184452, 187061, 193756, 193760, 193806, 197221, 202448, 202452, 202498, 205596, 213220, 213224, 104553, 107516, 109947, 109951 , 234426, 235953, 235981, 235985, 104553, 107516, 109947, 109951 , 250158, 253567, 253631, 253635, 104553, 107516, 109947, 109951 , 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 104553, 107516, 109947, 109951 , 184452, 187061, 193756, 193760, 193806, 197221, 202448, 202452, 202498, 205596, 213220, 213224, 104553, 107516, 109947, 109951 , 184452, 187061, 193756, 193760, 193806, 197221, 202448, 202452, 202498, 205596, 213220, 213224, 104553, 107516, 109947, 109951 , 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951 , 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951, 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951 , 468964, 469302, 477719, 477722, 104553, 107516, 109947, 109951, 477768, 477803, 486865, 486869, 104553, 107516, 109947, 109951 , 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951, 491216, 494215, 494270, 494274, 104553, 107516, 109947, 109951 , 477768, 477803, 486865, 486869, 104553, 107516, 109947, 109951 , 422684, 422691, 427246, 427249, 104553, 107516, 109947, 109951 , 152314, 153942, 153983, 153987, 145685, 147283, 147316, 147320, 147366, 148964, 149014, 149018, 149064, 150518, 150556, 150560, 150606, 152208, 152264, 152268, 104553, 107516, 109947, 109951 , 154033, 155265, 155359, 155363, 155409, 156684, 156738, 156742, 156788, 157862, 157904, 157908, 157954, 159458, 159518, 159522, 104553, 107516, 109947, 109951 , 159568, 161399, 161528, 161531, 157954, 159458, 159518, 159522, 104553, 107516, 109947, 109951 , 161577, 162997, 163058, 163061, 163107, 163947, 164005, 164009, 104553, 107516, 109947, 109951 , 128835, 130255, 130315, 130319, 104553, 107516, 109947, 109951 , 134414, 139947, 140009, 140013, 140059, 145048, 145094, 145639, 104553, 107516, 109947, 109951, 134414, 139947, 140009, 140013, 140059, 145048, 145094, 145639, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951 , 115681, 116735, 116826, 116830, 116876, 118026, 118099, 118103, 118149, 119716, 119783, 119787, 119833, 120476, 120524, 120528, 120574, 121437, 121479, 121483, 121529, 122659, 122715, 122719, 122765, 123901, 123949, 123953, 104553, 107516, 109947, 109951 , 115681, 116735, 116826, 116830, 116876, 118026, 118099, 118103, 118149, 119716, 119783, 119787, 119833, 120476, 120524, 120528, 120574, 121437, 121479, 121483, 121529, 122659, 122715, 122719, 122765, 123901, 123949, 123953, 104553, 107516, 109947, 109951 , 115681, 116735, 116826, 116830, 116876, 118026, 118099, 118103, 118149, 119716, 119783, 119787, 119833, 120476, 120524, 120528, 120574, 121437, 121479, 121483, 121529, 122659, 122715, 122719, 122765, 123901, 123949, 123953, 104553, 107516, 109947, 109951 , 116876, 118026, 118099, 118103, 118149, 119716, 119783, 119787, 119833, 120476, 120524, 120528, 120574, 121437, 121479, 121483, 121529, 122659, 122715, 122719, 122765, 123901, 123949, 123953, 104553, 107516, 109947, 109951 , 123999, 124832, 124886, 124890, 124936, 126114, 126157, 126161, 126207, 127166, 127200, 127204, 104553, 107516, 109947, 109951 , 127250, 128730, 128785, 128789, 104553, 107516, 109947, 109951 , 130365, 131304, 131419, 131423, 127250, 128730, 128785, 128789, 104553, 107516, 109947, 109951 , 132946, 133543, 133618, 133622, 133668, 134255, 134364, 134368, 104553, 107516, 109947, 109951 , 131469, 132834, 132896, 132900, 104553, 107516, 109947, 109951, 164055, 165356, 165410, 165414, 104553, 107516, 109947, 109951 , 131469, 132834, 132896, 132900, 104553, 107516, 109947, 109951, 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951 , 164055, 165356, 165410, 165414, 104553, 107516, 109947, 109951 , 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951, 164055, 165356, 165410, 165414, 104553, 107516, 109947, 109951 , 165460, 165467, 170770, 170773, 104553, 107516, 109947, 109951, 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951 , 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951 , 178332, 179476, 179514, 179518, 104553, 107516, 109947, 109951 , 178332, 179476, 179514, 179518, 104553, 107516, 109947, 109951 , 444250, 446618, 446673, 446676, 104553, 107516, 109947, 109951, 444250, 446618, 446673, 446676, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 458259, 458274, 458324, 458328, 104553, 107516, 109947, 109951 , 165460, 165467, 170770, 170773, 104553, 107516, 109947, 109951, 444250, 446618, 446673, 446676, 104553, 107516, 109947, 109951 , 165460, 165467, 170770, 170773, 104553, 107516, 109947, 109951, 458259, 458274, 458324, 458328, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 111215, 114051, 114195, 114199, 104553, 107516, 109947, 109951 , 170819, 172904, 178282, 178286, 104553, 107516, 109947, 109951, 468964, 469302, 477719, 477722, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 458259, 458274, 458324, 458328, 104553, 107516, 109947, 109951 , 245622, 245631, 246058, 246062, 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 458259, 458274, 458324, 458328, 104553, 107516, 109947, 109951 , 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951, 109997, 111117, 111165, 111169, 104553, 107516, 109947, 109951 , 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 458259, 458274, 458324, 458328, 104553, 107516, 109947, 109951 , 458374, 458443, 458509, 458513, 104553, 107516, 109947, 109951, 468964, 469302, 477719, 477722, 104553, 107516, 109947, 109951 , 497937, 497944, 498216, 498220, 104553, 107516, 109947, 109951, 458559, 458628, 458694, 458698, 104553, 107516, 109947, 109951 , 225419, 226721, 226857, 226861, 497937, 497944, 498216, 498220, 104553, 107516, 109947, 109951, 273246, 279414, 279482, 279486, 273246, 279414, 279482, 279486, 273246, 279414, 279482, 279486, 458559, 458628, 458694, 458698, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 420832, 420839, 421808, 421811 , 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951, 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951 , 421857, 422553, 422634, 422638, 104553, 107516, 109947, 109951, 446722, 451551, 452134, 452138, 104553, 107516, 109947, 109951 , 268319, 273119, 273196, 273200, 273246, 279414, 279482, 279486, 104553, 107516, 109947, 109951, 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951 , 477768, 477803, 486865, 486869, 104553, 107516, 109947, 109951, 213270, 214542, 223232, 223236, 104553, 107516, 109947, 109951 , 477768, 477803, 486865, 486869, 104553, 107516, 109947, 109951, 477768, 477803, 486865, 486869, 104553, 107516, 109947, 109951 , 468964, 469302, 477719, 477722, 104553, 107516, 109947, 109951, 477768, 477803, 486865, 486869, 104553, 107516, 109947, 109951 , 279532, 280933, 281008, 281012, 430456, 430745, 444201, 444204, 104553, 107516, 109947, 109951 , 265958, 268233, 268269, 268273, 104553, 107516, 109947, 109951 , 259435, 262219, 262280, 262284, 262330, 265870, 265909, 265912, 104553, 107516, 109947, 109951 , 372986, 372993, 374146, 374149, 104553, 107516, 109947, 109951, 259435, 262219, 262280, 262284, 262330, 265870, 265909, 265912, 104553, 107516, 109947, 109951 , 253681, 259347, 259385, 259389, 104553, 107516, 109947, 109951 , 430271, 430340, 430406, 430410, 104553, 107516, 109947, 109951, 372986, 372993, 374146, 374149, 104553, 107516, 109947, 109951 , 179564, 181331, 181480, 181484, 182549, 184354, 184402, 184406, 104553, 107516, 109947, 109951, 179564, 181331, 181480, 181484 , 226907, 228598, 228634, 228638, 228684, 230386, 230446, 230450, 230496, 231531, 231577, 231581, 231627, 232659, 232697, 232701, 232747, 234316, 234376, 234380, 104553, 107516, 109947, 109951 , 182549, 184354, 184402, 184406, 104553, 107516, 109947, 109951 , 458744, 458761, 458809, 458813, 458859, 458874, 458945, 458949, 104553, 107516, 109947, 109951, 374195, 374202, 378658, 378661 , 374195, 374202, 378658, 378661, 104553, 107516, 109947, 109951, 430271, 430340, 430406, 430410, 104553, 107516, 109947, 109951 , 359039, 361896, 361930, 361936, 104553, 107516, 109947, 109951 , 372986, 372993, 374146, 374149, 104553, 107516, 109947, 109951 , 317192, 322428, 324359, 324363, 104553, 107516, 109947, 109951, 365242, 372321, 372937, 372940 , 317192, 322428, 324359, 324363, 104553, 107516, 109947, 109951 , 317192, 322428, 324359, 324363, 104553, 107516, 109947, 109951, 430271, 430340, 430406, 430410, 104553, 107516, 109947, 109951 , 378707, 386731, 392236, 392240, 104553, 107516, 109947, 109951 , 494320, 494327, 497887, 497891, 104553, 107516, 109947, 109951 , 165460, 165467, 170770, 170773, 104553, 107516, 109947, 109951 , 458995, 459002, 467284, 467288, 104553, 107516, 109947, 109951, 458995, 459002, 467284, 467288, 104553, 107516, 109947, 109951 , 430271, 430340, 430406, 430410, 104553, 107516, 109947, 109951, 430271, 430340, 430406, 430410, 430271, 430340, 430406, 430410 , 467334, 467341, 468914, 468918, 104553, 107516, 109947, 109951, 467334, 467341, 468914, 468918, 104553, 107516, 109947, 109951 , 458995, 459002, 467284, 467288, 458995, 459002, 467284, 467288, 104553, 107516, 109947, 109951, 468964, 469302, 477719, 477722 , 394105, 394112, 402261, 402265, 104553, 107516, 109947, 109951, 394105, 394112, 402261, 402265, 104553, 107516, 109947, 109951 , 310498, 310505, 315890, 315893, 104553, 107516, 109947, 109951, 310498, 310505, 315890, 315893, 104553, 107516, 109947, 109951 , 300874, 300881, 301290, 301293, 458995, 459002, 467284, 467288, 315939, 315946, 317143, 317146, 324409, 324416, 326066, 326069, 494320, 494327, 497887, 497891, 364827, 364834, 365193, 365196, 491098, 491105, 491166, 491170, 315939, 315946, 317143, 317146, 315939, 315946, 317143, 317146, 458859, 458874, 458945, 458949, 308850, 308857, 310449, 310452, 308850, 308857, 310449, 310452, 315939, 315946, 317143, 317146, 486915, 486922, 490788, 490791, 394105, 394112, 402261, 402265, 394105, 394112, 402261, 402265, 486915, 486922, 490788, 490791, 317192, 322428, 324359, 324363, 317192, 322428, 324359, 324363, 498266, 504094, 509971, 509975, 317192, 322428, 324359, 324363, 498266, 504094, 509971, 509975, 317192, 322428, 324359, 324363, 498266, 504094, 509971, 509975, 317192, 322428, 324359, 324363, 317192, 322428, 324359, 324363, 378707, 386731, 392236, 392240, 317192, 322428, 324359, 324363, 510021, 517480, 523309, 523313, 408390, 414552, 418085, 418089, 402311, 405925, 408340, 408344, 326115, 328272, 329700, 329718, 378707, 386731, 392236, 392240, 329764, 329771, 331520, 331523, 378707, 386731, 392236, 392240, 331569, 331578, 332352, 332356, 510021, 517480, 523309, 523313, 332402, 332409, 335602, 335605, 335651, 335658, 338371, 338374, 338420, 338427, 341339, 341342, 341388, 341395, 344475, 344478, 344524, 344531, 348542, 348545, 365242, 372321, 372937, 372940, 365242, 372321, 372937, 372940, 374195, 374202, 378658, 378661, 374195, 374202, 378658, 378661, 348591, 348598, 351266, 351269, 351315, 351322, 354565, 354568, 354614, 355735, 356287, 356300, 354614, 355735, 356287, 356300, 356346, 356353, 358990, 358993, 362018, 362025, 364777, 364781, 392286, 392293, 394056, 394059, 372986, 372993, 374146, 374149, 372986, 372993, 374146, 374149, 418135, 418142, 419758, 419761, 418135, 418142, 419758, 419761, 428157, 428493, 430221, 430225, 428157, 428493, 430221, 430225, 348591, 348598, 351266, 351269, 326115, 328272, 329700, 329718, 408390, 414552, 418085, 418089, 301339, 307602, 308800, 308804, 332402, 332409, 335602, 335605, 491098, 491105, 491166, 491170, 335651, 335658, 338371, 338374, 317192, 322428, 324359, 324363, 365242, 372321, 372937, 372940 }; allegro-4.4.3.1/src/dos/wss.c0000664000175000017500000002227313437077643014642 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows Sound System driver. * Supports DMA playback and sampling rates to up to 48khz. * * The WSS CODEC is more common than you might think. * Supported chips: AD1848, CS4231/A, CS4232 and compatibles. * * By Antti Koskipaa. * * See readme.txt for copyright information. * * The WSS chips (all of them, clones too) have a bug which causes them * to "swap" the LSB/MSB of each sample (or something like that) causing * nothing but a loud fuzz from the speakers on "rare" occasions. * An errata sheet on the CS4231 chip exists, but I haven't found it. * If you fix this problem, email me and tell how... * * Should I support recording? naah... =) * AD1848 can't do full duplex, and this driver is meant to be AD1848 compatible. * So, if you plan to support full duplex, check the chip revision first! */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* CODEC ports */ #define IADDR (_sound_port+4) #define IDATA (_sound_port+5) #define STATUS (_sound_port+6) #define PIO (_sound_port+7) /* IADDR bits */ #define INIT 0x80 #define MCE 0x40 #define TRD 0x20 /* STATUS bits */ #define INT 0x01 #define PRDY 0x02 #define PLR 0x04 #define PUL 0x08 #define SER 0x10 #define CRDY 0x20 #define CLR 0x40 #define CUL 0x80 /* IADDR registers */ #define LADC 0x00 #define RADC 0x01 #define LAUX1 0x02 #define RAUX1 0x03 #define LAUX2 0x04 #define RAUX2 0x05 #define LDAC 0x06 #define RDAC 0x07 #define FS 0x08 #define INTCON 0x09 #define PINCON 0x0A #define ERRSTAT 0x0B #define MODE_ID 0x0C #define LOOPBCK 0x0D #define PB_UCNT 0x0E #define PB_LCNT 0x0F #define NUMCODECRATES 16 /* DMA block size */ #define BLOCKLEN 512 #define WSSOUT(i, d) outportb(IADDR, i); \ outportb(IDATA, d); static int wss_detect(int input); static int wss_init(int input, int voices); static void wss_exit(int input); static int wss_set_mixer_volume(int volume); static int wss_buffer_size(void); static char wss_desc[256] = EMPTY_STRING; DIGI_DRIVER digi_wss = { DIGI_WINSOUNDSYS, empty_string, empty_string, "Windows Sound System", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, wss_detect, wss_init, wss_exit, wss_set_mixer_volume, NULL, NULL, NULL, wss_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }; static int wss_usedrate = 0; static int wss_stereo = TRUE; static int wss_16bits = TRUE; static int wss_dma_sel; static unsigned long wss_dma_addr; static int wss_dma_block; static int wss_in_use = FALSE; static int wss_detected = FALSE; struct codec_rate_struct { int freq; int divider; }; /* List of supported rates */ static struct codec_rate_struct codec_rates[NUMCODECRATES] = { { 5512, 0x01 }, { 6620, 0x0F }, { 8000, 0x00 }, { 9600, 0x0E }, { 11025, 0x03 }, { 16000, 0x02 }, { 18900, 0x05 }, { 22050, 0x07 }, { 27420, 0x04 }, { 32000, 0x06 }, { 33075, 0x0D }, { 37800, 0x09 }, { 44100, 0x0B }, { 48000, 0x0C }, { 54857, 0x08 }, /* These last two values are ILLEGAL, { 64000, 0x0A } but they may work on some devices. Check 'em out! */ }; /* return size of audiostream buffers */ static int wss_buffer_size(void) { return BLOCKLEN / (wss_stereo ? 2 : 1) / (wss_16bits ? 2 : 1); } /* WSS busy wait */ static void wss_wait(void) { int i = 0xFFFF; /* Wait for INIT bit to clear */ while ((inportb(_sound_port + 4) & INIT) || (i-- > 0)) ; } /* Our IRQ handler. Kinda short... */ static int wss_irq_handler(void) { /* Ack int */ outportb(STATUS, 0); wss_dma_block = (_dma_todo(_sound_dma) > BLOCKLEN) ? 1 : 0; _mix_some_samples(wss_dma_addr + wss_dma_block * BLOCKLEN, _dos_ds, TRUE); _eoi(_sound_irq); return 0; } END_OF_STATIC_FUNCTION(wss_irq_handler); static int wss_detect(int input) { int i, diff, bestdiff, freq; char tmp[1024]; if (input) return FALSE; if (wss_detected) return TRUE; if ((_sound_port < 0) || (_sound_irq < 0) || (_sound_dma < 0)) return FALSE; /* Select best sampling rate */ if (_sound_freq < 0) freq = 44100; else freq = _sound_freq; bestdiff = 10000000; for (i=0; i 0)) ; if (i < 1) return -1; /* Enter MCE */ outportb(IADDR, MCE | FS); wss_wait(); /* Set playback format */ i = codec_rates[wss_usedrate].divider; if (wss_stereo) i |= 0x10; if (wss_16bits) i |= 0x40; outportb(IDATA, i); wss_wait(); outportb(IADDR, 0); outportb(STATUS, 0); outportb(IADDR, PINCON); wss_wait(); outportb(IDATA, 0x2); /* Enable interrupts in Pin Control reg. */ _enable_irq(_sound_irq); _install_irq(_map_irq(_sound_irq), wss_irq_handler); _mix_some_samples(wss_dma_addr, _dos_ds, TRUE); _mix_some_samples(wss_dma_addr + BLOCKLEN, _dos_ds, TRUE); _dma_start(_sound_dma, wss_dma_addr, BLOCKLEN * 2, TRUE, FALSE); LOCK_FUNCTION(wss_irq_handler); LOCK_VARIABLE(wss_dma_addr); LOCK_VARIABLE(wss_dma_block); LOCK_VARIABLE(_sound_dma); _eoi(_sound_irq); /* Set playback length */ outportb(IADDR, PB_UCNT); wss_wait(); outportb(IDATA, (nsamples - 1) >> 8); outportb(IADDR, PB_LCNT); wss_wait(); outportb(IDATA, (nsamples - 1) & 0xFF); wss_wait(); outportb(IADDR, INTCON | MCE); wss_wait(); outportb(IDATA, 0x5); /* PEN - Playback Enable! */ outportb(IADDR, 0); /* Unmute outputs */ WSSOUT(LDAC, 0); WSSOUT(RDAC, 0); wss_in_use = TRUE; return 0; } static void wss_exit(int input) { if (!wss_in_use) return; /* Mute outputs */ WSSOUT(LDAC, 0x80); WSSOUT(RDAC, 0x80); /* Stop playback */ outportb(IADDR, MCE | INTCON); wss_wait(); outportb(IDATA, 0); outportb(IADDR, 0); outportb(STATUS, 0); _remove_irq(_map_irq(_sound_irq)); _restore_irq(_sound_irq); __dpmi_free_dos_memory(wss_dma_sel); _mixer_exit(); wss_in_use = FALSE; } static int wss_set_mixer_volume(int volume) { if (volume > 255) volume = 255; if (volume < 0) volume = 0; /* WSS has only attenuation regs, so we totally mute outputs to get silence w/volume 0 */ DISABLE(); if (!volume) { WSSOUT(RDAC, 0x80); WSSOUT(LDAC, 0x80); } else { WSSOUT(RDAC, 0x3F-volume/4); WSSOUT(LDAC, 0x3F-volume/4); } ENABLE(); return 0; } allegro-4.4.3.1/src/dos/ifsega2p.c0000664000175000017500000003020513437077643015520 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the IF-SEGA2/PCI (I-O DATA) controller. * * By S. Suzuki, * * based code by E.Watanabe (ifsega.c : IF-SEGA/ISA joystick driver). * * Test program and informations provided by Saka (sp2p : analog joystick * emulation driver for Win9x DOS Session + IF-SEGA/ISA, IF-SEGA2/PCI). */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* prototype */ int _sg_pci_init(void); void _sg_pci_exit(void); unsigned long _sg_pci_ioin(unsigned long offset); void _sg_pci_ioout(unsigned long offset, unsigned long data); static int sg_pci_poll(void); static int sg_pci_poll1(void); static int sg_pci_poll_sub(int num, int base); static int sg_pci_poll_sub2(int base); static int sg_pci_poll_sub3(int num, int count, int base); static void sg_pci_button_init(int num); /* grobal */ static unsigned long PowerVR_Physical_Address; static unsigned long PowerVR_Linear_Address; static int PowerVR_Linear_Selector; JOYSTICK_DRIVER joystick_sg2 = { JOY_TYPE_IFSEGA_PCI, NULL, NULL, "IF-SEGA2/PCI", _sg_pci_init, _sg_pci_exit, sg_pci_poll1, NULL, NULL, NULL, NULL }; /* _sg_pci_init: * Initialises the driver. */ int _sg_pci_init(void) { static char *name_b[] = { "A", "B", "C", "X", "Y", "Z", "L", "R", "Start" }; int i, j; __dpmi_regs r; num_joysticks = 4; PowerVR_Physical_Address = 0; PowerVR_Linear_Address = 0; PowerVR_Linear_Selector = 0; r.d.eax = 0x0000b101; /* PCI BIOS - INSTALLATION CHECK */ r.d.edi = 0x00000000; __dpmi_int(0x1a, &r); if (r.d.edx != 0x20494350) { /* ' ICP' */ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("PCI BIOS not installed")); return -1; } r.d.eax = 0x0000b102; /* PCI BIOS - FIND PCI DEVICE */ r.d.ecx = 0x00000046; /* device ID */ r.d.edx = 0x00001033; /* vendor ID */ r.d.esi = 0x00000000; /* device index */ __dpmi_int(0x1a, &r); if (r.h.ah != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("IF-SEGA2/PCI: device not found")); return -1; } r.d.eax = 0x0000b10a; /* READ CONFIGURATION DWORD */ /* BH = bus number */ /* BL = device/function number */ r.d.edi = 0x00000010; /* register number */ __dpmi_int(0x1a, &r); if (r.h.ah != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("IF-SEGA2/PCI: read configuration dword error")); return -1; } PowerVR_Physical_Address = r.d.ecx & 0xffff0000; if (_create_linear_mapping(&PowerVR_Linear_Address, PowerVR_Physical_Address, 0x10000) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("IF-SEGA2/PCI: _create_linear_mapping error")); return -1; } if (_create_selector(&PowerVR_Linear_Selector, PowerVR_Linear_Address, 0x10000) != 0) { _remove_linear_mapping(&PowerVR_Linear_Address); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("IF-SEGA2/PCI: _create_selector error")); return -1; } for (i = 0; i < num_joysticks; i++) { joy[i].flags = JOYFLAG_ANALOGUE; joy[i].num_sticks = 2; for (j = 0; j < 2; j++) { joy[i].stick[j].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[i].stick[j].num_axis = 2; joy[i].stick[j].axis[0].name = get_config_text("X"); joy[i].stick[j].axis[1].name = get_config_text("Y"); joy[i].stick[j].name = get_config_text("Pad"); } joy[i].num_buttons = 9; for (j = 0; j < 9; j++) { joy[i].button[j].name = get_config_text(name_b[j]); } } return 0; } /* _sg_pci_exit: * Shuts down the driver. */ void _sg_pci_exit(void) { _remove_linear_mapping(&PowerVR_Linear_Address); _remove_selector(&PowerVR_Linear_Selector); } /* sg_pci_poll: * Common - Updates the joystick status variables. */ static int sg_pci_poll(void) { int num = 0; num = sg_pci_poll_sub(num, 0x000); /* IFSEGA 1P */ if (num < num_joysticks) num = sg_pci_poll_sub(num, 0x200); /* IFSEGA 2P */ while (num < num_joysticks) { sg_pci_button_init(num); num++; } return 0; } static int sg_pci_poll_sub(int num, int base) { int i; int j; int a; int b; int num1; int result; i = 0x40; result = 0; _sg_pci_ioout(base, 0x1f); do { _sg_pci_ioout(base + 0x100, 0x60); a = _sg_pci_ioin(base + 0x100); if ((a & 0x07) == 0x01 || (a & 0x07) == 0x04) break; } while (i--); if (a & 0x0c) result |= 0x08; if (a & 0x03) result |= 0x04; _sg_pci_ioout(base + 0x100, 0x20); a = _sg_pci_ioin(base + 0x100); if (a & 0x0c) result |= 0x02; if (a & 0x03) result |= 0x01; switch (result) { case 0x0b: /* Normal Pad , Twin Stick , etc.. */ /*outportb(base,0x1f); */ /*outportb(base+2,0xe0); */ /*a = inportb(base+2); // L 1 0 0 */ _sg_pci_ioout(base, 0x1f); _sg_pci_ioout(base + 0x100, 0xe0); a = _sg_pci_ioin(base + 0x100); joy[num].button[6].b = !(a & 0x08); /*outportb(base+2,0x80); */ /*a = inportb(base+2); // R X Y Z */ _sg_pci_ioout(base + 0x100, 0x80); a = _sg_pci_ioin(base + 0x100); joy[num].button[7].b = !(a & 0x08); joy[num].button[3].b = !(a & 0x04); joy[num].button[4].b = !(a & 0x02); joy[num].button[5].b = !(a & 0x01); /*outportb(base+2,0xc0); // Start A C B */ /*a = inportb(base+2); */ _sg_pci_ioout(base + 0x100, 0xc0); a = _sg_pci_ioin(base + 0x100); joy[num].button[8].b = !(a & 0x08); joy[num].button[0].b = !(a & 0x04); joy[num].button[2].b = !(a & 0x02); joy[num].button[1].b = !(a & 0x01); /*outportb(base+2,0xa0); */ /*a = inportb(base+2); // axis R L D U */ _sg_pci_ioout(base + 0x100, 0xa0); a = _sg_pci_ioin(base + 0x100); joy[num].stick[0].axis[0].d1 = !(a & 0x04); joy[num].stick[0].axis[0].d2 = !(a & 0x08); joy[num].stick[0].axis[1].d1 = !(a & 0x01); joy[num].stick[0].axis[1].d2 = !(a & 0x02); for (j = 0; j <= 1; j++) { if (joy[num].stick[0].axis[j].d1) joy[num].stick[0].axis[j].pos = -128; else { if (joy[num].stick[0].axis[j].d2) joy[num].stick[0].axis[j].pos = 128; else joy[num].stick[0].axis[j].pos = 0; } } joy[num].stick[1].axis[0].d1 = 0; joy[num].stick[1].axis[0].d2 = 0; joy[num].stick[1].axis[1].d1 = 0; joy[num].stick[1].axis[1].d2 = 0; joy[num].stick[1].axis[0].pos = 0; joy[num].stick[1].axis[1].pos = 0; num++; break; case 0x05: switch (sg_pci_poll_sub2(base)) { case 0x00: /* Multi Controller , Racing Controller , etc.. */ case 0x01: sg_pci_poll_sub3(num, sg_pci_poll_sub2(base) * 2, base); num++; break; case 0x04: /* Multi-Terminal 6 */ sg_pci_poll_sub2(base); sg_pci_poll_sub2(base); sg_pci_poll_sub2(base); num1 = num; i = 6 + 1; while (num < num_joysticks) { sg_pci_button_init(num); if (!(--i)) break; a = sg_pci_poll_sub2(base); b = sg_pci_poll_sub2(base) * 2; if (a == 0x0f) continue; /* no pad */ if ((a == 0x0e) && (b == 6)) { sg_pci_poll_sub2(base); /* Shuttle Mouse */ sg_pci_poll_sub2(base); sg_pci_poll_sub2(base); sg_pci_poll_sub2(base); sg_pci_poll_sub2(base); sg_pci_poll_sub2(base); continue; } sg_pci_poll_sub3(num, b, base); num++; } if (num == num1) num++; break; default: sg_pci_button_init(num); } break; case 0x03: /* Shuttle Mouse */ default: sg_pci_button_init(num); num++; } /*outportb(base+2,0x60); */ _sg_pci_ioout(base + 0x100, 0x60); return num; } static int sg_pci_poll_sub2(int base) { int i = 0x100; int a; int b; /*a = inportb(base+2); */ /*outportb(base+2, a^0x20); */ a = _sg_pci_ioin(base + 0x100); _sg_pci_ioout(base + 0x100, a ^ 0x20); do { /*b = inportb(base+2); */ b = _sg_pci_ioin(base + 0x100); if ((a & 0x10) != (b & 0x10)) break; } while (i--); return (b & 0x0f); } static int sg_pci_poll_sub3(int num, int count, int base) { int i; int a; a = sg_pci_poll_sub2(base); /* axis R L D U (digital) */ joy[num].stick[0].axis[0].d1 = !(a & 0x04); joy[num].stick[0].axis[0].d2 = !(a & 0x08); joy[num].stick[0].axis[1].d1 = !(a & 0x01); joy[num].stick[0].axis[1].d2 = !(a & 0x02); a = sg_pci_poll_sub2(base); /* Start A C B */ joy[num].button[8].b = !(a & 0x08); joy[num].button[0].b = !(a & 0x04); joy[num].button[2].b = !(a & 0x02); joy[num].button[1].b = !(a & 0x01); a = sg_pci_poll_sub2(base); /* R X T Z */ joy[num].button[7].b = !(a & 0x08); joy[num].button[3].b = !(a & 0x04); joy[num].button[4].b = !(a & 0x02); joy[num].button[5].b = !(a & 0x01); a = sg_pci_poll_sub2(base); /* L */ joy[num].button[6].b = !(a & 0x08); joy[num].stick[1].axis[0].d1 = 0; joy[num].stick[1].axis[0].d2 = 0; joy[num].stick[1].axis[1].d1 = 0; joy[num].stick[1].axis[1].d2 = 0; joy[num].stick[1].axis[0].pos = 0; joy[num].stick[1].axis[1].pos = 0; if (count -= 4) joy[num].stick[0].axis[0].pos = ((sg_pci_poll_sub2(base) << 4) | sg_pci_poll_sub2(base)) - 128; else { for (i = 0; i <= 1; i++) { if (joy[num].stick[0].axis[i].d1) joy[num].stick[0].axis[i].pos = -128; else { if (joy[num].stick[0].axis[i].d2) joy[num].stick[0].axis[i].pos = 128; else joy[num].stick[0].axis[i].pos = 0; } } return 0; } if (count -= 2) joy[num].stick[0].axis[1].pos = ((sg_pci_poll_sub2(base) << 4) | sg_pci_poll_sub2(base)) - 128; else { if (joy[num].stick[0].axis[1].d1) joy[num].stick[0].axis[1].pos = -128; else { if (joy[num].stick[0].axis[1].d2) joy[num].stick[0].axis[1].pos = 128; else joy[num].stick[0].axis[1].pos = 0; } return 0; } if (count -= 2) joy[num].stick[1].axis[0].pos = ((sg_pci_poll_sub2(base) << 4) | sg_pci_poll_sub2(base)) - 128; else return 0; if (count -= 2) joy[num].stick[1].axis[1].pos = ((sg_pci_poll_sub2(base) << 4) | sg_pci_poll_sub2(base)) - 128; return 0; } static void sg_pci_button_init(int num) { int i; for (i = 0; i < 9; i++) { joy[num].button[i].b = 0; } for (i = 0; i <= 1; i++) { joy[num].stick[i].axis[0].d1 = 0; joy[num].stick[i].axis[0].d2 = 0; joy[num].stick[i].axis[1].d1 = 0; joy[num].stick[i].axis[1].d2 = 0; joy[num].stick[i].axis[0].pos = 0; joy[num].stick[i].axis[1].pos = 0; } } /* sg_pci_poll1: * 1P - Updates the joystick status variables. */ static int sg_pci_poll1(void) { return sg_pci_poll(); } /* offset 0x0000 0x0100 0x0200 0x0300 data 0x00?? */ unsigned long _sg_pci_ioin(unsigned long offset) { unsigned long in_data; unsigned long data; unsigned long data2; data2 = 0xff00b000 | offset; data = 0x00004000 | data2; _farsetsel(PowerVR_Linear_Selector); _farnspokel(0x0058, data); _farnspokel(0x0058, data2); in_data = _farnspeekl(0x0058); _farnspokel(0x0058, data); in_data &= 0xff; return (in_data); } /* offset 0x0000 0x0100 0x0200 0x0300 data 0x00?? */ void _sg_pci_ioout(unsigned long offset, unsigned long data) { unsigned long data2; data2 = 0xffff7000 | offset | data; data = 0x00008000 | data2; _farsetsel(PowerVR_Linear_Selector); _farnspokel(0x0058, data); _farnspokel(0x0058, data2); _farnspokel(0x0058, data); } allegro-4.4.3.1/src/dos/emu8kmid.c0000664000175000017500000003144013437077643015545 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * AWE32/EMU8000 driver for the MIDI player. * * By George Foot. * * Modified by J. Flynn to remove floating point log calculations * during interrupt - replaced by precomputed lookup table. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #include "emu8k.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* variables from awedata.c, containing the envelope data from synthgm.sf2 */ extern short int _awe_sf_defaults[]; extern int _awe_sf_num_presets; extern short int _awe_sf_presets[]; extern short int _awe_sf_splits[]; extern short int _awe_sf_gens[]; extern int _awe_sf_sample_data[]; /* external interface to the AWE32 driver */ static int awe32_detect(int input); static int awe32_init(int input, int voices); static void awe32_exit(int input); static void awe32_key_on(int inst, int note, int bend, int vol, int pan); static void awe32_key_off(int voice); static void _awe32_do_note(int inst, int note, int bend, int vol, int pan); static void awe32_set_volume(int voice, int vol); static void awe32_set_pitch(int voice, int note, int bend); static void translate_soundfont_into_something_useful(void); static void destroy_useful_version_of_soundfont(void); static struct midi_preset_t { /* struct to hold envelope data for each preset */ int num_splits; /* number of splits in this preset */ struct envparms_t **split; /* array of num_splits pointers to envelope data */ } *midi_preset; /* global variable to hold the data */ static struct envparms_t **voice_envelope; /* array of pointers pointing at the envelope playing on each voice */ static int *exclusive_class_info; /* exclusive class information */ static const unsigned char attentbl[] = /* logarithm table */ { 255, 255, 221, 199, 184, 172, 162, 154, 147, 141, 135, 130, 125, 121, 117, 113, 110, 107, 104, 101, 98, 95, 93, 91, 88, 86, 84, 82, 80, 78, 76, 75, 73, 71, 70, 68, 67, 65, 64, 62, 61, 60, 59, 57, 56, 55, 54, 53, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 39, 38, 37, 36, 35, 34, 34, 33, 32, 31, 31, 30, 29, 28, 28, 27, 26, 25, 25, 24, 23, 23, 22, 22, 21, 20, 20, 19, 18, 18, 17, 17, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, }; static char awe32_desc[256] = EMPTY_STRING; MIDI_DRIVER midi_awe32 = { MIDI_AWE32, /* id */ empty_string, /* name */ empty_string, /* desc */ "AWE32/EMU8000", /* ASCII name */ 32, 0, 32, 32, -1, -1, /* voices, basevoice, max_voices, def_voices, xmin, xmax */ awe32_detect, /* detect */ awe32_init, /* init */ awe32_exit, /* exit */ NULL, /* mixer_set_volume */ NULL, /* mixer_get_volume */ NULL, /* raw_midi */ _dummy_load_patches, /* load_patches */ _dummy_adjust_patches, /* adjust_patches */ awe32_key_on, /* key_on */ awe32_key_off, /* key_off */ awe32_set_volume, /* set_volume */ awe32_set_pitch, /* set_pitch */ _dummy_noop2, /* set_pan */ _dummy_noop2 /* set_vibrato */ }; /* awe32_key_on: * Triggers the specified voice. The instrument is specified as a GM * patch number, pitch as a midi note number, and volume from 0-127. * The bend parameter is _not_ expressed as a midi pitch bend value. * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp). * Drum sounds are indicated by passing an instrument number greater than * 128, in which case the sound is GM percussion key #(inst-128). */ static void awe32_key_on(int inst, int note, int bend, int vol, int pan) { if (inst > 127) { /* drum sound? */ _awe32_do_note(128, inst - 128, bend, vol, pan); } else { /* regular instrument */ _awe32_do_note(inst, note, bend, vol, pan); } } END_OF_STATIC_FUNCTION(awe32_key_on); /* _awe32_do_note: * Actually plays the note as described above; the above function just remaps * the drums. */ static void _awe32_do_note(int inst, int note, int bend, int vol, int pan) { int voice; int i; envparms_t *env; int key, vel; int atten; int pan_pos; /* EMU8000 pan is back-to-front and twice the scale */ pan = 0x100 - 2 * pan; if (pan > 0xff) pan = 0xff; if (pan < 0x00) pan = 0x00; for (i=0; i= env->minkey) && (note <= env->maxkey) && (vol >= env->minvel) && (vol <= env->maxvel)) { /* get a voice (any voice) to play it on */ voice = _midi_allocate_voice(-1, -1); /* did we get one? */ if (voice >= 0) { /* set the current envelope for this voice */ voice_envelope[voice] = env; /* set pitch and velocity */ key = note * 0x1000 + bend; vel = vol; /* override key and velocity if envelope says so */ if ((env->key >= 0) && (env->key <= 127)) key = env->key * 0x1000; if ((env->vel >= 0) && (env->vel <= 127)) vel = env->vel; /* check key and velocity numbers are within range */ if (key > 0x7ffff) key = 0x7ffff; if (key < 0) key = 0; if (vel > 127) vel = 127; if (vel < 0) vel = 0; /* add one-off information to the envelope (these have no side-effects on the other voices using this envelope) */ env->ip = env->ipbase + (env->ipscale * key) / 1200; /* remap MIDI velocity to attenuation */ if (vel) atten = env->atten + attentbl[vel]; else atten = 0xff; if (atten < 0x00) atten = 0x00; if (atten > 0xff) atten = 0xff; /* update it in the envelope */ env->ifatn = env->filter + atten; /* modify pan with envelope's built-in pan */ if (pan < 0x80) { pan_pos = (pan * env->pan) / 0x80; } else { pan_pos = env->pan + (pan - 0x80) * (256 - env->pan) / 0x80; } if (pan_pos < 0x00) pan_pos = 0x00; if (pan_pos > 0xff) pan_pos = 0xff; /* update pan in the envelope */ env->psst = (pan_pos << 24) + env->loopst; /* test exclusive class */ exclusive_class_info[voice] = (inst << 8) + env->exc; if (env->exc) { int chan; for (chan=0; chan<32; chan++) if ((chan != voice) && (exclusive_class_info[chan] == exclusive_class_info[voice])) emu8k_terminatesound(chan); } /* start the note playing */ emu8k_startsound(voice, env); } } } } END_OF_STATIC_FUNCTION(_awe32_do_note); /* awe32_set_*: * Modulation routines */ static void awe32_set_volume(int voice, int vol) { int atten; struct envparms_t *env; /* get envelope in use on this voice */ env = voice_envelope[voice]; /* allow envelope to override new volume */ if ((env->vel >= 0) && (env->vel <= 127)) vol = env->vel; /* check velocity number is within range */ if (vol > 127) vol = 127; if (vol < 0) vol = 0; /* remap MIDI velocity to attenuation */ if (vol) atten = env->atten + attentbl[vol]; else atten = 0xff; if (atten < 0x00) atten = 0x00; if (atten > 0xff) atten = 0xff; emu8k_modulate_atten(voice, atten); } END_OF_STATIC_FUNCTION(awe32_set_volume); static void awe32_set_pitch(int voice, int note, int bend) { struct envparms_t *env; int key, ip; /* get envelope in use on this voice */ env = voice_envelope[voice]; key = note * 0x1000 + bend; /* override key if envelope says so */ if ((env->key >= 0) && (env->key <= 127)) key = env->key * 0x1000; /* check key number is within range */ if (key > 0x7ffff) key = 0x7ffff; if (key < 0) key = 0; ip = env->ipbase + (env->ipscale * key) / 1200; emu8k_modulate_ip(voice, ip); } END_OF_STATIC_FUNCTION(awe32_set_pitch); /* awe32_key_off: * Hey, guess what this does :-) */ static void awe32_key_off(int voice) { emu8k_releasesound(voice, voice_envelope[voice]); } END_OF_STATIC_FUNCTION(awe32_key_off); /* awe32_detect: * AWE32/EMU8000 detection routine. */ static int awe32_detect(int input) { if (input) return FALSE; if (emu8k_detect()) { uszprintf(awe32_desc, sizeof(awe32_desc), get_config_text("SB AWE32/compatible on port 0x%04x"), _emu8k_baseport); midi_awe32.desc = awe32_desc; return TRUE; } ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("AWE32 not detected")); return FALSE; } /* awe32_lockmem: * Locks required memory blocks */ static void awe32_lockmem(void) { /* functions */ LOCK_FUNCTION(awe32_key_on); LOCK_FUNCTION(awe32_key_off); LOCK_FUNCTION(_awe32_do_note); LOCK_FUNCTION(awe32_set_volume); LOCK_FUNCTION(awe32_set_pitch); /* data */ LOCK_VARIABLE(midi_preset); LOCK_VARIABLE(voice_envelope); LOCK_VARIABLE(exclusive_class_info); LOCK_VARIABLE(midi_awe32); LOCK_VARIABLE(attentbl); /* stuff in emu8k.c */ emu8k_lock(); } /* awe32_init: * Setup the AWE32/EMU8000 driver. */ static int awe32_init(int input, int voices) { int chan; emu8k_init(); translate_soundfont_into_something_useful(); voice_envelope = (struct envparms_t **)_lock_malloc(32 * sizeof(struct envparms_t *)); exclusive_class_info = (int *)_lock_malloc(32 * sizeof(int)); awe32_lockmem(); for (chan=0; chan<32; chan++) { voice_envelope[chan] = NULL; exclusive_class_info[chan] = 0; } return 0; } /* awe32_exit: * Cleanup when we are finished. */ static void awe32_exit(int input) { int i; for (i=0; i<_emu8k_numchannels; i++) emu8k_terminatesound(i); destroy_useful_version_of_soundfont(); _AL_FREE(voice_envelope); _AL_FREE(exclusive_class_info); } /* translate_soundfont_into_something_useful: * Like it says, translate the soundfont data into something we can use * when playing notes. */ static void translate_soundfont_into_something_useful(void) { int p, s, gen, weirdo; struct midi_preset_t *thing_to_write = NULL; generators_t temp_gens; int global_split = 0, global_weirdo = 0, num_weirdos; midi_preset = (struct midi_preset_t *)_lock_malloc(129 * sizeof(struct midi_preset_t)); for (p=0; p<_awe_sf_num_presets; p++) { if (_awe_sf_presets[p * 3 + 1] == 0) { thing_to_write = &midi_preset[_awe_sf_presets[p * 3 + 0]]; } else if (_awe_sf_presets[p * 3 + 1] == 128) { thing_to_write = &midi_preset[128]; } else { thing_to_write = NULL; } if (thing_to_write) { thing_to_write->num_splits = _awe_sf_presets[p * 3 + 2]; thing_to_write->split = (struct envparms_t **)_lock_malloc(thing_to_write->num_splits * sizeof(struct envparms_t *)); for (s=0; snum_splits; s++) { for (gen=0; gensplit[s] = emu8k_createenvelope(temp_gens); } } else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("AWE32 driver: had trouble with the embedded data")); } } } /* destroy_useful_version_of_soundfont: * Destroys the data created by the above function */ static void destroy_useful_version_of_soundfont(void) { int p, s; for (p=0; p<129; p++) { if (midi_preset[p].num_splits > 0) { for (s=0; s= 0x100000) { /* map into linear memory */ meminfo.address = physaddr; meminfo.size = size; if (__dpmi_physical_address_mapping(&meminfo) != 0) return -1; *linear = meminfo.address; /* lock the linear memory range */ __dpmi_lock_linear_region(&meminfo); } else /* exploit 1 -> 1 physical to linear mapping in low megabyte */ *linear = physaddr; return 0; } /* _remove_linear_mapping: * Frees the DPMI resources being used to map a linear address range. */ void _remove_linear_mapping(unsigned long *linear) { __dpmi_meminfo meminfo; if (*linear) { if (*linear >= 0x100000) { meminfo.address = *linear; __dpmi_free_physical_address_mapping(&meminfo); } *linear = 0; } } /* _create_selector: * Allocates a selector to access a region of linear memory. */ int _create_selector(int *segment, unsigned long linear, int size) { /* allocate an ldt descriptor */ *segment = __dpmi_allocate_ldt_descriptors(1); if (*segment < 0) { *segment = 0; return -1; } /* set the descriptor base and limit */ __dpmi_set_segment_base_address(*segment, linear); __dpmi_set_segment_limit(*segment, MAX(size-1, 0xFFFF)); return 0; } /* _remove_selector: * Frees a DPMI segment selector. */ void _remove_selector(int *segment) { if (*segment) { __dpmi_free_ldt_descriptor(*segment); *segment = 0; } } /* _unlock_dpmi_data: * Unlocks a memory region (this is needed when repeatedly allocating and * freeing large samples, to prevent all of memory ending up in a locked * state). */ void _unlock_dpmi_data(void *addr, int size) { unsigned long baseaddr; __dpmi_meminfo mem; __dpmi_get_segment_base_address(_default_ds(), &baseaddr); mem.address = baseaddr + (unsigned long)addr; mem.size = size; __dpmi_unlock_linear_region(&mem); } allegro-4.4.3.1/src/dos/swpp.c0000664000175000017500000004332713437077643015022 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Preliminary driver for Microsoft Sidewinder 3D/Precision/ * Force Feedback Pro Joysticks. * * By Acho A. Tang. * * Notes on the 3D Pro: * - digital initialization is not 100% reliable, * - toggling the TM/CH switch will put the joystick back * in analogue mode, * - the stick must remain in a near-neutral position during * detection or the process will fail. * * Notes on the Force Feedback Pro: * - the driver has not been tested on a real FF Pro and it * lacks force feedback support. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define SWPP_DEBUG 0 /* Compiler switch for a debug-only build */ #define SWPP_VERBOSE 0 /* Compiler switch for debug messages */ #define SWPP_NPORTS 2 /* Number of game ports to scan */ #define SWPP_NSCANS 8 /* Number of scan attempts on each port */ #define SWPP_NSUCCESS 4 /* Number of successful attempts to pass detection */ #define SWPP_WAITID 800 /* Max wait for ID packet triplets [800 us](arbitrary) */ #define SWPP_START 400 /* Max wait for the first data triplet [400 us](arbitrary) */ #define SWPP_STROBE 50 /* Max wait for each successive data triplet [50 us](theoretical minimum [11 us]) */ #define SWPP_CMDELAY 80 /* Interrupt command delay [80 us](must be within X timer's period [354.2 us]) */ #define SWPP_MAXBITS 256 /* Max number of triplets */ #define NTSC_CLOCK 14318180.0 #define SW3D_POLLOUT 3000 /* Max analogue polling timeout [3 ms] */ #define SW3D_FID 32 #define SW3D_TSUB1 (115*2+(305-115)*2/SW3D_FID) /* SW3D A->D time constant 1 */ #define SW3D_TSUB2 (SW3D_TSUB1+697+775) /* SW3D A->D time constant 2 */ #define SW3D_TSUB3 (SW3D_TSUB1+288+312) /* SW3D A->D time constant 3 */ #define SWPP_NID 57 /* No. of triplets in a Precision Pro full packet */ #define SWFF_NID 30 /* No. of triplets in a Force Feedback Pro full packet *** UNCONFIRMED *** */ #define SW3D_NID 226 /* No. of triplets in a 3D Pro full packet */ #define SWPP_NDATA 16 /* No. of triplets in a Precision Pro data packet */ #define SWFF_NDATA 16 /* No. of triplets in a Force Feedback Pro data packet */ #define SW3D_NDATA 22 /* No. of triplets in a 3D Pro data packet */ #define SW3D_NSTREAM (SW3D_NDATA*3) enum { SWXX=0, SWPP, SWFF, SW3D }; /* driver functions */ static int swpp_init(void); static void swpp_exit(void); static int swpp_poll(void); #if !SWPP_DEBUG JOYSTICK_DRIVER joystick_sw_pp = { JOY_TYPE_SIDEWINDER_PP, empty_string, empty_string, "Sidewinder Precision Pro", swpp_init, swpp_exit, swpp_poll, NULL, /* AL_METHOD(int, save_data, (void)); */ NULL, /* AL_METHOD(int, load_data, (void)); */ NULL, /* AL_METHOD(AL_CONST char *, calibrate_name, (int n)); */ NULL /* AL_METHOD(int, calibrate, (int n)); */ }; #endif /* global context */ static struct SWINF_TYPE { unsigned int port, speed, mode, nid, ndata; unsigned int buttons; int hatx, haty; int x, y; int throttle, twist; } swinf; static int swpp_initialized = 0; /* utility macros */ #define US2COUNT(u, s) ((u * s) >> 10) #define WAITSWPP(p, c) do inportb(p); while (--c > 0) /* estimates game port speed in queries/ms (WARNING: timer 2 will be reprogrammed) */ extern void _swpp_get_portspeed(unsigned int port, unsigned int npasses, unsigned int *nqueries, unsigned int *elapsed); static unsigned int get_portspeed(unsigned int port) { #define NQUERIES 1024 unsigned int elapsed[5], nqueries[5]={1,NQUERIES+1,NQUERIES+1,NQUERIES+1,1}; unsigned int emin=-1, emax=0, e, imin=0, imax=0, i; double e64, r64; unsigned char ah, al; ah = al = inportb(0x61); al &= ~2; al |= 1; outportb(0x61, al); /* enable timer channel 2 */ outportb(0x43, 0xb4); /* wake timer */ _enter_critical(); _swpp_get_portspeed(port, 5, nqueries, elapsed); _exit_critical(); outportb(0x61, ah); for (i=1; i<4; i++) { e = elapsed[i]; if (e < emin) { emin = e; imin = i; } if (e >= emax) { emax = e; imax = i; } } e = elapsed[6-imin-imax] - elapsed[4]; if ((int)e > 0) { r64 = (double)e * 1000000; e64 = 1193182.0 * NQUERIES * 1024; e64 /= r64; e = (unsigned int)e64; } else e = 0; #if SWPP_VERBOSE printf("SWPP get_portspeed(%xh): %u queries/ms\n", port, e); #endif return(e); #undef NQUERIES } /* attempts to switch the Sidewinder 3D Pro into digital mode * * WARNING: No time-out during polling. Computer may freeze if timer gets * stuck although it rarely happens. A better solution is to use * timer 0 interrupt provided that it's not being used by Allegro. */ extern void _swpp_init_digital(unsigned int port, unsigned int ncmds, unsigned char *cmdiv, unsigned int *timeout); static int init_digital(unsigned int port, unsigned int speed) { unsigned char cmdiv[6]; unsigned char ah, al; unsigned int i; ah = al = inportb(0x61); al &= ~2; al |= 1; outportb(0x61, al); /* enable timer channel 2 */ outportb(0x43, 0xb0); /* wake timer */ i = NTSC_CLOCK * SW3D_TSUB1 / 24000000; /* clock divisor for command 1 delay */ cmdiv[0] = i & 0xff; cmdiv[1] = i>>8; i = NTSC_CLOCK * SW3D_TSUB2 / 24000000; /* clock divisor for command 2 delay */ cmdiv[2] = i & 0xff; cmdiv[3] = i>>8; i = NTSC_CLOCK * SW3D_TSUB3 / 24000000; /* clock divisor for command 3 delay */ cmdiv[4] = i & 0xff; cmdiv[5] = i>>8; i = US2COUNT(SW3D_POLLOUT * 3, speed); /* axis 0 timeout */ _enter_critical(); _swpp_init_digital(port, 3, cmdiv, &i); _exit_critical(); outportb(0x61, ah); #if SWPP_VERBOSE printf("SWPP init_digital(%xh): D1=%x%02x D2=%x%02x D3=%x%02x\n", port, cmdiv[1], cmdiv[0], cmdiv[3], cmdiv[2], cmdiv[5], cmdiv[4]); #endif return(i); } /* standard 4-axis polling */ extern void _swpp_read_analogue(unsigned int port, unsigned int *outbuf, unsigned int pollout); static int read_analogue(unsigned int port, unsigned int speed, unsigned char *buf) { unsigned int outbuf[6]; unsigned int pollout, i; if (inportb(port)) { pollout = US2COUNT(SW3D_POLLOUT, speed); _enter_critical(); _swpp_read_analogue(port, outbuf, pollout); _exit_critical(); if (!outbuf[5]) for (i=1; i<5; i++) { if (outbuf[i] >= pollout) outbuf[i] = -1; } } else { for (i=0; i<6; i++) outbuf[i] = -1; pollout = -1; } #if SWPP_VERBOSE i = outbuf[0]; printf("SWPP read_analogue(%xh): limit=%d A0=%d A1=%d A2=%d A3=%d B=%04x\n", port, pollout, outbuf[1], outbuf[2], outbuf[3], outbuf[4], (i&1)|((i&2)<<3)|((i&4)<<6)|((i&8)<<9)); #endif for (i=0; i<6; i++) buf[i] = (unsigned char)outbuf[i]; return(~outbuf[0] & 0x10); } /* thanks to Vojtech (vojtech@suse.cz) for the technical infos */ static unsigned int read_packet(unsigned int port, unsigned int speed, unsigned char *buf, int length, int id) { int timeout, start, strobe, cmdelay, cmout=0, count=0, i; unsigned char ah, al=0; if (id) { timeout = start = US2COUNT(SWPP_WAITID, speed); cmdelay = US2COUNT(SWPP_CMDELAY, speed); _enter_critical(); outportb(port, 0); al = inportb(port); do { ah = al; al = inportb(port); /* rising edge on button 0 */ if (al & ~ah & 0x10) { buf[count++] = al >> 5; if (count >= length) break; timeout = start; } /* falling edge on axis 0 */ if (cmdelay && ~al & ah & 0x01) cmout = 1; if (cmout && !(--cmdelay)) { cmout = 0; outportb(port, 0); } } while (--timeout); _exit_critical(); } else { timeout = start = US2COUNT(SWPP_START, speed); strobe = US2COUNT(SWPP_STROBE, speed); _enter_critical(); outportb(port, 0); al = inportb(port); do { ah = al; al = inportb(port); /* rising edge on button 0 */ if (al & ~ah & 0x10) { buf[count++] = al >> 5; if (count >= length) break; timeout = strobe; } } while (--timeout); _exit_critical(); } #if SWPP_VERBOSE printf("SWPP read_packet(%xh): %d triplets [", port, count); for (i=0; i> 2; buf[length] &= 3; for (i=0; i 29 && shift < 32) { pack64[0] |= temp32<>(32-shift); } else pack64[shift>>5 & 1] |= temp32<<(shift & 0x1f); shift += 3; } if ((pack64[0]^0x80) & 0x80808080 || pack64[1] & 0x80808080) continue; temp32 = pack64[0]; do sum += temp32 & 0x0f; while (temp32 >>= 4); temp32 = pack64[1]; do sum += temp32 & 0x0f; while (temp32 >>= 4); if (!(sum & 0x0f)) { ((unsigned long *)buf)[0] = pack64[0]; ((unsigned long *)buf)[1] = pack64[1]; return(1); } } return(0); } /* parses SWPP triplets into meaningful values */ static void decode_swpp(struct SWINF_TYPE *inf, unsigned char *buf) { int data, pos; data = buf[0] | buf[1]<<3 | buf[2]<<6; inf->buttons = ~data & 0x1ff; data = buf[3] | buf[4]<<3 | buf[5]<<6 | (buf[6]&1)<<9; inf->x = (data >> 2) - 128; data = (buf[6]&6)>>1 | buf[7]<<2 | buf[8]<<5 | (buf[9]&3)<<8; inf->y = (data >> 2) - 128; data = (buf[9]&4)>>2 | buf[10]<<1 | buf[11]<<4; data = ~data & 0x7f; inf->throttle = (data << 1) + (data >> 6) - 128; data = buf[12] | buf[13]<<3; inf->twist = (data << 2) + (data >> 4) - 128; data = buf[14] | (buf[15]&1)<<3; data = (1 << (data - 1)) & 0xff; if (data & 0xe0) pos = -128; else if (data & 0x0e) pos = 127; else pos = 0; inf->hatx = pos; if (data & 0x83) pos = -128; else if (data & 0x38) pos = 127; else pos = 0; inf->haty = pos; #if SWPP_VERBOSE printf("SWPP decode_swpp(): x=%d y=%d tw=%d th=%d hx=%d hy=%d B=%03x\n", inf->x, inf->y, inf->twist, inf->throttle, inf->hatx, inf->haty, inf->buttons); #endif } /* parse packed SW3D triplets into meaningful values */ static void decode_sw3d(struct SWINF_TYPE *inf, unsigned char *buf) { int data, pos; data = (buf[1]&0x7f) | (buf[4]&0x40)<<1; inf->buttons = (~data & 0xff) | (buf[4]&0x20)<<3; data = (buf[0]&0x38)<<4 | (buf[2]&0x7f); inf->x = (data >> 2) - 128; data = (buf[0]&0x07)<<7 | (buf[3]&0x7f); inf->y = (data >> 2) - 128; data = (buf[4]&0x18)<<4 | (buf[5]&0x7f); inf->twist = (data >> 1) - 128; data = (buf[4]&0x07)<<7 | (buf[6]&0x7f); data = ~data & 0x3ff; inf->throttle = (data >> 2) -128; data = (buf[0]&0x40)>>3 | (buf[7]&0x70)>>4; data = (1 << (data - 1)) & 0xff; if (data & 0xe0) pos = -128; else if (data & 0x0e) pos = 127; else pos = 0; inf->hatx = pos; if (data & 0x83) pos = -128; else if (data & 0x38) pos = 127; else pos = 0; inf->haty = pos; #if SWPP_VERBOSE printf("SWPP decode_sw3d(): x=%d y=%d tw=%d th=%d hx=%d hy=%d B=%03x\n", inf->x,inf->y,inf->twist,inf->throttle,inf->hatx,inf->haty,inf->buttons); #endif } /* initializes the driver */ static int swpp_init(void) { unsigned char buf[SWPP_MAXBITS]; unsigned int portlist[SWPP_NPORTS]={0x201,0x200}; unsigned int port=-1, speed=-1, mode=-1, ndata=-1, nid=-1, avgspeed=0; unsigned int tries=SWPP_NSCANS, lockport=0, success=0, counter, i; #if !SWPP_DEBUG /* fill joystick info */ num_joysticks = 1; joy[0].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].num_sticks = 4; joy[0].num_buttons = 9; joy[0].stick[0].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].stick[0].num_axis = 2; joy[0].stick[0].name = get_config_text("Stick"); joy[0].stick[0].axis[0].name = get_config_text("X"); joy[0].stick[0].axis[1].name = get_config_text("Y"); joy[0].stick[1].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].stick[1].num_axis = 1; joy[0].stick[1].name = get_config_text("Twist"); joy[0].stick[1].axis[0].name = get_config_text(""); joy[0].stick[2].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].stick[2].num_axis = 1; joy[0].stick[2].name = get_config_text("Throttle"); joy[0].stick[2].axis[0].name = get_config_text(""); joy[0].stick[3].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[0].stick[3].num_axis = 2; joy[0].stick[3].name = get_config_text("Hat"); joy[0].stick[3].axis[0].name = get_config_text("X"); joy[0].stick[3].axis[1].name = get_config_text("Y"); joy[0].button[0].name = get_config_text("B1"); joy[0].button[1].name = get_config_text("B2"); joy[0].button[2].name = get_config_text("B3"); joy[0].button[3].name = get_config_text("B4"); joy[0].button[4].name = get_config_text("B5"); joy[0].button[5].name = get_config_text("B6"); joy[0].button[6].name = get_config_text("B7"); joy[0].button[7].name = get_config_text("B8"); joy[0].button[8].name = get_config_text("B9"); #endif if (swpp_initialized) { read_packet(swinf.port, swinf.speed, buf, SWPP_MAXBITS, 1); counter = US2COUNT(50000, swinf.speed); WAITSWPP(swinf.port, counter); return(0); } /* do a simple detection run on each port */ do { i = 0; do { if (!lockport) port = portlist[i]; /* check port speed */ if (!(speed = get_portspeed(port))) continue; counter = US2COUNT(50000, speed); WAITSWPP(port, counter); /* check X timer */ if (!read_analogue(port, speed, buf)) continue; counter = US2COUNT(50000, speed); WAITSWPP(port, counter); /* check ID */ if (!(nid = read_packet(port, speed, buf, SWPP_MAXBITS, 1))) { /* initiate digital mode and recheck ID */ if (!init_digital(port, speed)) continue; counter = US2COUNT(300000, speed); WAITSWPP(port, counter); if (!(nid = read_packet(port, speed, buf, SWPP_MAXBITS, 1))) continue; } counter = US2COUNT(50000, speed); WAITSWPP(port, counter); lockport = 1; /* check packet length and parity */ ndata = read_packet(port, speed, buf, SWPP_MAXBITS, 0); counter = US2COUNT(50000, speed); WAITSWPP(port, counter); mode = SWXX; if (nid == SWPP_NID) { if (ndata != SWPP_NDATA || !check_parity(buf, ndata)) continue; mode = SWPP; } else if (nid >= SW3D_NID) { if (ndata < SW3D_NSTREAM || !pack_sw3d(buf, ndata)) continue; mode = SW3D; nid = SW3D_NID; ndata = SW3D_NSTREAM; } else { if (ndata != SWFF_NDATA || !check_parity(buf, ndata)) continue; mode = SWFF; } avgspeed += speed; success++; } while (!lockport && ++i < SWPP_NPORTS); } while (success < SWPP_NSUCCESS && --tries + success >= SWPP_NSUCCESS); if (success < SWPP_NSUCCESS) { swinf.mode = mode; return(-1); } avgspeed /= SWPP_NSUCCESS; memset(&swinf, 0, sizeof(struct SWINF_TYPE)); swinf.port = port; swinf.speed = avgspeed; swinf.mode = mode; swinf.nid = nid; swinf.ndata = ndata; swpp_initialized = 1; #if SWPP_VERBOSE printf("SWPP swpp_init(): port=%xh speed=%d mode=%d nid=%d ndata=%d\n",port, avgspeed, mode, nid, ndata); #endif return(0); } /* polls the joystick state */ static int swpp_poll(void) { unsigned char buf[SWPP_MAXBITS]; unsigned int i; int d; switch (swinf.mode) { case SWPP: case SWFF: if (read_packet(swinf.port, swinf.speed, buf, swinf.ndata, 0) == swinf.ndata) if (check_parity(buf, swinf.ndata)) decode_swpp(&swinf, buf); break; case SW3D: if ((i = read_packet(swinf.port, swinf.speed, buf, swinf.ndata+1, 0)) >= swinf.ndata) if (pack_sw3d(buf, i)) decode_sw3d(&swinf, buf); break; } #if !SWPP_DEBUG d = swinf.x; joy[0].stick[0].axis[0].pos = d; joy[0].stick[0].axis[0].d1 = d <= -64; joy[0].stick[0].axis[0].d2 = d >= 64; d = swinf.y; joy[0].stick[0].axis[1].pos = d; joy[0].stick[0].axis[1].d1 = d <= -64; joy[0].stick[0].axis[1].d2 = d >= 64; d = swinf.twist; joy[0].stick[1].axis[0].pos = d; joy[0].stick[1].axis[0].d1 = d <= -64; joy[0].stick[1].axis[0].d2 = d >= 64; d = swinf.throttle; joy[0].stick[2].axis[0].pos = d; joy[0].stick[2].axis[0].d1 = d <= -64; joy[0].stick[2].axis[0].d2 = d >= 64; d = swinf.hatx; joy[0].stick[3].axis[0].pos = d; joy[0].stick[3].axis[0].d1 = d <= -64; joy[0].stick[3].axis[0].d2 = d >= 64; d = swinf.haty; joy[0].stick[3].axis[1].pos = d; joy[0].stick[3].axis[1].d1 = d <= -64; joy[0].stick[3].axis[1].d2 = d >= 64; d = swinf.buttons; for (i=0; i<9; i++) joy[0].button[i].b = d & (1 << i); #endif return(0); } /* shuts down the driver */ static void swpp_exit(void) {} #if SWPP_DEBUG int main(void) { swpp_init(); if (swinf.mode != -1) { printf("\nFound "); switch (swinf.mode) { default: case SWXX: printf("unsupported Sidewinder input device\n"); break; case SWPP: printf("Sidewinder Precision Pro joystick\n"); break; case SWFF: printf("Sidewinder Force Feedback Pro joystick\n"); break; case SW3D: printf("Sidewinder 3D Pro joystick\n"); } } else printf("\nNo Sidewinder joystick found\n"); return(0); } #endif allegro-4.4.3.1/src/dos/ifsega.c0000664000175000017500000002056213437077643015263 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the IF-SEGA/ISA (I-O DATA) controller. * * By E. Watanabe (99/09/08), * based on sample code by Earle F. Philhower, III / Kerry High (SNES). * */ #include "allegro.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define IFSEGAISA_BASE 0x1001 /* driver functions */ static int sg_init(void); static void sg_exit(void); static int sg_poll(int); static int sg1_poll(void); static int sg_poll_sub(int num, int base); static int sg_poll_sub2(int base); static int sg_poll_sub3(int num, int count, int base); static int pad_kind(int base); static void sg_button_init(int num); JOYSTICK_DRIVER joystick_sg1 = { JOY_TYPE_IFSEGA_ISA, NULL, NULL, "IF-SEGA/ISA", sg_init, sg_exit, sg1_poll, NULL, NULL, NULL, NULL }; /* sg_init: * Initialises the driver. */ static int sg_init(void) { static char *name_b[] = { "A", "B", "C", "X", "Y", "Z", "L", "R", "Start" }; int i, j; num_joysticks = 4; for (i=0; i #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* external interface to the digital SB driver */ static int sb_detect(int input); static int sb_init(int input, int voices); static void sb_exit(int input); static int sb_set_mixer_volume(int volume); static int sb_buffer_size(void); static int sb_rec_cap_rate(int bits, int stereo); static int sb_rec_cap_parm(int rate, int bits, int stereo); static int sb_rec_source(int source); static int sb_rec_start(int rate, int bits, int stereo); static void sb_rec_stop(void); static int sb_rec_read(void *buf); static char sb_desc[256] = EMPTY_STRING; #define SB_DRIVER_CONTENTS \ 0, 0, \ MIXER_MAX_SFX, MIXER_DEF_SFX, \ sb_detect, \ sb_init, \ sb_exit, \ sb_set_mixer_volume, \ NULL, \ NULL, \ NULL, \ sb_buffer_size, \ _mixer_init_voice, \ _mixer_release_voice, \ _mixer_start_voice, \ _mixer_stop_voice, \ _mixer_loop_voice, \ _mixer_get_position, \ _mixer_set_position, \ _mixer_get_volume, \ _mixer_set_volume, \ _mixer_ramp_volume, \ _mixer_stop_volume_ramp, \ _mixer_get_frequency, \ _mixer_set_frequency, \ _mixer_sweep_frequency, \ _mixer_stop_frequency_sweep, \ _mixer_get_pan, \ _mixer_set_pan, \ _mixer_sweep_pan, \ _mixer_stop_pan_sweep, \ _mixer_set_echo, \ _mixer_set_tremolo, \ _mixer_set_vibrato, \ 0, 0, \ sb_rec_cap_rate, \ sb_rec_cap_parm, \ sb_rec_source, \ sb_rec_start, \ sb_rec_stop, \ sb_rec_read DIGI_DRIVER digi_sb10 = { DIGI_SB10, empty_string, empty_string, "Sound Blaster 1.0", SB_DRIVER_CONTENTS }; DIGI_DRIVER digi_sb15 = { DIGI_SB15, empty_string, empty_string, "Sound Blaster 1.5", SB_DRIVER_CONTENTS }; DIGI_DRIVER digi_sb20 = { DIGI_SB20, empty_string, empty_string, "Sound Blaster 2.0", SB_DRIVER_CONTENTS }; DIGI_DRIVER digi_sbpro = { DIGI_SBPRO, empty_string, empty_string, "Sound Blaster Pro", SB_DRIVER_CONTENTS }; DIGI_DRIVER digi_sb16= { DIGI_SB16, empty_string, empty_string, "Sound Blaster 16", SB_DRIVER_CONTENTS }; /* external interface to the SB midi output driver */ static int sb_midi_detect(int input); static int sb_midi_init(int input, int voices); static void sb_midi_exit(int input); static void sb_midi_output(int data); static char sb_midi_desc[256] = EMPTY_STRING; MIDI_DRIVER midi_sb_out = { MIDI_SB_OUT, empty_string, empty_string, "SB MIDI interface", 0, 0, 0xFFFF, 0, -1, -1, sb_midi_detect, sb_midi_init, sb_midi_exit, NULL, NULL, sb_midi_output, _dummy_load_patches, _dummy_adjust_patches, _dummy_key_on, _dummy_noop1, _dummy_noop2, _dummy_noop3, _dummy_noop2, _dummy_noop2 }; static int sb_in_use = FALSE; /* is SB being used? */ static int sb_stereo = FALSE; /* in stereo mode? */ static int sb_recording = FALSE; /* in input mode? */ static int sb_16bit = FALSE; /* in 16 bit mode? */ static int sb_midi_out_mode = FALSE; /* active for MIDI output? */ static int sb_midi_in_mode = FALSE; /* active for MIDI input? */ static int sb_int = -1; /* interrupt vector */ static int sb_dsp_ver = -1; /* SB DSP version */ static int sb_dma8 = -1; /* 8-bit DMA channel (SB16) */ static int sb_dma16 = -1; /* 16-bit DMA channel (SB16) */ static int sb_hw_dsp_ver = -1; /* as reported by autodetect */ static int sb_dma_size = -1; /* size of dma transfer in bytes */ static int sb_dma_mix_size = -1; /* number of samples to mix */ static int sb_dma_count = 0; /* need to resync with dma? */ static volatile int sb_semaphore = FALSE; /* reentrant interrupt? */ static int sb_sel[2]; /* selectors for the buffers */ static unsigned long sb_buf[2]; /* pointers to the two buffers */ static int sb_bufnum = 0; /* the one currently in use */ static int sb_recbufnum = 0; /* the one to be returned */ static int sb_master_vol = -1; /* stored mixer settings */ static int sb_digi_vol = -1; static int sb_fm_vol = -1; static int sb_detecting_midi = FALSE; static void sb_lock_mem(void); /* sb_read_dsp: * Reads a byte from the SB DSP chip. Returns -1 if it times out. */ static INLINE RET_VOLATILE int sb_read_dsp(void) { int x; for (x=0; x<0xFFFF; x++) if (inportb(0x0E + _sound_port) & 0x80) return inportb(0x0A+_sound_port); return -1; } /* sb_write_dsp: * Writes a byte to the SB DSP chip. Returns -1 if it times out. */ static INLINE RET_VOLATILE int sb_write_dsp(unsigned char byte) { int x; for (x=0; x<0xFFFF; x++) { if (!(inportb(0x0C+_sound_port) & 0x80)) { outportb(0x0C+_sound_port, byte); return 0; } } return -1; } /* _sb_voice: * Turns the SB speaker on or off. */ void _sb_voice(int state) { if (state) { sb_write_dsp(0xD1); if (sb_hw_dsp_ver >= 0x300) { /* set up the mixer */ if (sb_master_vol < 0) { outportb(_sound_port+4, 0x22); /* store master volume */ sb_master_vol = inportb(_sound_port+5); } if (sb_digi_vol < 0) { outportb(_sound_port+4, 4); /* store DAC level */ sb_digi_vol = inportb(_sound_port+5); } if (sb_fm_vol < 0) { outportb(_sound_port+4, 0x26); /* store FM level */ sb_fm_vol = inportb(_sound_port+5); } } } else { sb_write_dsp(0xD3); if (sb_hw_dsp_ver >= 0x300) { /* reset previous mixer settings */ outportb(_sound_port+4, 0x22); /* restore master volume */ outportb(_sound_port+5, sb_master_vol); outportb(_sound_port+4, 4); /* restore DAC level */ outportb(_sound_port+5, sb_digi_vol); outportb(_sound_port+4, 0x26); /* restore FM level */ outportb(_sound_port+5, sb_fm_vol); } } } /* _sb_set_mixer: * Alters the SB-Pro hardware mixer. */ int _sb_set_mixer(int digi_volume, int midi_volume) { if (sb_hw_dsp_ver < 0x300) return -1; if (digi_volume >= 0) { /* set DAC level */ outportb(_sound_port+4, 4); outportb(_sound_port+5, (digi_volume & 0xF0) | (digi_volume >> 4)); } if (midi_volume >= 0) { /* set FM level */ outportb(_sound_port+4, 0x26); outportb(_sound_port+5, (midi_volume & 0xF0) | (midi_volume >> 4)); } return 0; } /* sb_set_mixer_volume: * Sets the SB mixer volume for playing digital samples. */ static int sb_set_mixer_volume(int volume) { return _sb_set_mixer(volume, -1); } /* sb_stereo_mode: * Enables or disables stereo output for SB-Pro. */ static void sb_stereo_mode(int enable) { outportb(_sound_port+0x04, 0x0E); outportb(_sound_port+0x05, (enable ? 2 : 0)); } /* sb_input_stereo_mode: * Enables or disables stereo input for SB-Pro. */ static void sb_input_stereo_mode(int enable) { sb_write_dsp(enable ? 0xA8 : 0xA0); } /* sb_set_sample_rate: * The parameter is the rate to set in Hz (samples per second). */ static void sb_set_sample_rate(unsigned int rate) { if (sb_16bit) { sb_write_dsp(0x41); sb_write_dsp(rate >> 8); sb_write_dsp(rate & 0xff); } else { if (sb_stereo) rate *= 2; sb_write_dsp(0x40); sb_write_dsp((unsigned char)(256-1000000/rate)); } } /* sb_set_input_sample_rate: * The parameter is the rate to set in Hz (samples per second). */ static void sb_set_input_sample_rate(unsigned int rate, int stereo) { if (sb_16bit) { sb_write_dsp(0x42); sb_write_dsp(rate >> 8); sb_write_dsp(rate & 0xff); } else { if (stereo) rate *= 2; sb_write_dsp(0x40); sb_write_dsp((unsigned char)(256-1000000/rate)); } } /* _sb_reset_dsp: * Resets the SB DSP chip, returning -1 on error. */ int _sb_reset_dsp(int data) { int x; outportb(0x06+_sound_port, data); for (x=0; x<8; x++) inportb(0x06+_sound_port); outportb(0x06+_sound_port, 0); if (sb_read_dsp() != 0xAA) return -1; return 0; } /* _sb_read_dsp_version: * Reads the version number of the SB DSP chip, returning -1 on error. */ int _sb_read_dsp_version(void) { int x, y; if (sb_hw_dsp_ver > 0) return sb_hw_dsp_ver; if (_sound_port <= 0) _sound_port = 0x220; if (_sb_reset_dsp(1) != 0) { sb_hw_dsp_ver = -1; } else { sb_write_dsp(0xE1); x = sb_read_dsp(); y = sb_read_dsp(); sb_hw_dsp_ver = ((x << 8) | y); } return sb_hw_dsp_ver; } /* sb_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int sb_buffer_size(void) { return (sb_stereo ? sb_dma_mix_size/2 : sb_dma_mix_size); } /* sb_play_buffer: * Starts a dma transfer of size bytes. On cards capable of it, the * transfer will use auto-initialised dma, so there is no need to call * this routine more than once. On older cards it must be called from * the end-of-buffer handler to switch to the new buffer. */ static void sb_play_buffer(int size) { if (sb_dsp_ver <= 0x200) { /* 8 bit single-shot */ sb_write_dsp(0x14); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); } else if (sb_dsp_ver < 0x400) { /* 8 bit auto-initialised */ sb_write_dsp(0x48); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); sb_write_dsp(0x90); } else { /* 16 bit */ size /= 2; sb_write_dsp(0xB6); sb_write_dsp(0x30); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); } } END_OF_STATIC_FUNCTION(sb_play_buffer); /* sb_record_buffer: * Starts a dma transfer of size bytes. On cards capable of it, the * transfer will use auto-initialised dma, so there is no need to call * this routine more than once. On older cards it must be called from * the end-of-buffer handler to switch to the new buffer. */ static void sb_record_buffer(int size, int stereo, int bits) { if (sb_dsp_ver <= 0x200) { /* 8 bit single-shot */ sb_write_dsp(0x24); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); } else if (sb_dsp_ver < 0x400) { /* 8 bit auto-initialised */ sb_write_dsp(0x48); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); sb_write_dsp(0x98); } else if (bits <= 8) { /* 8 bit */ sb_write_dsp(0xCE); sb_write_dsp((stereo) ? 0x20 : 0x00); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); } else { /* 16 bit */ size /= 2; sb_write_dsp(0xBE); sb_write_dsp((stereo) ? 0x20 : 0x00); sb_write_dsp((size-1) & 0xFF); sb_write_dsp((size-1) >> 8); } } END_OF_STATIC_FUNCTION(sb_record_buffer); /* sb_interrupt: * The SB end-of-buffer interrupt handler. Swaps to the other buffer * if the card doesn't have auto-initialised dma, and then refills the * buffer that just finished playing. */ static int sb_interrupt(void) { unsigned char isr; if (sb_dsp_ver >= 0x400) { /* read SB16 ISR mask */ outportb(_sound_port+4, 0x82); isr = inportb(_sound_port+5) & 7; if (isr & 4) { /* MPU-401 interrupt */ _mpu_poll(); _eoi(_sound_irq); return 0; } if (!(isr & 3)) { /* unknown interrupt */ _eoi(_sound_irq); return 0; } } if (sb_dsp_ver <= 0x200) { /* not auto-initialised */ _dma_start(_sound_dma, sb_buf[1-sb_bufnum], sb_dma_size, FALSE, FALSE); if (sb_recording) sb_record_buffer(sb_dma_size, FALSE, 8); else sb_play_buffer(sb_dma_size); } else { /* poll dma position */ sb_dma_count++; if (sb_dma_count > 16) { sb_bufnum = (_dma_todo(_sound_dma) > (unsigned)sb_dma_size) ? 1 : 0; sb_dma_count = 0; } } if ((!sb_semaphore) && (!sb_recording)) { sb_semaphore = TRUE; ENABLE(); /* mix some more samples */ _mix_some_samples(sb_buf[sb_bufnum], _dos_ds, TRUE); DISABLE(); sb_semaphore = FALSE; } sb_bufnum = 1 - sb_bufnum; if ((sb_recording) && (digi_recorder)) { sb_semaphore = TRUE; ENABLE(); /* sample input callback */ digi_recorder(); DISABLE(); sb_semaphore = FALSE; } if (sb_16bit) /* acknowledge SB */ inportb(_sound_port+0x0F); else inportb(_sound_port+0x0E); _eoi(_sound_irq); /* acknowledge interrupt */ return 0; } END_OF_STATIC_FUNCTION(sb_interrupt); /* sb_start: * Starts up the sound output. */ static void sb_start(void) { sb_bufnum = 0; _sb_voice(1); sb_set_sample_rate(_sound_freq); if ((sb_hw_dsp_ver >= 0x300) && (sb_dsp_ver < 0x400)) sb_stereo_mode(sb_stereo); if (sb_dsp_ver <= 0x200) _dma_start(_sound_dma, sb_buf[0], sb_dma_size, FALSE, FALSE); else _dma_start(_sound_dma, sb_buf[0], sb_dma_size*2, TRUE, FALSE); sb_play_buffer(sb_dma_size); } /* sb_stop: * Stops the sound output. */ static void sb_stop(void) { /* halt sound output */ _sb_voice(0); /* stop dma transfer */ _dma_stop(_sound_dma); if (sb_dsp_ver <= 0x0200) sb_write_dsp(0xD0); _sb_reset_dsp(1); } /* sb_detect: * SB detection routine. Uses the BLASTER environment variable, * or 'sensible' guesses if that doesn't exist. */ static int sb_detect(int input) { char *blaster = getenv("BLASTER"); char tmp[64], *msg; int cmask; int max_freq; int default_freq; if (!sb_detecting_midi) { /* input mode only works on the top of an existing output driver */ if (input) { if (digi_driver != digi_input_driver) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("SB output driver must be installed before input can be read")); return FALSE; } return TRUE; } /* what breed of SB are we looking for? */ switch (digi_card) { case DIGI_SB10: sb_dsp_ver = 0x100; break; case DIGI_SB15: sb_dsp_ver = 0x200; break; case DIGI_SB20: sb_dsp_ver = 0x201; break; case DIGI_SBPRO: sb_dsp_ver = 0x300; break; case DIGI_SB16: sb_dsp_ver = 0x400; break; default: sb_dsp_ver = -1; break; } } else sb_dsp_ver = -1; /* parse BLASTER env */ if (blaster) { while (*blaster) { while ((*blaster == ' ') || (*blaster == '\t')) blaster++; if (*blaster) { switch (*blaster) { case 'a': case 'A': if (_sound_port < 0) _sound_port = strtol(blaster+1, NULL, 16); break; case 'i': case 'I': if (_sound_irq < 0) _sound_irq = strtol(blaster+1, NULL, 10); break; case 'd': case 'D': sb_dma8 = strtol(blaster+1, NULL, 10); break; case 'h': case 'H': sb_dma16 = strtol(blaster+1, NULL, 10); break; } while ((*blaster) && (*blaster != ' ') && (*blaster != '\t')) blaster++; } } } if (_sound_port < 0) _sound_port = 0x220; /* make sure we got a good port address */ if (_sb_reset_dsp(1) != 0) { static int bases[] = { 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0 }; int i; for (i=0; bases[i]; i++) { _sound_port = bases[i]; if (_sb_reset_dsp(1) == 0) break; } } /* check if the card really exists */ _sb_read_dsp_version(); if (sb_hw_dsp_ver < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Sound Blaster not found")); return FALSE; } if (sb_dsp_ver < 0) { sb_dsp_ver = sb_hw_dsp_ver; } else { if (sb_dsp_ver > sb_hw_dsp_ver) { sb_hw_dsp_ver = sb_dsp_ver = -1; ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Older SB version detected")); return FALSE; } } if (sb_dsp_ver >= 0x400) { /* read configuration from SB16 card */ if (_sound_irq < 0) { outportb(_sound_port+4, 0x80); cmask = inportb(_sound_port+5); if (cmask&1) _sound_irq = 2; /* or 9? */ if (cmask&2) _sound_irq = 5; if (cmask&4) _sound_irq = 7; if (cmask&8) _sound_irq = 10; } if ((sb_dma8 < 0) || (sb_dma16 < 0)) { outportb(_sound_port+4, 0x81); cmask = inportb(_sound_port+5); if (sb_dma8 < 0) { if (cmask&1) sb_dma8 = 0; if (cmask&2) sb_dma8 = 1; if (cmask&8) sb_dma8 = 3; } if (sb_dma16 < 0) { sb_dma16 = sb_dma8; if (cmask&0x20) sb_dma16 = 5; if (cmask&0x40) sb_dma16 = 6; if (cmask&0x80) sb_dma16 = 7; } } } /* if nothing else works */ if (_sound_irq < 0) _sound_irq = 7; if (sb_dma8 < 0) sb_dma8 = 1; if (sb_dma16 < 0) sb_dma16 = 5; /* figure out the hardware interrupt number */ sb_int = _map_irq(_sound_irq); if (!sb_detecting_midi) { /* what breed of SB? */ if (sb_dsp_ver >= 0x400) { msg = "SB 16"; max_freq = 45454; default_freq = 22727; } else if (sb_dsp_ver >= 0x300) { msg = "SB Pro"; max_freq = 22727; default_freq = 22727; } else if (sb_dsp_ver >= 0x201) { msg = "SB 2.0"; max_freq = 45454; default_freq = 22727; } else if (sb_dsp_ver >= 0x200) { msg = "SB 1.5"; max_freq = 16129; default_freq = 16129; } else { msg = "SB 1.0"; max_freq = 16129; default_freq = 16129; } /* set up the playback frequency */ if (_sound_freq <= 0) _sound_freq = default_freq; if (_sound_freq < 15000) { _sound_freq = 11906; sb_dma_size = 128; } else if (MIN(_sound_freq, max_freq) < 20000) { _sound_freq = 16129; sb_dma_size = 128; } else if (MIN(_sound_freq, max_freq) < 40000) { _sound_freq = 22727; sb_dma_size = 256; } else { _sound_freq = 45454; sb_dma_size = 512; } if (sb_dsp_ver <= 0x200) sb_dma_size *= 4; sb_dma_mix_size = sb_dma_size; /* can we handle 16 bit sound? */ if (sb_dsp_ver >= 0x400) { if (_sound_dma < 0) _sound_dma = sb_dma16; else sb_dma16 = _sound_dma; sb_16bit = TRUE; digi_driver->rec_cap_bits = 24; sb_dma_size <<= 1; } else { if (_sound_dma < 0) _sound_dma = sb_dma8; else sb_dma8 = _sound_dma; sb_16bit = FALSE; digi_driver->rec_cap_bits = 8; } /* can we handle stereo? */ if (sb_dsp_ver >= 0x300) { sb_stereo = TRUE; digi_driver->rec_cap_stereo = TRUE; sb_dma_size <<= 1; sb_dma_mix_size <<= 1; } else { sb_stereo = FALSE; digi_driver->rec_cap_stereo = FALSE; } /* set up the card description */ uszprintf(sb_desc, sizeof(sb_desc), get_config_text("%s (%d hz) on port %X, using IRQ %d and DMA channel %d"), uconvert_ascii(msg, tmp), _sound_freq, _sound_port, _sound_irq, _sound_dma); digi_driver->desc = sb_desc; } return TRUE; } /* sb_init: * SB init routine: returns zero on success, -1 on failure. */ static int sb_init(int input, int voices) { if (input) return 0; if (sb_in_use) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't use SB MIDI interface and DSP at the same time")); return -1; } if (sb_dsp_ver <= 0x200) { /* two conventional mem buffers */ if ((_dma_allocate_mem(sb_dma_size, &sb_sel[0], &sb_buf[0]) != 0) || (_dma_allocate_mem(sb_dma_size, &sb_sel[1], &sb_buf[1]) != 0)) return -1; } else { /* auto-init dma, one big buffer */ if (_dma_allocate_mem(sb_dma_size*2, &sb_sel[0], &sb_buf[0]) != 0) return -1; sb_sel[1] = sb_sel[0]; sb_buf[1] = sb_buf[0] + sb_dma_size; } sb_lock_mem(); digi_driver->voices = voices; if (_mixer_init(sb_dma_mix_size, _sound_freq, sb_stereo, sb_16bit, &digi_driver->voices) != 0) return -1; _mix_some_samples(sb_buf[0], _dos_ds, TRUE); _mix_some_samples(sb_buf[1], _dos_ds, TRUE); _enable_irq(_sound_irq); _install_irq(sb_int, sb_interrupt); sb_start(); sb_in_use = TRUE; return 0; } /* sb_exit: * SB driver cleanup routine, removes ints, stops dma, frees buffers, etc. */ static void sb_exit(int input) { if (input) return; sb_stop(); _remove_irq(sb_int); _restore_irq(_sound_irq); __dpmi_free_dos_memory(sb_sel[0]); if (sb_sel[1] != sb_sel[0]) __dpmi_free_dos_memory(sb_sel[1]); _mixer_exit(); sb_hw_dsp_ver = sb_dsp_ver = -1; sb_in_use = FALSE; } /* sb_rec_cap_rate: * Returns maximum input sampling rate. */ static int sb_rec_cap_rate(int bits, int stereo) { if (sb_dsp_ver < 0) return 0; if (sb_dsp_ver >= 0x400) /* SB16 can handle 45kHz under all circumstances */ return 45454; /* lesser SB cards can't handle 16-bit */ if (bits != 8) return 0; if (sb_dsp_ver >= 0x300) /* SB Pro can handle 45kHz, but only half that in stereo */ return (stereo) ? 22727 : 45454; /* lesser SB cards can't handle stereo */ if (stereo) return 0; if (sb_dsp_ver >= 0x201) /* SB 2.0 supports 15kHz */ return 15151; /* SB 1.x supports 13kHz */ return 13157; } /* sb_rec_cap_parm: * Returns whether the specified parameters can be set. */ static int sb_rec_cap_parm(int rate, int bits, int stereo) { int c, r; if ((r = sb_rec_cap_rate(bits, stereo)) <= 0) return 0; if (r < rate) return -r; if (sb_dsp_ver >= 0x400) { /* if bits==8 and rate==_sound_freq, bidirectional is possible, but that's not implemented yet */ return 1; } if (stereo) rate *= 2; c = 1000000/rate; r = 1000000/c; if (r != rate) return -r; return 1; } /* sb_rec_source: * Sets the sampling source for audio recording. */ static int sb_rec_source(int source) { int v1, v2; if (sb_hw_dsp_ver >= 0x400) { /* SB16 */ switch (source) { case SOUND_INPUT_MIC: v1 = 1; v2 = 1; break; case SOUND_INPUT_LINE: v1 = 16; v2 = 8; break; case SOUND_INPUT_CD: v1 = 4; v2 = 2; break; default: return -1; } outportb(_sound_port+4, 0x3D); outportb(_sound_port+5, v1); outportb(_sound_port+4, 0x3E); outportb(_sound_port+5, v2); return 0; } else if (sb_hw_dsp_ver >= 0x300) { /* SB Pro */ outportb(_sound_port+4, 0xC); v1 = inportb(_sound_port+5); switch (source) { case SOUND_INPUT_MIC: v1 = (v1 & 0xF9); break; case SOUND_INPUT_LINE: v1 = (v1 & 0xF9) | 6; break; case SOUND_INPUT_CD: v1 = (v1 & 0xF9) | 2; break; default: return -1; } outportb(_sound_port+4, 0xC); outportb(_sound_port+5, v1); return 0; } return -1; } /* sb_rec_start: * Stops playback, switches the SB to A/D mode, and starts recording. * Returns the DMA buffer size if successful. */ static int sb_rec_start(int rate, int bits, int stereo) { if (sb_rec_cap_parm(rate, bits, stereo) <= 0) return 0; sb_stop(); sb_16bit = (bits>8); _sound_dma = (sb_16bit) ? sb_dma16 : sb_dma8; sb_recording = TRUE; sb_recbufnum = sb_bufnum = 0; _sb_voice(1); sb_set_input_sample_rate(rate, stereo); if ((sb_hw_dsp_ver >= 0x300) && (sb_dsp_ver < 0x400)) sb_input_stereo_mode(stereo); if (sb_dsp_ver <= 0x200) _dma_start(_sound_dma, sb_buf[0], sb_dma_size, FALSE, TRUE); else _dma_start(_sound_dma, sb_buf[0], sb_dma_size*2, TRUE, TRUE); sb_record_buffer(sb_dma_size, stereo, bits); return sb_dma_size; } /* sb_rec_stop: * Stops recording, switches the SB back to D/A mode, and restarts playback. */ static void sb_rec_stop(void) { if (!sb_recording) return; sb_stop(); sb_recording = FALSE; sb_16bit = (sb_dsp_ver >= 0x400); _sound_dma = (sb_16bit) ? sb_dma16 : sb_dma8; _mix_some_samples(sb_buf[0], _dos_ds, TRUE); _mix_some_samples(sb_buf[1], _dos_ds, TRUE); sb_start(); } /* sb_rec_read: * Retrieves the just recorded DMA buffer, if there is one. */ static int sb_rec_read(void *buf) { if (!sb_recording) return 0; if (sb_bufnum == sb_recbufnum) return 0; dosmemget(sb_buf[sb_recbufnum], sb_dma_size, buf); sb_recbufnum = 1-sb_recbufnum; return 1; } END_OF_STATIC_FUNCTION(sb_rec_read); /* sb_midi_interrupt: * Interrupt handler for the SB MIDI input. */ static int sb_midi_interrupt(void) { int c = sb_read_dsp(); if ((c >= 0) && (midi_recorder)) midi_recorder(c); _eoi(_sound_irq); return 0; } END_OF_STATIC_FUNCTION(sb_midi_interrupt); /* sb_midi_output: * Writes a byte to the SB midi interface. */ static void sb_midi_output(int data) { sb_write_dsp(data); } END_OF_STATIC_FUNCTION(sb_midi_output); /* sb_midi_detect: * Detection routine for the SB MIDI interface. */ static int sb_midi_detect(int input) { int ret; if ((input) && (sb_midi_out_mode)) return TRUE; sb_detecting_midi = TRUE; ret = sb_detect(FALSE); sb_detecting_midi = FALSE; return ret; } /* sb_midi_init: * Initialises the SB midi interface, returning zero on success. */ static int sb_midi_init(int input, int voices) { if ((sb_in_use) && (!sb_midi_out_mode)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't use SB MIDI interface and DSP at the same time")); return -1; } sb_dsp_ver = -1; sb_lock_mem(); uszprintf(sb_midi_desc, sizeof(sb_midi_desc), get_config_text("Sound Blaster MIDI interface on port %X"), _sound_port); midi_sb_out.desc = sb_midi_desc; if (input) { _enable_irq(_sound_irq); _install_irq(sb_int, sb_midi_interrupt); sb_midi_in_mode = TRUE; } else sb_midi_out_mode = TRUE; sb_write_dsp(0x35); sb_in_use = TRUE; return 0; } /* sb_midi_exit: * Resets the SB midi interface when we are finished. */ static void sb_midi_exit(int input) { if (input) { _remove_irq(sb_int); _restore_irq(_sound_irq); sb_midi_in_mode = FALSE; } else sb_midi_out_mode = FALSE; if ((!sb_midi_in_mode) && (!sb_midi_out_mode)) { _sb_reset_dsp(1); sb_in_use = FALSE; } } /* sb_lock_mem: * Locks all the memory touched by parts of the SB code that are executed * in an interrupt context. */ static void sb_lock_mem(void) { extern void _mpu_poll_end(void); LOCK_VARIABLE(digi_sb10); LOCK_VARIABLE(digi_sb15); LOCK_VARIABLE(digi_sb20); LOCK_VARIABLE(digi_sbpro); LOCK_VARIABLE(digi_sb16); LOCK_VARIABLE(midi_sb_out); LOCK_VARIABLE(_sound_freq); LOCK_VARIABLE(_sound_port); LOCK_VARIABLE(_sound_dma); LOCK_VARIABLE(_sound_irq); LOCK_VARIABLE(sb_int); LOCK_VARIABLE(sb_in_use); LOCK_VARIABLE(sb_recording); LOCK_VARIABLE(sb_16bit); LOCK_VARIABLE(sb_midi_out_mode); LOCK_VARIABLE(sb_midi_in_mode); LOCK_VARIABLE(sb_dsp_ver); LOCK_VARIABLE(sb_hw_dsp_ver); LOCK_VARIABLE(sb_dma_size); LOCK_VARIABLE(sb_dma_mix_size); LOCK_VARIABLE(sb_sel); LOCK_VARIABLE(sb_buf); LOCK_VARIABLE(sb_bufnum); LOCK_VARIABLE(sb_recbufnum); LOCK_VARIABLE(sb_dma_count); LOCK_VARIABLE(sb_semaphore); LOCK_VARIABLE(sb_recording); LOCK_FUNCTION(sb_play_buffer); LOCK_FUNCTION(sb_interrupt); LOCK_FUNCTION(sb_rec_read); LOCK_FUNCTION(sb_midi_interrupt); LOCK_FUNCTION(sb_midi_output); LOCK_FUNCTION(sb_record_buffer); LOCK_FUNCTION(_mpu_poll); _dma_lock_mem(); } allegro-4.4.3.1/src/dos/dma.c0000664000175000017500000002127513437077643014570 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DMA routines for the sound code. I used to feel slightly guilty * because I pinched this code from MikMod, but then I looked at * the GUS SDK and realised that Jean Paul Mikkers took it from * there, so I think that justifies me in using it. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" /* DMA controller #1 (8-bit controller) */ #define DMA1_STAT 0x08 /* read status register */ #define DMA1_WCMD 0x08 /* write command register */ #define DMA1_WREQ 0x09 /* write request register */ #define DMA1_SNGL 0x0A /* write single bit register */ #define DMA1_MODE 0x0B /* write mode register */ #define DMA1_CLRFF 0x0C /* clear byte ptr flip/flop */ #define DMA1_MCLR 0x0D /* master clear register */ #define DMA1_CLRM 0x0E /* clear mask register */ #define DMA1_WRTALL 0x0F /* write all mask register */ /* DMA controller #2 (16-bit controller) */ #define DMA2_STAT 0xD0 /* read status register */ #define DMA2_WCMD 0xD0 /* write command register */ #define DMA2_WREQ 0xD2 /* write request register */ #define DMA2_SNGL 0xD4 /* write single bit register */ #define DMA2_MODE 0xD6 /* write mode register */ #define DMA2_CLRFF 0xD8 /* clear byte ptr flip/flop */ #define DMA2_MCLR 0xDA /* master clear register */ #define DMA2_CLRM 0xDC /* clear mask register */ #define DMA2_WRTALL 0xDE /* write all mask register */ /* stuff for each DMA channel */ #define DMA0_ADDR 0x00 /* chan 0 base adddress */ #define DMA0_CNT 0x01 /* chan 0 base count */ #define DMA1_ADDR 0x02 /* chan 1 base adddress */ #define DMA1_CNT 0x03 /* chan 1 base count */ #define DMA2_ADDR 0x04 /* chan 2 base adddress */ #define DMA2_CNT 0x05 /* chan 2 base count */ #define DMA3_ADDR 0x06 /* chan 3 base adddress */ #define DMA3_CNT 0x07 /* chan 3 base count */ #define DMA4_ADDR 0xC0 /* chan 4 base adddress */ #define DMA4_CNT 0xC2 /* chan 4 base count */ #define DMA5_ADDR 0xC4 /* chan 5 base adddress */ #define DMA5_CNT 0xC6 /* chan 5 base count */ #define DMA6_ADDR 0xC8 /* chan 6 base adddress */ #define DMA6_CNT 0xCA /* chan 6 base count */ #define DMA7_ADDR 0xCC /* chan 7 base adddress */ #define DMA7_CNT 0xCE /* chan 7 base count */ #define DMA0_PAGE 0x87 /* chan 0 page register (refresh) */ #define DMA1_PAGE 0x83 /* chan 1 page register */ #define DMA2_PAGE 0x81 /* chan 2 page register */ #define DMA3_PAGE 0x82 /* chan 3 page register */ #define DMA4_PAGE 0x8F /* chan 4 page register (unuseable) */ #define DMA5_PAGE 0x8B /* chan 5 page register */ #define DMA6_PAGE 0x89 /* chan 6 page register */ #define DMA7_PAGE 0x8A /* chan 7 page register */ typedef struct { unsigned char dma_disable; /* bits to disable dma channel */ unsigned char dma_enable; /* bits to enable dma channel */ unsigned short page; /* page port location */ unsigned short addr; /* addr port location */ unsigned short count; /* count port location */ unsigned short single; /* single mode port location */ unsigned short mode; /* mode port location */ unsigned short clear_ff; /* clear flip-flop port location */ unsigned char write; /* bits for write transfer */ unsigned char read; /* bits for read transfer */ } DMA_ENTRY; static DMA_ENTRY mydma[] = { /* channel 0 */ { 0x04, 0x00, DMA0_PAGE, DMA0_ADDR, DMA0_CNT, DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x48, 0x44 }, /* channel 1 */ { 0x05, 0x01, DMA1_PAGE, DMA1_ADDR, DMA1_CNT, DMA1_SNGL,DMA1_MODE,DMA1_CLRFF,0x49,0x45 }, /* channel 2 */ { 0x06, 0x02, DMA2_PAGE, DMA2_ADDR, DMA2_CNT, DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x4A, 0x46 }, /* channel 3 */ { 0x07, 0x03, DMA3_PAGE, DMA3_ADDR, DMA3_CNT, DMA1_SNGL, DMA1_MODE, DMA1_CLRFF, 0x4B, 0x47 }, /* channel 4 */ { 0x04, 0x00, DMA4_PAGE, DMA4_ADDR, DMA4_CNT, DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x48, 0x44 }, /* channel 5 */ { 0x05, 0x01, DMA5_PAGE, DMA5_ADDR, DMA5_CNT, DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x49, 0x45 }, /* channel 6 */ { 0x06, 0x02, DMA6_PAGE, DMA6_ADDR, DMA6_CNT, DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x4A, 0x46 }, /* channel 7 */ { 0x07, 0x03, DMA7_PAGE, DMA7_ADDR, DMA7_CNT, DMA2_SNGL, DMA2_MODE, DMA2_CLRFF, 0x4B, 0x47 } }; /* _dma_allocate_mem: * Allocates the specified amount of conventional memory, ensuring that * the returned block doesn't cross a page boundary. Sel will be set to * the protected mode segment that should be used to free the block, and * phys to the linear address of the block. On error, returns non-zero * and sets sel and phys to 0. */ int _dma_allocate_mem(int bytes, int *sel, unsigned long *phys) { int seg; /* allocate twice as much memory as we really need */ seg = __dpmi_allocate_dos_memory((bytes*2 + 15) >> 4, sel); if (seg < 0) { *sel = 0; *phys = 0; return -1; } *phys = seg << 4; /* if it crosses a page boundary, use the second half of the block */ if ((*phys>>16) != ((*phys+bytes)>>16)) *phys += bytes; return 0; } END_OF_FUNCTION(_dma_allocate_mem); /* dma_start: * Starts the DMA controller for the specified channel, transferring * size bytes from addr (the block must not cross a page boundary). * If auto_init is set, it will use the endless repeat DMA mode. */ void _dma_start(int channel, unsigned long addr, int size, int auto_init, int input) { DMA_ENTRY *tdma; unsigned long page, offset; int mode; tdma = &mydma[channel]; page = addr >> 16; if (channel >= 4) { /* 16 bit data is halved */ addr >>= 1; size >>= 1; } offset = addr & 0xFFFF; size--; mode = (input) ? tdma->read : tdma->write; if (auto_init) mode |= 0x10; outportb(tdma->single, tdma->dma_disable); /* disable channel */ outportb(tdma->mode, mode); /* set mode */ outportb(tdma->clear_ff, 0); /* clear flip-flop */ outportb(tdma->addr, offset & 0xFF); /* address LSB */ outportb(tdma->addr, offset >> 8); /* address MSB */ outportb(tdma->page, page); /* page number */ outportb(tdma->clear_ff, 0); /* clear flip-flop */ outportb(tdma->count, size & 0xFF); /* count LSB */ outportb(tdma->count, size >> 8); /* count MSB */ outportb(tdma->single, tdma->dma_enable); /* enable channel */ } END_OF_FUNCTION(_dma_start); /* dma_stop: * Disables the specified DMA channel. */ void _dma_stop(int channel) { DMA_ENTRY *tdma = &mydma[channel]; outportb(tdma->single, tdma->dma_disable); } END_OF_FUNCTION(_dma_stop); /* dma_todo: * Returns the current position in a dma transfer. Interrupts should be * disabled before calling this function. */ unsigned long _dma_todo(int channel) { int val1, val2; DMA_ENTRY *tdma = &mydma[channel]; outportb(tdma->clear_ff, 0xff); do { val1 = inportb(tdma->count); val1 |= inportb(tdma->count) << 8; val2 = inportb(tdma->count); val2 |= inportb(tdma->count) << 8; val1 -= val2; } while (val1 > 0x40); if (channel > 3) val2 <<= 1; return val2; } END_OF_FUNCTION(_dma_todo); /* _dma_lock_mem: * Locks the memory used by the dma routines. */ void _dma_lock_mem(void) { LOCK_VARIABLE(mydma); LOCK_FUNCTION(_dma_allocate_mem); LOCK_FUNCTION(_dma_start); LOCK_FUNCTION(_dma_stop); LOCK_FUNCTION(_dma_todo); } allegro-4.4.3.1/src/dos/joystd.c0000664000175000017500000007753013437077643015350 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DOS joystick routines. * * By Shawn Hargreaves. * * Based on code provided by Jonathan Tarbox and Marcel de Kogel. * * CH Flightstick Pro and Logitech Wingman Extreme * support by Fabian Nunez. * * Matthew Bowie added support for 4-button joysticks. * * Richard Mitton added support for 6-button joysticks. * * Stefan Eilert added support for dual joysticks. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* driver functions */ static int joy_init(void); static void joy_exit(void); static int joy_poll(void); static int joy_save_data(void); static int joy_load_data(void); static AL_CONST char *joy_calibrate_name(int n); static int joy_calibrate(int n); static int poll(int *x, int *y, int *x2, int *y2, int poll_mask); #define JOYSTICK_DRIVER_CONTENTS \ joy_init, \ joy_exit, \ joy_poll, \ joy_save_data, \ joy_load_data, \ joy_calibrate_name, \ joy_calibrate JOYSTICK_DRIVER joystick_standard = { JOY_TYPE_STANDARD, empty_string, empty_string, "Standard joystick", JOYSTICK_DRIVER_CONTENTS }; JOYSTICK_DRIVER joystick_2pads = { JOY_TYPE_2PADS, empty_string, empty_string, "Dual joysticks", JOYSTICK_DRIVER_CONTENTS }; JOYSTICK_DRIVER joystick_4button = { JOY_TYPE_4BUTTON, empty_string, empty_string, "4-button joystick", JOYSTICK_DRIVER_CONTENTS }; JOYSTICK_DRIVER joystick_6button = { JOY_TYPE_6BUTTON, empty_string, empty_string, "6-button joystick", JOYSTICK_DRIVER_CONTENTS }; JOYSTICK_DRIVER joystick_8button = { JOY_TYPE_8BUTTON, empty_string, empty_string, "8-button joystick", JOYSTICK_DRIVER_CONTENTS }; JOYSTICK_DRIVER joystick_fspro = { JOY_TYPE_FSPRO, empty_string, empty_string, "Flightstick Pro", JOYSTICK_DRIVER_CONTENTS }; JOYSTICK_DRIVER joystick_wingex = { JOY_TYPE_WINGEX, empty_string, empty_string, "Wingman Extreme", JOYSTICK_DRIVER_CONTENTS }; /* flags describing different variants of the basic joystick */ #define JDESC_STICK2 0x0001 #define JDESC_4BUTTON 0x0002 #define JDESC_6BUTTON 0x0004 #define JDESC_8BUTTON 0x0008 #define JDESC_Y2_THROTTLE 0x0010 #define JDESC_Y2_HAT 0x0020 #define JDESC_FSPRO_HAT 0x0040 /* calibration state information */ #define JOYSTICK_CALIB_TL1 0x00010000 #define JOYSTICK_CALIB_BR1 0x00020000 #define JOYSTICK_CALIB_TL2 0x00040000 #define JOYSTICK_CALIB_BR2 0x00080000 #define JOYSTICK_CALIB_THRTL_MIN 0x00100000 #define JOYSTICK_CALIB_THRTL_MAX 0x00200000 #define JOYSTICK_CALIB_HAT_CENTRE 0x00400000 #define JOYSTICK_CALIB_HAT_LEFT 0x00800000 #define JOYSTICK_CALIB_HAT_DOWN 0x01000000 #define JOYSTICK_CALIB_HAT_RIGHT 0x02000000 #define JOYSTICK_CALIB_HAT_UP 0x04000000 #define JOYSTICK_CALIB_HAT (JOYSTICK_CALIB_HAT_CENTRE | \ JOYSTICK_CALIB_HAT_LEFT | \ JOYSTICK_CALIB_HAT_DOWN | \ JOYSTICK_CALIB_HAT_RIGHT | \ JOYSTICK_CALIB_HAT_UP) /* driver state information */ static int joystick_flags = 0; static int joycentre_x, joycentre_y; static int joyx_min, joyx_low_margin, joyx_high_margin, joyx_max; static int joyy_min, joyy_low_margin, joyy_high_margin, joyy_max; static int joycentre2_x, joycentre2_y; static int joyx2_min, joyx2_low_margin, joyx2_high_margin, joyx2_max; static int joyy2_min, joyy2_low_margin, joyy2_high_margin, joyy2_max; static int joy_thr_min, joy_thr_max; static int joy_hat_pos[5], joy_hat_threshold[4]; static int joy_old_x, joy_old_y; static int joy2_old_x, joy2_old_y; /* masks indicating which axis to read */ #define MASK_1X 1 #define MASK_1Y 2 #define MASK_2X 4 #define MASK_2Y 8 /* poll_mask: * Returns a mask indicating which axes to poll. */ static int poll_mask(void) { int mask = MASK_1X | MASK_1Y; if (joystick_flags & (JDESC_STICK2 | JDESC_6BUTTON | JDESC_8BUTTON)) mask |= (MASK_2X | MASK_2Y); if (joystick_flags & (JDESC_Y2_THROTTLE | JDESC_Y2_HAT)) mask |= MASK_2Y; return mask; } /* averaged_poll: * For calibration it is crucial that we get the right results, so we * average out several attempts. */ static int averaged_poll(int *x, int *y, int *x2, int *y2, int mask) { int x_tmp, y_tmp, x2_tmp, y2_tmp; int x_total, y_total, x2_total, y2_total; int c; #define AVERAGE_COUNT 4 x_total = y_total = x2_total = y2_total = 0; for (c=0; c 2) { joy[i].button[2].name = get_config_text("B3"); joy[i].button[3].name = get_config_text("B4"); } if (joy[i].num_buttons > 4) { joy[i].button[4].name = get_config_text("B5"); joy[i].button[5].name = get_config_text("B6"); } if (joy[i].num_buttons > 6) { joy[i].button[6].name = get_config_text("B7"); joy[i].button[7].name = get_config_text("B8"); } } recalc_calibration_flags(); return 0; } /* joy_exit: * Shuts down the driver. */ static void joy_exit(void) { joystick_flags = 0; } /* sort_out_middle_values: * Sets up the values used by sort_out_analogue() to create a 'dead' * region in the centre of the joystick range. */ static void sort_out_middle_values(int n) { if (n == 0) { joyx_low_margin = joycentre_x - (joycentre_x - joyx_min) / 8; joyx_high_margin = joycentre_x + (joyx_max - joycentre_x) / 8; joyy_low_margin = joycentre_y - (joycentre_y - joyy_min) / 8; joyy_high_margin = joycentre_y + (joyy_max - joycentre_y) / 8; } else { joyx2_low_margin = joycentre2_x - (joycentre2_x - joyx2_min) / 8; joyx2_high_margin = joycentre2_x + (joyx2_max - joycentre2_x) / 8; joyy2_low_margin = joycentre2_y - (joycentre2_y - joyy2_min) / 8; joyy2_high_margin = joycentre2_y + (joyy2_max - joycentre2_y) / 8; } } /* calibrate_corner: * For analogue access to the joystick, this is used to measure the top * left and bottom right corner positions. */ static int calibrate_corner(int stick, int corner) { int flag, other, ret, nowhere; if (stick == 0) { /* stick 1 calibration */ flag = (corner) ? JOYSTICK_CALIB_BR1 : JOYSTICK_CALIB_TL1; other = (corner) ? JOYSTICK_CALIB_TL1 : JOYSTICK_CALIB_BR1; if (corner) ret = averaged_poll(&joyx_max, &joyy_max, &nowhere, &nowhere, MASK_1X | MASK_1Y); else ret = averaged_poll(&joyx_min, &joyy_min, &nowhere, &nowhere, MASK_1X | MASK_1Y); } else { /* stick 2 calibration */ flag = (corner) ? JOYSTICK_CALIB_BR2 : JOYSTICK_CALIB_TL2; other = (corner) ? JOYSTICK_CALIB_TL2 : JOYSTICK_CALIB_BR2; if (corner) ret = averaged_poll(&nowhere, &nowhere, &joyx2_max, &joyy2_max, MASK_2X | MASK_2Y); else ret = averaged_poll(&nowhere, &nowhere, &joyx2_min, &joyy2_min, MASK_2X | MASK_2Y); } if (ret != 0) { joystick_flags &= ~flag; return -1; } joystick_flags |= flag; /* once we've done both corners, we are ready for full analogue input */ if (joystick_flags & other) { sort_out_middle_values(stick); recalc_calibration_flags(); } return 0; } /* calibrate_joystick_tl: * For backward compatibility with the old API. */ int calibrate_joystick_tl(void) { int ret; if (!_joystick_installed) return -1; ret = calibrate_corner(0, 0); if ((ret == 0) && (joystick_flags & JDESC_STICK2)) ret = calibrate_corner(1, 0); return ret; } /* calibrate_joystick_br: * For backward compatibility with the old API. */ int calibrate_joystick_br(void) { int ret; if (!_joystick_installed) return -1; ret = calibrate_corner(0, 1); if ((ret == 0) && (joystick_flags & JDESC_STICK2)) ret = calibrate_corner(1, 1); return ret; } /* calibrate_joystick_throttle_min: * For analogue access to the FSPro's throttle, call this after * initialise_joystick(), with the throttle at the "minimum" extreme * (the user decides whether this is all the way forwards or all the * way back), and also call calibrate_joystick_throttle_max(). */ int calibrate_joystick_throttle_min(void) { int dummy; if (!_joystick_installed) return -1; if (averaged_poll(&dummy, &dummy, &dummy, &joy_thr_min, MASK_2Y) != 0) return -1; /* prevent division by zero errors if user miscalibrated */ if ((joystick_flags & JOYSTICK_CALIB_THRTL_MAX) && (joy_thr_min == joy_thr_max)) joy_thr_min = 255 - joy_thr_max; joystick_flags |= JOYSTICK_CALIB_THRTL_MIN; recalc_calibration_flags(); return 0; } /* calibrate_joystick_throttle_max: * For analogue access to the FSPro's throttle, call this after * initialise_joystick(), with the throttle at the "maximum" extreme * (the user decides whether this is all the way forwards or all the * way back), and also call calibrate_joystick_throttle_min(). */ int calibrate_joystick_throttle_max(void) { int dummy; if (!_joystick_installed) return -1; if (averaged_poll(&dummy, &dummy, &dummy, &joy_thr_max, MASK_2Y) != 0) return -1; /* prevent division by zero errors if user miscalibrated */ if ((joystick_flags & JOYSTICK_CALIB_THRTL_MIN) && (joy_thr_min == joy_thr_max)) joy_thr_max = 255 - joy_thr_min; joystick_flags |= JOYSTICK_CALIB_THRTL_MAX; recalc_calibration_flags(); return 0; } /* calibrate_joystick_hat: * For access to the Wingman Extreme's hat (I think this will work on all * Thrustmaster compatible joysticks), call this after initialise_joystick(), * passing the JOY_HAT constant you wish to calibrate. */ int calibrate_joystick_hat(int direction) { static int pos_const[] = { JOYSTICK_CALIB_HAT_CENTRE, JOYSTICK_CALIB_HAT_LEFT, JOYSTICK_CALIB_HAT_DOWN, JOYSTICK_CALIB_HAT_RIGHT, JOYSTICK_CALIB_HAT_UP }; int dummy, value; if ((direction > JOY_HAT_UP) || (!_joystick_installed)) return -1; if (averaged_poll(&dummy, &dummy, &dummy, &value, MASK_2Y) != 0) return -1; joy_hat_pos[direction] = value; joystick_flags |= pos_const[direction]; /* when all directions have been calibrated, calculate deltas */ if ((joystick_flags & JOYSTICK_CALIB_HAT) == JOYSTICK_CALIB_HAT) { joy_hat_threshold[0] = (joy_hat_pos[0] + joy_hat_pos[1]) / 2; joy_hat_threshold[1] = (joy_hat_pos[1] + joy_hat_pos[2]) / 2; joy_hat_threshold[2] = (joy_hat_pos[2] + joy_hat_pos[3]) / 2; joy_hat_threshold[3] = (joy_hat_pos[3] + joy_hat_pos[4]) / 2; recalc_calibration_flags(); } return 0; } /* sort_out_analogue: * There are a couple of problems with reading analogue input from the PC * joystick. For one thing, joysticks tend not to centre repeatably, so * we need a small 'dead' zone in the middle. Also a lot of joysticks aren't * linear, so the positions less than centre need to be handled differently * to those above the centre. */ static int sort_out_analogue(int x, int min, int low_margin, int high_margin, int max) { if (x < min) { return -128; } else if (x < low_margin) { return -128 + (x - min) * 128 / (low_margin - min); } else if (x <= high_margin) { return 0; } else if (x <= max) { return 128 - (max - x) * 128 / (max - high_margin); } else return 128; } /* joy_poll: * Updates the joystick status variables. */ static int joy_poll(void) { int x, y, x2, y2, i; unsigned char status; /* read the hardware */ if (poll(&x, &y, &x2, &y2, poll_mask()) != 0) return -1; status = inportb(0x201); /* stick 1 position */ if ((ABS(x-joy_old_x) <= x/4) && (ABS(y-joy_old_y) <= y/4)) { if ((joystick_flags & JOYSTICK_CALIB_TL1) && (joystick_flags & JOYSTICK_CALIB_BR1)) { joy[0].stick[0].axis[0].pos = sort_out_analogue(x, joyx_min, joyx_low_margin, joyx_high_margin, joyx_max); joy[0].stick[0].axis[1].pos = sort_out_analogue(y, joyy_min, joyy_low_margin, joyy_high_margin, joyy_max); } else { joy[0].stick[0].axis[0].pos = x - joycentre_x; joy[0].stick[0].axis[1].pos = y - joycentre_y; } joy[0].stick[0].axis[0].d1 = (x < (joycentre_x/2)); joy[0].stick[0].axis[0].d2 = (x > (joycentre_x*4/3)); joy[0].stick[0].axis[1].d1 = (y < (joycentre_y/2)); joy[0].stick[0].axis[1].d2 = (y > (joycentre_y*4/3)); } if (joystick_flags & JDESC_STICK2) { /* stick 2 position */ if ((ABS(x2-joy2_old_x) <= x2/4) && (ABS(y2-joy2_old_y) <= y2/4)) { if ((joystick_flags & JOYSTICK_CALIB_TL2) && (joystick_flags & JOYSTICK_CALIB_BR2)) { joy[1].stick[0].axis[0].pos = sort_out_analogue(x2, joyx2_min, joyx2_low_margin, joyx2_high_margin, joyx2_max); joy[1].stick[0].axis[1].pos = sort_out_analogue(y2, joyy2_min, joyy2_low_margin, joyy2_high_margin, joyy2_max); } else { joy[1].stick[0].axis[0].pos = x2 - joycentre2_x; joy[1].stick[0].axis[1].pos = y2 - joycentre2_y; } joy[1].stick[0].axis[0].d1 = (x2 < (joycentre2_x/2)); joy[1].stick[0].axis[0].d2 = (x2 > (joycentre2_x*3/2)); joy[1].stick[0].axis[1].d1 = (y2 < (joycentre2_y/2)); joy[1].stick[0].axis[1].d2 = (y2 > (joycentre2_y*3/2)); } joy[1].button[0].b = ((status & 0x40) == 0); joy[1].button[1].b = ((status & 0x80) == 0); } /* button state */ joy[0].button[0].b = ((status & 0x10) == 0); joy[0].button[1].b = ((status & 0x20) == 0); if (joystick_flags & JDESC_4BUTTON) { /* four button state */ joy[0].button[2].b = ((status & 0x40) == 0); joy[0].button[3].b = ((status & 0x80) == 0); } if (joystick_flags & JDESC_6BUTTON) { /* six button state */ joy[0].button[4].b = (x2 < 128); joy[0].button[5].b = (y2 < 128); } else if (joystick_flags & JDESC_8BUTTON) { /* eight button state */ joy[0].button[4].b = (x2 < (joycentre2_x/2)); joy[0].button[5].b = (y2 < (joycentre2_y/2)); joy[0].button[6].b = (x2 > (joycentre2_x*3/2)); joy[0].button[7].b = (y2 > (joycentre2_y*3)/2); } if (joystick_flags & JDESC_Y2_THROTTLE) { /* throttle */ if ((joystick_flags & JOYSTICK_CALIB_THRTL_MIN) && (joystick_flags & JOYSTICK_CALIB_THRTL_MAX)) { i = (y2 - joy_thr_min) * 255 / (joy_thr_max - joy_thr_min); joy[0].stick[2].axis[0].pos = CLAMP(0, i, 255); if (joy[0].stick[2].axis[0].pos > 255*2/3) joy[0].stick[2].axis[0].d2 = TRUE; else joy[0].stick[2].axis[0].d2 = FALSE; } } if (joystick_flags & JDESC_FSPRO_HAT) { /* FSPro hat control (accessed via special button values) */ joy[0].stick[1].axis[0].pos = 0; joy[0].stick[1].axis[1].pos = 0; joy[0].stick[1].axis[0].d1 = joy[0].stick[1].axis[0].d2 = 0; joy[0].stick[1].axis[1].d1 = joy[0].stick[1].axis[1].d2 = 0; if ((status & 0x30) == 0) { joy[0].button[0].b = FALSE; joy[0].button[1].b = FALSE; joy[0].button[2].b = FALSE; joy[0].button[3].b = FALSE; switch (status & 0xC0) { case 0x00: /* up */ joy[0].stick[1].axis[1].pos = -128; joy[0].stick[1].axis[1].d1 = TRUE; break; case 0x40: /* right */ joy[0].stick[1].axis[0].pos = 128; joy[0].stick[1].axis[0].d2 = TRUE; break; case 0x80: /* down */ joy[0].stick[1].axis[1].pos = 128; joy[0].stick[1].axis[1].d2 = TRUE; break; case 0xC0: /* left */ joy[0].stick[1].axis[0].pos = -128; joy[0].stick[1].axis[0].d1 = TRUE; break; } } } if (joystick_flags & JDESC_Y2_HAT) { /* Wingman Extreme hat control (accessed via the y2 pot) */ joy[0].stick[1].axis[0].pos = 0; joy[0].stick[1].axis[1].pos = 0; joy[0].stick[1].axis[0].d1 = joy[0].stick[1].axis[0].d2 = 0; joy[0].stick[1].axis[1].d1 = joy[0].stick[1].axis[1].d2 = 0; if ((joystick_flags & JOYSTICK_CALIB_HAT) == JOYSTICK_CALIB_HAT) { if (y2 >= joy_hat_threshold[0]) { /* centre */ } else if (y2 >= joy_hat_threshold[1]) { /* left */ joy[0].stick[1].axis[0].pos = -128; joy[0].stick[1].axis[0].d1 = TRUE; } else if (y2 >= joy_hat_threshold[2]) { /* down */ joy[0].stick[1].axis[1].pos = 128; joy[0].stick[1].axis[1].d2 = TRUE; } else if (y2 >= joy_hat_threshold[3]) { /* right */ joy[0].stick[1].axis[0].pos = 128; joy[0].stick[1].axis[0].d2 = TRUE; } else { /* up */ joy[0].stick[1].axis[1].pos = -128; joy[0].stick[1].axis[1].d1 = TRUE; } } } joy_old_x = x; joy_old_y = y; joy2_old_x = x2; joy2_old_y = y2; return 0; } /* poll: * Polls the joystick to read the axis position. Returns raw position * values, zero for success, non-zero if no joystick found. This has * to come after the routines that call it, to make sure it will never * be inlined (that could shift alignment and upset the timing values). */ static int poll(int *x, int *y, int *x2, int *y2, int poll_mask) { int c, d; *x = *y = *x2 = *y2 = 0; _enter_critical(); outportb(0x201, 0); for (c=0; c<100000; c++) { d = inportb(0x201); if (d & MASK_1X) (*x)++; if (d & MASK_1Y) (*y)++; if (d & MASK_2X) (*x2)++; if (d & MASK_2Y) (*y2)++; if (!(d & poll_mask)) break; } _exit_critical(); if (((poll_mask & MASK_1X) && (*x >= 100000)) || ((poll_mask & MASK_1Y) && (*y >= 100000)) || ((poll_mask & MASK_2X) && (*x2 >= 100000)) || ((poll_mask & MASK_2Y) && (*y2 >= 100000))) return -1; return 0; } /* joy_save_data: * Writes calibration data into the config file. */ static int joy_save_data(void) { char tmp1[128], tmp2[128]; char *j = uconvert_ascii("joystick", tmp1); set_config_int(j, uconvert_ascii("joystick_flags", tmp2), joystick_flags); set_config_int(j, uconvert_ascii("joycentre_x", tmp2), joycentre_x); set_config_int(j, uconvert_ascii("joycentre_y", tmp2), joycentre_y); set_config_int(j, uconvert_ascii("joyx_min", tmp2), joyx_min); set_config_int(j, uconvert_ascii("joyx_low_margin", tmp2), joyx_low_margin); set_config_int(j, uconvert_ascii("joyx_high_margin", tmp2), joyx_high_margin); set_config_int(j, uconvert_ascii("joyx_max", tmp2), joyx_max); set_config_int(j, uconvert_ascii("joyy_min", tmp2), joyy_min); set_config_int(j, uconvert_ascii("joyy_low_margin", tmp2), joyy_low_margin); set_config_int(j, uconvert_ascii("joyy_high_margin", tmp2), joyy_high_margin); set_config_int(j, uconvert_ascii("joyy_max", tmp2), joyy_max); set_config_int(j, uconvert_ascii("joycentre2_x", tmp2), joycentre2_x); set_config_int(j, uconvert_ascii("joycentre2_y", tmp2), joycentre2_y); set_config_int(j, uconvert_ascii("joyx2_min", tmp2), joyx2_min); set_config_int(j, uconvert_ascii("joyx2_low_margin", tmp2), joyx2_low_margin); set_config_int(j, uconvert_ascii("joyx2_high_margin", tmp2), joyx2_high_margin); set_config_int(j, uconvert_ascii("joyx2_max", tmp2), joyx2_max); set_config_int(j, uconvert_ascii("joyy2_min", tmp2), joyy2_min); set_config_int(j, uconvert_ascii("joyy2_low_margin", tmp2), joyy2_low_margin); set_config_int(j, uconvert_ascii("joyy2_high_margin", tmp2), joyy2_high_margin); set_config_int(j, uconvert_ascii("joyy2_max", tmp2), joyy2_max); set_config_int(j, uconvert_ascii("joythr_min", tmp2), joy_thr_min); set_config_int(j, uconvert_ascii("joythr_max", tmp2), joy_thr_max); set_config_int(j, uconvert_ascii("joyhat_0", tmp2), joy_hat_threshold[0]); set_config_int(j, uconvert_ascii("joyhat_1", tmp2), joy_hat_threshold[1]); set_config_int(j, uconvert_ascii("joyhat_2", tmp2), joy_hat_threshold[2]); set_config_int(j, uconvert_ascii("joyhat_3", tmp2), joy_hat_threshold[3]); return 0; } /* joy_load_data: * Loads calibration data from the config file. */ static int joy_load_data(void) { char tmp1[128], tmp2[128]; char *j = uconvert_ascii("joystick", tmp1); joystick_flags = get_config_int(j, uconvert_ascii("joystick_flags", tmp2), joystick_flags); joycentre_x = get_config_int(j, uconvert_ascii("joycentre_x", tmp2), joycentre_x); joycentre_y = get_config_int(j, uconvert_ascii("joycentre_y", tmp2), joycentre_y); joyx_min = get_config_int(j, uconvert_ascii("joyx_min", tmp2), joyx_min); joyx_low_margin = get_config_int(j, uconvert_ascii("joyx_low_margin", tmp2), joyx_low_margin); joyx_high_margin = get_config_int(j, uconvert_ascii("joyx_high_margin", tmp2), joyx_high_margin); joyx_max = get_config_int(j, uconvert_ascii("joyx_max", tmp2), joyx_max); joyy_min = get_config_int(j, uconvert_ascii("joyy_min", tmp2), joyy_min); joyy_low_margin = get_config_int(j, uconvert_ascii("joyy_low_margin", tmp2), joyy_low_margin); joyy_high_margin = get_config_int(j, uconvert_ascii("joyy_high_margin", tmp2), joyy_high_margin); joyy_max = get_config_int(j, uconvert_ascii("joyy_max", tmp2), joyy_max); joycentre2_x = get_config_int(j, uconvert_ascii("joycentre2_x", tmp2), joycentre2_x); joycentre2_y = get_config_int(j, uconvert_ascii("joycentre2_y", tmp2), joycentre2_y); joyx2_min = get_config_int(j, uconvert_ascii("joyx2_min", tmp2), joyx2_min); joyx2_low_margin = get_config_int(j, uconvert_ascii("joyx_low2_margin", tmp2), joyx2_low_margin); joyx2_high_margin = get_config_int(j, uconvert_ascii("joyx_high2_margin", tmp2), joyx2_high_margin); joyx2_max = get_config_int(j, uconvert_ascii("joyx2_max", tmp2), joyx2_max); joyy2_min = get_config_int(j, uconvert_ascii("joyy2_min", tmp2), joyy2_min); joyy2_low_margin = get_config_int(j, uconvert_ascii("joyy2_low_margin", tmp2), joyy2_low_margin); joyy2_high_margin = get_config_int(j, uconvert_ascii("joyy2_high_margin", tmp2), joyy2_high_margin); joyy2_max = get_config_int(j, uconvert_ascii("joyy2_max", tmp2), joyy2_max); joy_thr_min = get_config_int(j, uconvert_ascii("joythr_min", tmp2), joy_thr_min); joy_thr_max = get_config_int(j, uconvert_ascii("joythr_max", tmp2), joy_thr_max); joy_hat_threshold[0] = get_config_int(j, uconvert_ascii("joyhat_0", tmp2), joy_hat_threshold[0]); joy_hat_threshold[1] = get_config_int(j, uconvert_ascii("joyhat_1", tmp2), joy_hat_threshold[1]); joy_hat_threshold[2] = get_config_int(j, uconvert_ascii("joyhat_2", tmp2), joy_hat_threshold[2]); joy_hat_threshold[3] = get_config_int(j, uconvert_ascii("joyhat_3", tmp2), joy_hat_threshold[3]); joy_old_x = joy_old_y = 0; recalc_calibration_flags(); return 0; } /* next_calib_action: * Returns a flag indicating the next thing that needs to be calibrated. */ static int next_calib_action(int stick) { if (stick == 0) { /* stick 1 analogue input? */ if (!(joystick_flags & JOYSTICK_CALIB_TL1)) return JOYSTICK_CALIB_TL1; if (!(joystick_flags & JOYSTICK_CALIB_BR1)) return JOYSTICK_CALIB_BR1; /* FSPro throttle input? */ if (joystick_flags & JDESC_Y2_THROTTLE) { if (!(joystick_flags & JOYSTICK_CALIB_THRTL_MIN)) return JOYSTICK_CALIB_THRTL_MIN; if (!(joystick_flags & JOYSTICK_CALIB_THRTL_MAX)) return JOYSTICK_CALIB_THRTL_MAX; } /* Wingman Extreme hat input? */ if (joystick_flags & JDESC_Y2_HAT) { if (!(joystick_flags & JOYSTICK_CALIB_HAT_CENTRE)) return JOYSTICK_CALIB_HAT_CENTRE; if (!(joystick_flags & JOYSTICK_CALIB_HAT_LEFT)) return JOYSTICK_CALIB_HAT_LEFT; if (!(joystick_flags & JOYSTICK_CALIB_HAT_DOWN)) return JOYSTICK_CALIB_HAT_DOWN; if (!(joystick_flags & JOYSTICK_CALIB_HAT_RIGHT)) return JOYSTICK_CALIB_HAT_RIGHT; if (!(joystick_flags & JOYSTICK_CALIB_HAT_UP)) return JOYSTICK_CALIB_HAT_UP; } } else if (stick == 1) { if (joystick_flags & JDESC_STICK2) { /* stick 2 analogue input? */ if (!(joystick_flags & JOYSTICK_CALIB_TL2)) return JOYSTICK_CALIB_TL2; if (!(joystick_flags & JOYSTICK_CALIB_BR2)) return JOYSTICK_CALIB_BR2; } } return 0; } /* joy_calibrate_name: * Returns the name of the next calibration operation. */ static AL_CONST char *joy_calibrate_name(int n) { switch (next_calib_action(n)) { case JOYSTICK_CALIB_TL1: return get_config_text("Move stick to the top left"); break; case JOYSTICK_CALIB_BR1: return get_config_text("Move stick to the bottom right"); break; case JOYSTICK_CALIB_TL2: return get_config_text("Move stick 2 to the top left"); break; case JOYSTICK_CALIB_BR2: return get_config_text("Move stick 2 to the bottom right"); break; case JOYSTICK_CALIB_THRTL_MIN: return get_config_text("Set throttle to minimum"); break; case JOYSTICK_CALIB_THRTL_MAX: return get_config_text("Set throttle to maximum"); break; case JOYSTICK_CALIB_HAT_CENTRE: return get_config_text("Centre the hat"); break; case JOYSTICK_CALIB_HAT_LEFT: return get_config_text("Move the hat left"); break; case JOYSTICK_CALIB_HAT_DOWN: return get_config_text("Move the hat down"); break; case JOYSTICK_CALIB_HAT_RIGHT: return get_config_text("Move the hat right"); break; case JOYSTICK_CALIB_HAT_UP: return get_config_text("Move the hat up"); break; } return NULL; } /* joy_calibrate: * Performs the next calibration operation. */ static int joy_calibrate(int n) { switch (next_calib_action(n)) { case JOYSTICK_CALIB_TL1: return calibrate_corner(0, 0); break; case JOYSTICK_CALIB_BR1: return calibrate_corner(0, 1); break; case JOYSTICK_CALIB_TL2: return calibrate_corner(1, 0); break; case JOYSTICK_CALIB_BR2: return calibrate_corner(1, 1); break; case JOYSTICK_CALIB_THRTL_MIN: return calibrate_joystick_throttle_min(); break; case JOYSTICK_CALIB_THRTL_MAX: return calibrate_joystick_throttle_max(); break; case JOYSTICK_CALIB_HAT_CENTRE: return calibrate_joystick_hat(JOY_HAT_CENTRE); break; case JOYSTICK_CALIB_HAT_LEFT: return calibrate_joystick_hat(JOY_HAT_LEFT); break; case JOYSTICK_CALIB_HAT_DOWN: return calibrate_joystick_hat(JOY_HAT_DOWN); break; case JOYSTICK_CALIB_HAT_RIGHT: return calibrate_joystick_hat(JOY_HAT_RIGHT); break; case JOYSTICK_CALIB_HAT_UP: return calibrate_joystick_hat(JOY_HAT_UP); break; } return -1; } allegro-4.4.3.1/src/dos/dgfxdrv.c0000664000175000017500000000175213437077643015471 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of DOS graphics drivers, kept in a seperate file so that * they can be overriden by user programs. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif BEGIN_GFX_DRIVER_LIST GFX_DRIVER_VBEAF GFX_DRIVER_VGA GFX_DRIVER_MODEX GFX_DRIVER_VESA3 GFX_DRIVER_VESA2L GFX_DRIVER_VESA2B GFX_DRIVER_XTENDED GFX_DRIVER_VESA1 END_GFX_DRIVER_LIST allegro-4.4.3.1/src/dos/emu8k.h0000664000175000017500000001212013437077643015052 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Low-level functions for the AWE32 driver, by George Foot. * * Information taken primarily from "AWE32/EMU8000 Programmer's Guide" * (AEPG) by Dave Rossum. The AEPG is part of the AWE32 Developers' * Information Pack (ADIP) from Creative Labs. * * I/O port verification technique taken from "The Un-official Sound * Blaster AWE32 Programming Guide" by Vince Vu a.k.a. Judge Dredd * * See readme.txt for copyright information. */ #ifndef ALLEGRO_DOS_EMU8K_H #define ALLEGRO_DOS_EMU8K_H typedef struct envparms_t { int envvol, envval, dcysus, atkhldv; int lfo1val, atkhld, lfo2val, ip; int ifatn, pefe, fmmod, tremfrq; int fm2frq2, dcysusv, ptrx, psst; int csl, ccca, rootkey, ipbase; int ipscale, minkey, maxkey, minvel; int maxvel, key, vel, exc; int keyMEH, keyMED, keyVEH, keyVED; int filter, atten, smpmode, volrel; int modrel, pan, loopst, reverb; int chorus, volsust, modsust, pitch; int sampend; } envparms_t; #define sfgen_startAddrsOffset 0 #define sfgen_endAddrsOffset 1 #define sfgen_startloopAddrsOffset 2 #define sfgen_endloopAddrsOffset 3 #define sfgen_startAddrsCoarseOffset 4 #define sfgen_modLfoToPitch 5 #define sfgen_vibLfoToPitch 6 #define sfgen_modEnvToPitch 7 #define sfgen_initialFilterFc 8 #define sfgen_initialFilterQ 9 #define sfgen_modLfoToFilterFc 10 #define sfgen_modEnvToFilterFc 11 #define sfgen_endAddrsCoarseOffset 12 #define sfgen_modLfoToVolume 13 #define sfgen_chorusEffectsSend 15 #define sfgen_reverbEffectsSend 16 #define sfgen_pan 17 #define sfgen_delayModLFO 21 #define sfgen_freqModLFO 22 #define sfgen_delayVibLFO 23 #define sfgen_freqVibLFO 24 #define sfgen_delayModEnv 25 #define sfgen_attackModEnv 26 #define sfgen_holdModEnv 27 #define sfgen_decayModEnv 28 #define sfgen_sustainModEnv 29 #define sfgen_releaseModEnv 30 #define sfgen_keynumToModEnvHold 31 #define sfgen_keynumToModEnvDecay 32 #define sfgen_delayVolEnv 33 #define sfgen_attackVolEnv 34 #define sfgen_holdVolEnv 35 #define sfgen_decayVolEnv 36 #define sfgen_sustainVolEnv 37 #define sfgen_releaseVolEnv 38 #define sfgen_keynumToVolEnvHold 39 #define sfgen_keynumToVolEnvDecay 40 #define sfgen_instrument 41 #define sfgen_keyRange 43 #define sfgen_velRange 44 #define sfgen_startloopAddrsCoarseOffset 45 #define sfgen_keynum 46 #define sfgen_velocity 47 #define sfgen_initialAttenuation 48 #define sfgen_endloopAddrsCoarseOffset 50 #define sfgen_coarseTune 51 #define sfgen_fineTune 52 #define sfgen_sampleID 53 #define sfgen_sampleModes 54 #define sfgen_initialPitch 55 #define sfgen_scaleTuning 56 #define sfgen_exclusiveClass 57 #define sfgen_overridingRootKey 58 #define gfgen_startAddrs 59 #define gfgen_startloopAddrs 60 #define gfgen_endloopAddrs 61 #define gfgen_endAddrs 62 #define SOUNDFONT_NUM_GENERATORS 63 typedef int generators_t[SOUNDFONT_NUM_GENERATORS]; /*extern envparms_t env_default;*/ extern int _emu8k_baseport; extern int _emu8k_numchannels; void emu8k_init(void); void emu8k_startsound(int channel,struct envparms_t *envparms); void emu8k_releasesound(int channel,struct envparms_t *envparms); void emu8k_terminatesound(int channel); int emu8k_detect(void); void emu8k_modulate_atten (int channel, int atten); void emu8k_modulate_ip (int channel, int ip); void emu8k_modulate_pan (int channel, int pan); envparms_t *emu8k_createenvelope(generators_t); void emu8k_destroyenvelope(envparms_t *); void emu8k_lock(void); void *_lock_malloc(size_t size); /* malloc and lock */ #endif allegro-4.4.3.1/src/dos/gpro.c0000664000175000017500000001126413437077643014773 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the Gravis GamePad Pro. * * By Marius Fodor, using information provided by Benji York. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* driver functions */ static int gpro_init(void); static void gpro_exit(void); static int gpro_poll(void); JOYSTICK_DRIVER joystick_gpro = { JOY_TYPE_GAMEPAD_PRO, empty_string, empty_string, "GamePad Pro", gpro_init, gpro_exit, gpro_poll, NULL, NULL, NULL, NULL }; /* int read_gpp: * Reads the GamePad Pro pointed to by pad_num (0 or 1) and returns its * status. Returns 1 if the GPP returned corrupt data, or if no GPP was * detected. * * This code was converted from asm into C by Shawn Hargreaves, who didn't * really understand the original, so any errors are very probable :-) */ static int read_gpp(int pad_num) { int samples[50]; int clock_mask, data_mask, data, old_data; int num_samples, timeout1, timeout2, sample_pos, c; if (pad_num == 0) { clock_mask = 0x10; data_mask = 0x20; } else { clock_mask = 0x40; data_mask = 0x80; } num_samples = 0; timeout1 = 0; DISABLE(); old_data = inportb(0x201); data = 0; while (num_samples<50) { for (timeout2=0; timeout2<255; timeout2++) { data = inportb(0x201); if (data != old_data) break; } if (timeout2 == 255) { ENABLE(); return 1; } if ((old_data & clock_mask) && (!(data & clock_mask))) { samples[num_samples] = (data & data_mask) ? 1 : 0; num_samples++; } old_data = data; if (timeout1++ == 200) break; } ENABLE(); c = 0; for (sample_pos=1; sample_pos= 0) && (midi_recorder)) midi_recorder(c); } END_OF_FUNCTION(_mpu_poll); /* mpu_interrupt: * Handler for the MPU-401 input interrupt. */ static int mpu_interrupt(void) { _mpu_poll(); _eoi(_mpu_irq); return 0; } END_OF_STATIC_FUNCTION(mpu_interrupt); /* mpu_detect: * Detects the presence of an MPU-401 compatible midi interface. */ static int mpu_detect(int input) { char *blaster = getenv("BLASTER"); char tmp1[64], tmp2[64]; int i; _mpu_port = get_config_hex(uconvert_ascii("sound", tmp1), uconvert_ascii("mpu_port", tmp2), -1); _mpu_irq = get_config_hex(uconvert_ascii("sound", tmp1), uconvert_ascii("mpu_irq", tmp2), -1); /* only bother with the detection if we aren't already active */ if (!mpu_output_mode) { /* parse BLASTER env */ if ((blaster) && (_mpu_port < 0)) { while (*blaster) { while ((*blaster == ' ') || (*blaster == '\t')) blaster++; if (((*blaster == 'p') || (*blaster == 'P')) && (_mpu_port < 0)) _mpu_port = strtol(blaster+1, NULL, 16); if (((*blaster == 'i') || (*blaster == 'I')) && (_mpu_irq < 0)) _mpu_irq = strtol(blaster+1, NULL, 10); while ((*blaster) && (*blaster != ' ') && (*blaster != '\t')) blaster++; } } /* if that didn't work, guess :-) */ if (_mpu_port < 0) _mpu_port = 0x330; if (_mpu_irq < 0) { if (_sound_irq > 0) _mpu_irq = _sound_irq; else _mpu_irq = 7; } mpu_int = _map_irq(_mpu_irq); /* check whether the MPU is there */ outportb(_mpu_port+1, 0xFF); mpu_input(); if (wait_for_mpu(0x40, _mpu_port+1) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MPU-401 not found")); return FALSE; } uszprintf(mpu_desc, sizeof(mpu_desc), get_config_text("MPU-401 MIDI interface on port %X, using IRQ %d"), _mpu_port, _mpu_irq); midi_mpu401.desc = mpu_desc; } /* can we handle input? */ if (input) { static int conflicts[] = { DIGI_SB10, DIGI_SB15, DIGI_SB20, DIGI_SBPRO, DIGI_SB16, DIGI_AUDIODRIVE, 0 }; mpu_piggyback = FALSE; for (i=0; conflicts[i]; i++) { if (digi_card == conflicts[i]) { if (_sound_irq == _mpu_irq) { mpu_piggyback = TRUE; if (digi_card != DIGI_SB16) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MPU-401 and %s conflict over IRQ %d"), digi_driver->name, _mpu_irq); return FALSE; } } break; } } } return TRUE; } /* mpu_init: * Initialises the MPU-401 midi interface. */ static int mpu_init(int input, int voices) { if (!mpu_output_mode) { /* only do the hardware initialisation once */ outportb(_mpu_port+1, 0x3F); mpu_input(); LOCK_VARIABLE(midi_mpu401); LOCK_VARIABLE(_mpu_port); LOCK_VARIABLE(_mpu_irq); LOCK_FUNCTION(_mpu_poll); LOCK_FUNCTION(mpu_output); LOCK_FUNCTION(mpu_interrupt); } if (input) { /* only hook the interrupt if we have direct access to it */ if (!mpu_piggyback) { _enable_irq(_mpu_irq); _install_irq(mpu_int, mpu_interrupt); } mpu_input_mode = TRUE; } else mpu_output_mode = TRUE; return 0; } /* mpu_exit: * Resets the MPU-401 midi interface when we are finished. */ static void mpu_exit(int input) { if (input) { /* only unhook the interrupt if we have direct access to it */ if (!mpu_piggyback) { _remove_irq(mpu_int); _restore_irq(_mpu_irq); } mpu_input_mode = FALSE; } else mpu_output_mode = FALSE; if ((!mpu_input_mode) && (!mpu_output_mode)) { /* shut down the hardware once nothing is active */ outportb(_mpu_port+1, 0xFF); } } allegro-4.4.3.1/src/dos/djirqs.s0000664000175000017500000001272213437077643015340 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The djgpp interrupt wrappers used by the stuff in djirq.c. * * By Shawn Hargreaves. * * Thanks to Marcel de Kogel for identifying the problems Allegro was * having with reentrant interrupts, and for suggesting this solution. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" .text #define WRAPPER(x) ; \ FUNC(_irq_wrapper_##x) ; \ pushw %ds /* save registers */ ; \ pushw %es ; \ pushw %fs ; \ pushw %gs ; \ pushal ; \ ; \ .byte 0x2e /* cs: override */ ; \ movw GLOBL(__djgpp_ds_alias), %ax ; \ movw %ax, %ds /* set up selectors */ ; \ movw %ax, %es ; \ movw %ax, %fs ; \ movw %ax, %gs ; \ ; \ movl $IRQ_STACKS-1, %ecx /* look for a free stack */ ; \ ; \ stack_search_loop_##x: ; \ leal GLOBL(_irq_stack)(, %ecx, 4), %ebx ; \ cmpl $0, (%ebx) ; \ jnz found_stack_##x /* found one! */ ; \ ; \ decl %ecx ; \ jge stack_search_loop_##x ; \ ; \ jmp get_out_##x /* oh shit.. */ ; \ ; \ found_stack_##x: ; \ movl %esp, %ecx /* old stack in ecx + dx */ ; \ movw %ss, %dx ; \ ; \ movl (%ebx), %esp /* set up our stack */ ; \ movw %ax, %ss ; \ ; \ movl $0, (%ebx) /* flag the stack is in use */ ; \ ; \ pushl %edx /* push old stack onto new */ ; \ pushl %ecx ; \ pushl %ebx ; \ ; \ cld /* clear the direction flag */ ; \ ; \ movl GLOBL(_irq_handler) + IRQ_HANDLER + IRQ_SIZE*x, %eax ; \ call *%eax /* call the C handler */ ; \ ; \ cli ; \ ; \ popl %ebx /* restore the old stack */ ; \ popl %ecx ; \ popl %edx ; \ movl %esp, (%ebx) ; \ movw %dx, %ss ; \ movl %ecx, %esp ; \ ; \ orl %eax, %eax /* check return value */ ; \ jz get_out_##x ; \ ; \ popal /* chain to old handler */ ; \ popw %gs ; \ popw %fs ; \ popw %es ; \ popw %ds ; \ ljmp *%cs:GLOBL(_irq_handler) + IRQ_OLDVEC + IRQ_SIZE*x ; \ ; \ get_out_##x: ; \ popal /* iret */ ; \ popw %gs ; \ popw %fs ; \ popw %es ; \ popw %ds ; \ sti ; \ iret WRAPPER(0); WRAPPER(1); WRAPPER(2); WRAPPER(3); WRAPPER(4); WRAPPER(5); WRAPPER(6); WRAPPER(7); FUNC(_irq_wrapper_0_end) ret allegro-4.4.3.1/src/dos/dmouse.c0000664000175000017500000003144513437077643015323 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DOS mouse module. * * By Shawn Hargreaves. * * 3-button support added by Fabian Nunez. * * Mark Wodrich added double-buffered drawing of the mouse pointer and * the set_mouse_sprite_focus() function. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif static int mouse_mx = 0; /* internal position, in mickeys */ static int mouse_my = 0; static int mouse_sx = 2; /* mickey -> pixel scaling factor */ static int mouse_sy = 2; static int mouse_minx = 0; /* mouse range */ static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int mymickey_x = 0; /* for get_mouse_mickeys() */ static int mymickey_y = 0; static int mymickey_ox = 0; static int mymickey_oy = 0; #ifdef ALLEGRO_DJGPP static _go32_dpmi_seginfo mouse_seginfo; #endif static __dpmi_regs mouse_regs; #define MICKEY_TO_COORD_X(n) ((n) / mouse_sx) #define MICKEY_TO_COORD_Y(n) ((n) / mouse_sy) #define COORD_TO_MICKEY_X(n) ((n) * mouse_sx) #define COORD_TO_MICKEY_Y(n) ((n) * mouse_sy) #define CLEAR_MICKEYS() \ { \ __dpmi_regs regs; \ regs.x.ax = 11; \ __dpmi_int(0x33, ®s); \ mymickey_ox = 0; \ mymickey_oy = 0; \ } /* this driver does all our own position tracking, avoiding int 0x33 bugs */ static int mick_init(void); static void mick_exit(void); static void mick_position(int x, int y); static void mick_set_range(int x1, int y1, int x2, int y2); static void mick_set_speed(int xspeed, int yspeed); static void mick_get_mickeys(int *mickeyx, int *mickeyy); MOUSE_DRIVER mousedrv_mickeys = { MOUSEDRV_MICKEYS, empty_string, empty_string, "Mickey mouse", mick_init, mick_exit, NULL, NULL, mick_position, mick_set_range, mick_set_speed, mick_get_mickeys, NULL, NULL, NULL }; /* this driver uses the int 0x33 movement callbacks */ static int int33_init(void); static void int33_exit(void); static void int33_position(int x, int y); static void int33_set_range(int x1, int y1, int x2, int y2); static void int33_set_speed(int xspeed, int yspeed); static void int33_get_mickeys(int *mickeyx, int *mickeyy); MOUSE_DRIVER mousedrv_int33 = { MOUSEDRV_INT33, empty_string, empty_string, "Int 0x33 mouse", int33_init, int33_exit, NULL, NULL, int33_position, int33_set_range, int33_set_speed, int33_get_mickeys, NULL, NULL, NULL }; /* this driver polls int 0x33 from a timer handler */ static int polling_init(void); static void polling_exit(void); static void polling_timer_poll(void); MOUSE_DRIVER mousedrv_polling = { MOUSEDRV_POLLING, empty_string, empty_string, "Polling mouse", polling_init, polling_exit, NULL, polling_timer_poll, int33_position, int33_set_range, int33_set_speed, int33_get_mickeys, NULL, NULL, NULL }; /* this driver is a wrapper for the polling driver*/ static int winnt_init(void); MOUSE_DRIVER mousedrv_winnt = { MOUSEDRV_POLLING, empty_string, empty_string, "Windows NT mouse", winnt_init, polling_exit, NULL, polling_timer_poll, int33_position, int33_set_range, int33_set_speed, int33_get_mickeys, NULL, NULL, NULL }; /* this driver is a wrapper for the mickeys driver */ static int win2k_init(void); MOUSE_DRIVER mousedrv_win2k = { MOUSEDRV_MICKEYS, empty_string, empty_string, "Windows 2000 mouse", win2k_init, mick_exit, NULL, NULL, mick_position, mick_set_range, mick_set_speed, mick_get_mickeys, NULL, NULL, NULL }; /* list the available drivers */ _DRIVER_INFO _mouse_driver_list[] = { { MOUSEDRV_MICKEYS, &mousedrv_mickeys, TRUE }, { MOUSEDRV_INT33, &mousedrv_int33, TRUE }, { MOUSEDRV_POLLING, &mousedrv_polling, TRUE }, { MOUSEDRV_WINNT, &mousedrv_winnt, TRUE }, { MOUSEDRV_WIN2K, &mousedrv_win2k, TRUE }, { MOUSEDRV_NONE, &mousedrv_none, TRUE }, { 0, NULL, 0 } }; /* init_mouse: * Helper for initialising the int 0x33 driver and installing an RMCB. */ static int init_mouse(void (*handler)(__dpmi_regs *r)) { __dpmi_regs r; int num_buttons; /* initialise the int 0x33 driver */ r.x.ax = 0; __dpmi_int(0x33, &r); if (r.x.ax == 0) return -1; num_buttons = r.x.bx; if (num_buttons == 0xFFFF) num_buttons = 2; /* create and activate a real mode callback */ if (handler) { LOCK_VARIABLE(mouse_regs); #ifdef ALLEGRO_DJGPP /* djgpp version uses libc routines to set up the RMCB */ { LOCK_VARIABLE(mouse_seginfo); mouse_seginfo.pm_offset = (int)handler; mouse_seginfo.pm_selector = _my_cs(); if (_go32_dpmi_allocate_real_mode_callback_retf(&mouse_seginfo, &mouse_regs) != 0) return -1; r.x.ax = 0x0C; r.x.cx = 0x7F; r.x.dx = mouse_seginfo.rm_offset; r.x.es = mouse_seginfo.rm_segment; __dpmi_int(0x33, &r); } #elif defined ALLEGRO_WATCOM /* Watcom version relies on the DOS extender to do it for us */ { struct SREGS sregs; union REGS inregs, outregs; inregs.w.ax = 0x0C; inregs.w.cx = 0x7F; inregs.x.edx = _allocate_real_mode_callback(handler, &mouse_regs); segread(&sregs); sregs.es = _my_cs(); int386x(0x33, &inregs, &outregs, &sregs); } #else #error unknown platform #endif } return num_buttons; } /* mick_handler: * Movement callback for mickey-mode driver. */ static void mick_handler(__dpmi_regs *r) { int x = (signed short)r->x.si; int y = (signed short)r->x.di; _mouse_b = r->x.bx; mymickey_x += x - mymickey_ox; mymickey_y += y - mymickey_oy; mymickey_ox = x; mymickey_oy = y; _mouse_x = MICKEY_TO_COORD_X(mouse_mx + x); _mouse_y = MICKEY_TO_COORD_Y(mouse_my + y); if ((_mouse_x < mouse_minx) || (_mouse_x > mouse_maxx) || (_mouse_y < mouse_miny) || (_mouse_y > mouse_maxy)) { _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); CLEAR_MICKEYS(); } _handle_mouse_input(); } END_OF_STATIC_FUNCTION(mick_handler); /* mick_position: * Sets the position of the mickey-mode mouse. */ static void mick_position(int x, int y) { DISABLE(); _mouse_x = x; _mouse_y = y; mouse_mx = COORD_TO_MICKEY_X(x); mouse_my = COORD_TO_MICKEY_Y(y); CLEAR_MICKEYS(); mymickey_x = mymickey_y = 0; ENABLE(); } /* mick_set_range: * Sets the range of the mickey-mode mouse. */ static void mick_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; DISABLE(); _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); CLEAR_MICKEYS(); ENABLE(); } /* mick_set_speed: * Sets the speed of the mickey-mode mouse. */ static void mick_set_speed(int xspeed, int yspeed) { DISABLE(); mouse_sx = MAX(1, xspeed); mouse_sy = MAX(1, yspeed); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); CLEAR_MICKEYS(); ENABLE(); } /* mick_get_mickeys: * Reads the mickey-mode count. */ static void mick_get_mickeys(int *mickeyx, int *mickeyy) { int temp_x = mymickey_x; int temp_y = mymickey_y; mymickey_x -= temp_x; mymickey_y -= temp_y; *mickeyx = temp_x; *mickeyy = temp_y; } /* mick_lock: * Locks the mickeys stuff. */ static void mick_lock(void) { LOCK_VARIABLE(mousedrv_mickeys); LOCK_VARIABLE(mouse_mx); LOCK_VARIABLE(mouse_my); LOCK_VARIABLE(mouse_sx); LOCK_VARIABLE(mouse_sy); LOCK_VARIABLE(mouse_minx); LOCK_VARIABLE(mouse_miny); LOCK_VARIABLE(mouse_maxx); LOCK_VARIABLE(mouse_maxy); LOCK_VARIABLE(mymickey_x); LOCK_VARIABLE(mymickey_y); LOCK_VARIABLE(mymickey_ox); LOCK_VARIABLE(mymickey_oy); LOCK_FUNCTION(mick_handler); } /* mick_init: * Initialises the mickey-mode driver. */ static int mick_init(void) { if (os_type == OSTYPE_WINNT) return -1; mick_lock(); return init_mouse(mick_handler); } /* win2k_init: * Initialises the win2k driver. */ static int win2k_init(void) { /* only for use under Win2k */ if (os_type != OSTYPE_WINNT) return -1; mick_lock(); return init_mouse(mick_handler); } /* mick_exit: * Shuts down the mickey-mode driver. */ static void mick_exit(void) { __dpmi_regs r; r.x.ax = 0x0C; /* install NULL callback */ r.x.cx = 0; r.x.dx = 0; r.x.es = 0; __dpmi_int(0x33, &r); #ifdef ALLEGRO_DJGPP _go32_dpmi_free_real_mode_callback(&mouse_seginfo); #endif } /* int33_handler: * Movement callback for the int 0x33 driver. */ static void int33_handler(__dpmi_regs *r) { _mouse_x = r->x.cx / 8; _mouse_y = r->x.dx / 8; _mouse_b = r->x.bx; _handle_mouse_input(); } END_OF_STATIC_FUNCTION(int33_handler); /* int33_position: * Sets the int 0x33 cursor position. */ static void int33_position(int x, int y) { __dpmi_regs r; _mouse_x = x; _mouse_y = y; r.x.ax = 4; r.x.cx = x * 8; r.x.dx = y * 8; __dpmi_int(0x33, &r); r.x.ax = 11; __dpmi_int(0x33, &r); } /* int33_set_range: * Sets the int 0x33 movement range. */ static void int33_set_range(int x1, int y1, int x2, int y2) { __dpmi_regs r; r.x.ax = 7; /* set horizontal range */ r.x.cx = x1 * 8; r.x.dx = x2 * 8; __dpmi_int(0x33, &r); r.x.ax = 8; /* set vertical range */ r.x.cx = y1 * 8; r.x.dx = y2 * 8; __dpmi_int(0x33, &r); r.x.ax = 3; /* check the position */ __dpmi_int(0x33, &r); _mouse_x = r.x.cx / 8; _mouse_y = r.x.dx / 8; } /* int33_set_speed: * Sets the int 0x33 movement speed. */ static void int33_set_speed(int xspeed, int yspeed) { __dpmi_regs r; r.x.ax = 15; r.x.cx = xspeed; r.x.dx = yspeed; __dpmi_int(0x33, &r); } /* int33_get_mickeys: * Reads the int 0x33 mickey count. */ static void int33_get_mickeys(int *mickeyx, int *mickeyy) { __dpmi_regs r; r.x.ax = 11; __dpmi_int(0x33, &r); *mickeyx = (signed short)r.x.cx; *mickeyy = (signed short)r.x.dx; } /* int33_init: * Initialises the int 0x33 driver. */ static int int33_init(void) { if (os_type == OSTYPE_WINNT) return -1; LOCK_VARIABLE(mousedrv_int33); LOCK_FUNCTION(int33_handler); return init_mouse(int33_handler); } /* int33_exit: * Shuts down the int 0x33 driver. */ static void int33_exit(void) { __dpmi_regs r; r.x.ax = 0x0C; /* install NULL callback */ r.x.cx = 0; r.x.dx = 0; r.x.es = 0; __dpmi_int(0x33, &r); r.x.ax = 15; /* reset sensitivity */ r.x.cx = 8; r.x.dx = 16; __dpmi_int(0x33, &r); #ifdef ALLEGRO_DJGPP _go32_dpmi_free_real_mode_callback(&mouse_seginfo); #endif } /* polling_timer_poll: * Handler for the periodic timer polling mode. */ static void polling_timer_poll(void) { __dpmi_regs r; r.x.ax = 3; __dpmi_int(0x33, &r); _mouse_b = r.x.bx; _mouse_x = r.x.cx / 8; _mouse_y = r.x.dx / 8; } END_OF_STATIC_FUNCTION(polling_timer_poll); /* polling_init: * Initialises the periodic timer driver. */ static int polling_init(void) { if (os_type == OSTYPE_WINNT) return -1; LOCK_VARIABLE(mousedrv_polling); LOCK_FUNCTION(polling_timer_poll); return init_mouse(NULL); } /* winnt_init: * Initialises the WinNT driver. */ static int winnt_init(void) { /* only for use under WinNT */ if (os_type != OSTYPE_WINNT) return -1; LOCK_VARIABLE(mousedrv_polling); LOCK_FUNCTION(polling_timer_poll); return init_mouse(NULL); } /* polling_exit: * Shuts down the periodic timer driver. */ static void polling_exit(void) { __dpmi_regs r; r.x.ax = 15; /* reset sensitivity */ r.x.cx = 8; r.x.dx = 16; __dpmi_int(0x33, &r); } allegro-4.4.3.1/src/dos/wat.c0000664000175000017500000004165613437077643014627 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper functions to make things work with Watcom. This file * emulates the DPMI support functions from the djgpp libc, and * provides interrupt wrapper routines using the same API as the * stuff in djirq.c. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #include "../i386/asmdefs.inc" /* some useful globals */ static int out_eax, out_ebx, out_ecx, out_edx, out_esi, out_edi; #define MAX_IRQS 8 #define STACK_SIZE 8192 static _IRQ_HANDLER irq_handler[MAX_IRQS]; static unsigned char *irq_stack[IRQ_STACKS]; static unsigned char *rmcb_stack; static void (__interrupt __far *old_int24)() = NULL; unsigned long __tb = 0; static int tb_sel = 0; int __djgpp_ds_alias = 0; /* my_int24: * Stop those stupid "abort, retry, fail" messages from popping up all * over the place. */ #if __WATCOMC__ >= 1200 static void __interrupt __far my_int24(void) {} #else static int __interrupt __far my_int24(void) { return 3; } #endif /* _dos_irq_init: * Initialises this module. */ void _dos_irq_init(void) { int c; old_int24 = _dos_getvect(0x24); _dos_setvect(0x24, my_int24); __tb = __dpmi_allocate_dos_memory(16384/16, &tb_sel) * 16; __djgpp_ds_alias = _default_ds(); for (c=0; cx.flags = 0; regs->x.sp = 0; regs->x.ss = 0; return DPMI(0x300, vector, 0, 0, 0, (int)regs); } /* __dpmi_simulate_real_mode_interrupt: * Watcom implementation of the djgpp library routine. */ int __dpmi_simulate_real_mode_interrupt(int vector, __dpmi_regs *regs) { return DPMI(0x300, vector, 0, 0, 0, (int)regs); } /* __dpmi_simulate_real_mode_procedure_retf: * Watcom implementation of the djgpp library routine. */ int __dpmi_simulate_real_mode_procedure_retf(__dpmi_regs *regs) { return DPMI(0x301, 0, 0, 0, 0, (int)regs); } /* __dpmi_allocate_dos_memory: * Watcom implementation of the djgpp library routine. */ int __dpmi_allocate_dos_memory(int paragraphs, int *ret) { if (DPMI_OUT(0x100, paragraphs, 0, 0, 0, 0) != 0) return -1; *ret = (out_edx & 0xFFFF); return (out_eax & 0xFFFF); } /* __dpmi_free_dos_memory: * Watcom implementation of the djgpp library routine. */ int __dpmi_free_dos_memory(int selector) { return DPMI(0x101, 0, 0, selector, 0, 0); } /* __dpmi_physical_address_mapping: * Watcom implementation of the djgpp library routine. */ int __dpmi_physical_address_mapping(__dpmi_meminfo *info) { if (DPMI_OUT(0x800, (info->address >> 16), (info->address & 0xFFFF), 0, (info->size >> 16), (info->size & 0xFFFF)) != 0) return -1; info->address = (out_ebx << 16) | (out_ecx & 0xFFFF); return 0; } /* __dpmi_free_physical_address_mapping: * Watcom implementation of the djgpp library routine. */ int __dpmi_free_physical_address_mapping(__dpmi_meminfo *info) { return DPMI(0x801, (info->address >> 16), (info->address & 0xFFFF), 0, 0, 0); } /* __dpmi_lock_linear_region: * Watcom implementation of the djgpp library routine. */ int __dpmi_lock_linear_region(__dpmi_meminfo *info) { return DPMI(0x600, (info->address >> 16), (info->address & 0xFFFF), 0, (info->size >> 16), (info->size & 0xFFFF)); } /* __dpmi_unlock_linear_region: * Watcom implementation of the djgpp library routine. */ int __dpmi_unlock_linear_region(__dpmi_meminfo *info) { return DPMI(0x601, (info->address >> 16), (info->address & 0xFFFF), 0, (info->size >> 16), (info->size & 0xFFFF)); } /* _go32_dpmi_lock_data: * Watcom implementation of the djgpp library routine. */ int _go32_dpmi_lock_data(void *lockaddr, unsigned long locksize) { unsigned long baseaddr; __dpmi_meminfo meminfo; if (__dpmi_get_segment_base_address(_default_ds(), &baseaddr) != 0) return -1; meminfo.handle = 0; meminfo.size = locksize; meminfo.address = baseaddr + (unsigned long)lockaddr; return __dpmi_lock_linear_region(&meminfo); } /* _go32_dpmi_lock_code: * Watcom implementation of the djgpp library routine. */ int _go32_dpmi_lock_code(void *lockaddr, unsigned long locksize) { unsigned long baseaddr; __dpmi_meminfo meminfo; if (__dpmi_get_segment_base_address(_my_cs(), &baseaddr) != 0) return -1; meminfo.handle = 0; meminfo.size = locksize; meminfo.address = baseaddr + (unsigned long)lockaddr; return __dpmi_lock_linear_region(&meminfo); } /* __dpmi_allocate_ldt_descriptors: * Watcom implementation of the djgpp library routine. */ int __dpmi_allocate_ldt_descriptors(int count) { if (DPMI_OUT(0x000, 0, count, 0, 0, 0) != 0) return -1; return (out_eax & 0xFFFF); } /* __dpmi_free_ldt_descriptor: * Watcom implementation of the djgpp library routine. */ int __dpmi_free_ldt_descriptor(int descriptor) { return DPMI(0x001, descriptor, 0, 0, 0, 0); } /* __dpmi_get_segment_base_address: * Watcom implementation of the djgpp library routine. */ int __dpmi_get_segment_base_address(int selector, unsigned long *addr) { if (DPMI_OUT(0x006, selector, 0, 0, 0, 0) != 0) return -1; *addr = (out_ecx << 16) | (out_edx & 0xFFFF); return 0; } /* __dpmi_set_segment_base_address: * Watcom implementation of the djgpp library routine. */ int __dpmi_set_segment_base_address(int selector, unsigned long address) { return DPMI(0x007, selector, (address >> 16), (address & 0xFFFF), 0, 0); } /* __dpmi_set_segment_limit: * Watcom implementation of the djgpp library routine. */ int __dpmi_set_segment_limit(int selector, unsigned long limit) { return DPMI(0x008, selector, (limit >> 16), (limit & 0xFFFF), 0, 0); } /* __dpmi_get_free_memory_information: * Watcom implementation of the djgpp library routine. */ int __dpmi_get_free_memory_information(__dpmi_free_mem_info *info) { return DPMI(0x500, 0, 0, 0, 0, (int)info); } /* switches to a custom stack when running interrupt code */ int CALL_HANDLER(int (*func)(void), int max_stack); #pragma aux CALL_HANDLER = \ " push ds " \ " pop es " \ \ " stack_search_loop: " /* look for a free stack */ \ " lea ebx, irq_stack[ecx*4] " \ " cmp [ebx], 0 " \ " jnz found_stack " /* found one! */ \ \ " dec ecx " \ " jge stack_search_loop " \ \ " mov eax, 0 " /* oh shit.. */ \ " jmp get_out " \ \ " found_stack: " \ " mov ecx, esp " /* old stack in ecx + dx */ \ " mov dx, ss " \ \ " mov ax, ds " /* set up our stack */ \ " mov ss, ax " \ " mov esp, [ebx] " \ \ " mov dword ptr [ebx], 0 " /* flag the stack is in use */ \ \ " push edx " /* push old stack onto new */ \ " push ecx " \ " push ebx " \ \ " cld " /* call the handler */ \ " cli " \ " call esi " \ \ " pop ebx " /* restore the old stack */ \ " pop ecx " \ " pop edx " \ " mov [ebx], esp " \ " mov ss, dx " \ " mov esp, ecx " \ " get_out: " \ \ parm [esi] [ecx] \ modify [ebx edx edi] \ value [eax]; /* interrupt wrapper */ #define WRAPPER(num) \ \ static void __interrupt __far irq_wrapper_##num() \ { \ if (CALL_HANDLER(irq_handler[num].handler, IRQ_STACKS-1)) \ _chain_intr(irq_handler[num].old_vector); \ } WRAPPER(0); WRAPPER(1); WRAPPER(2); WRAPPER(3); WRAPPER(4); WRAPPER(5); WRAPPER(6); WRAPPER(7); END_OF_STATIC_FUNCTION(irq_wrapper_0); /* _install_irq: * Installs a custom IRQ handler. */ int _install_irq(int num, int (*handler)(void)) { int c; LOCK_FUNCTION(irq_wrapper_0); for (c=0; c */ joy[num].stick[0].axis[0].d2 = !(i & 0x08); /* <- */ joy[num].stick[0].axis[1].d1 = !(i & 0x01); /* */ joy[num].stick[0].axis[1].d2 = !(i & 0x02); /* ^ */ for (i = 0; i <= 1; i++) { if (joy[num].stick[0].axis[i].d1) joy[num].stick[0].axis[i].pos = -128; else { if (joy[num].stick[0].axis[i].d2) joy[num].stick[0].axis[i].pos = 128; else joy[num].stick[0].axis[i].pos = 0; } } _sg_pci_ioout(base + 0x100, 0x60); return num; } allegro-4.4.3.1/src/dos/dkeybd.c0000664000175000017500000001477213437077643015275 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * DOS keyboard module. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define KEYBOARD_INT 9 static int leds_ok = TRUE; static int in_a_terrupt = FALSE; static int extended_key = FALSE; static int pcdos_key_init(void); static void pcdos_key_exit(void); static void pcdos_set_leds(int leds); static void pcdos_set_rate(int delay, int rate); KEYBOARD_DRIVER keydrv_pcdos = { KEYDRV_PCDOS, empty_string, empty_string, "PC keyboard (DOS)", FALSE, pcdos_key_init, pcdos_key_exit, NULL, pcdos_set_leds, pcdos_set_rate, NULL, NULL, _pckey_scancode_to_ascii, _pckey_scancode_to_name }; /* list the available drivers */ _DRIVER_INFO _keyboard_driver_list[] = { { KEYDRV_PCDOS, &keydrv_pcdos, TRUE }, { 0, NULL, 0 } }; /* kb_wait_for_write_ready: * Wait for the keyboard controller to set the ready-for-write bit. */ static INLINE int kb_wait_for_write_ready(void) { int timeout = 4096; while ((timeout > 0) && (inportb(0x64) & 2)) timeout--; return (timeout > 0); } /* kb_wait_for_read_ready: * Wait for the keyboard controller to set the ready-for-read bit. */ static INLINE int kb_wait_for_read_ready(void) { int timeout = 16384; while ((timeout > 0) && (!(inportb(0x64) & 1))) timeout--; return (timeout > 0); } /* kb_send_data: * Sends a byte to the keyboard controller. Returns 1 if all OK. */ static INLINE int kb_send_data(unsigned char data) { int resends = 4; int timeout, temp; do { if (!kb_wait_for_write_ready()) return 0; outportb(0x60, data); timeout = 4096; while (--timeout > 0) { if (!kb_wait_for_read_ready()) return 0; temp = inportb(0x60); if (temp == 0xFA) return 1; if (temp == 0xFE) break; } } while ((resends-- > 0) && (timeout > 0)); return 0; } /* pcdos_set_leds: * Updates the LED state. */ static void pcdos_set_leds(int leds) { if (!leds_ok) return; if (!in_a_terrupt) DISABLE(); if (!kb_send_data(0xED)) { kb_send_data(0xF4); leds_ok = FALSE; } else if (!kb_send_data((leds>>8) & 7)) { kb_send_data(0xF4); leds_ok = FALSE; } if (!in_a_terrupt) ENABLE(); } END_OF_STATIC_FUNCTION(pcdos_set_leds); /* pcdos_set_rate: * Sets the key repeat rate. */ static void pcdos_set_rate(int delay, int rate) { if (!leds_ok) return; if (delay < 375) delay = 0; else if (delay < 625) delay = 1; else if (delay < 875) delay = 2; else delay = 3; rate = CLAMP(0, (rate-33) * 31 / (500-33), 31); DISABLE(); if ((!kb_send_data(0xF3)) || (!kb_send_data((delay << 5) | rate))) kb_send_data(0xF4); ENABLE(); } /* keyint: * Hardware level keyboard interrupt (int 9) handler. */ static int keyint(void) { int code = inportb(0x60); in_a_terrupt = TRUE; _handle_pckey(code); in_a_terrupt = FALSE; #ifdef ALLEGRO_DJGPP /* three-finger salute for killing the program */ if (three_finger_flag) { if (((code == 0x4F) || (code == 0x53)) && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG)) { asm ( " movb $0x79, %%al ; " " call ___djgpp_hw_exception " : : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" ); } /* also handle ctrl+break, like the standard djgpp libc */ if ((code == 0x46) && (extended_key) && (_key_shifts & KB_CTRL_FLAG)) { asm ( " movb $0x1B, %%al ; " " call ___djgpp_hw_exception " : : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" ); } } #endif extended_key = (code == 0xE0); outportb(0x20, 0x20); return 0; } END_OF_STATIC_FUNCTION(keyint); /* pcdos_key_init: * Installs the keyboard handler. */ static int pcdos_key_init(void) { int s1, s2, s3; _pckeys_init(); LOCK_VARIABLE(leds_ok); LOCK_VARIABLE(in_a_terrupt); LOCK_VARIABLE(extended_key); LOCK_FUNCTION(pcdos_set_leds); LOCK_FUNCTION(keyint); /* read the current BIOS keyboard state */ while (kbhit()) simulate_keypress(getch()); _farsetsel(_dos_ds); s1 = _farnspeekb(0x417); s2 = _farnspeekb(0x418); s3 = _farnspeekb(0x496); _key_shifts = 0; if (s1 & 1) { _key_shifts |= KB_SHIFT_FLAG; key[KEY_RSHIFT] = TRUE; } if (s1 & 2) { _key_shifts |= KB_SHIFT_FLAG; key[KEY_LSHIFT] = TRUE; } if (s2 & 1) { _key_shifts |= KB_CTRL_FLAG; key[KEY_LCONTROL] = TRUE; } if (s2 & 2) { _key_shifts |= KB_ALT_FLAG; key[KEY_ALT] = TRUE; } if (s3 & 4) { _key_shifts |= KB_CTRL_FLAG; key[KEY_RCONTROL] = TRUE; } if (s3 & 8) { _key_shifts |= KB_ALT_FLAG; key[KEY_ALTGR] = TRUE; } if (s1 & 16) _key_shifts |= KB_SCROLOCK_FLAG; if (s1 & 32) _key_shifts |= KB_NUMLOCK_FLAG; if (s1 & 64) _key_shifts |= KB_CAPSLOCK_FLAG; key_shifts = _key_shifts; _install_irq(KEYBOARD_INT, keyint); pcdos_set_leds(_key_shifts); return 0; } /* pcdos_key_exit: * Removes the keyboard handler. */ static void pcdos_key_exit(void) { int s1, s2, s3; _remove_irq(KEYBOARD_INT); /* transfer state info back to the BIOS */ _farsetsel(_dos_ds); s1 = _farnspeekb(0x417) & 0x80; s2 = _farnspeekb(0x418) & 0xFC; s3 = _farnspeekb(0x496) & 0xF3; if (key[KEY_RSHIFT]) { s1 |= 1; } if (key[KEY_LSHIFT]) { s1 |= 2; } if (key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; } if (key[KEY_ALT]) { s1 |= 8; s2 |= 2; } if (key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; } if (key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; } if (_key_shifts & KB_SCROLOCK_FLAG) s1 |= 16; if (_key_shifts & KB_NUMLOCK_FLAG) s1 |= 32; if (_key_shifts & KB_CAPSLOCK_FLAG) s1 |= 64; _farsetsel(_dos_ds); _farnspokeb(0x417, s1); _farnspokeb(0x418, s2); _farnspokeb(0x496, s3); } allegro-4.4.3.1/src/dos/ww.c0000664000175000017500000001403513437077643014460 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for the Wingman Warrior. * * By Kester Maddock * * TODO: Support all SWIFT devices. x and y values are correct, * my Wingman always has these set to 0, joystick values in * pitch and roll. Joystick values range from -8192 to 8192, I * >> by 6 to get -128 to 128 Allegro range. Spinner's range is * +/- 18? I would recommend setting x/y values to hat switch's * axis, and reading the hat switch as buttons instead of an axis. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif /* driver functions */ static int ww_init(void); static void ww_exit(void); static int ww_poll(void); typedef union SWIFT_T { struct { unsigned char type; } swift; struct { short x; /* unused */ short y; /* unused */ short z; /* throttle */ short pitch; /* stick y axis */ short roll; /* stick x axis */ short yaw; /* spinner */ short buttons; } data; } SWIFT_T; static SWIFT_T *wingman = NULL; JOYSTICK_DRIVER joystick_ww = { JOY_TYPE_WINGWARRIOR, empty_string, empty_string, "Wingman Warrior", ww_init, ww_exit, ww_poll, NULL, NULL, NULL, NULL }; /* ww_init: * Initialises the driver. */ static int ww_init(void) { __dpmi_regs r; wingman = _AL_MALLOC(sizeof(SWIFT_T)); memset(wingman, 0, sizeof(SWIFT_T)); memset(&r, 0, sizeof(r)); r.d.eax = 0x53C1; r.x.es = __tb >> 4; r.d.edx = 0; __dpmi_int(0x33, &r); dosmemget(__tb, sizeof(SWIFT_T), wingman); if (r.x.ax != 1) { /* SWIFT functions not present */ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("SWIFT Device not detected")); _AL_FREE(wingman); wingman = NULL; return -1; } if (wingman->swift.type != 1) { /* no SWIFT device, or not Wingman */ if (wingman->swift.type == 0) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Wingman Warrior not connected")); else ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Device connected is not a Wingman Warrior")); _AL_FREE(wingman); wingman = NULL; return -1; } num_joysticks = 1; joy[0].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].num_sticks = 4; joy[0].num_buttons = 4; joy[0].stick[0].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].stick[0].num_axis = 2; joy[0].stick[0].name = get_config_text("Stick"); joy[0].stick[0].axis[0].name = get_config_text("X"); joy[0].stick[0].axis[1].name = get_config_text("Y"); joy[0].stick[1].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[0].stick[1].num_axis = 1; joy[0].stick[1].name = joy[0].stick[1].axis[0].name = get_config_text("Spinner"); joy[0].stick[2].flags = JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; joy[0].stick[2].num_axis = 1; joy[0].stick[2].name = joy[0].stick[2].axis[0].name = get_config_text("Throttle"); joy[0].stick[3].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[0].stick[3].num_axis = 2; joy[0].stick[3].name = get_config_text("Hat"); joy[0].stick[3].axis[0].name = get_config_text("X"); joy[0].stick[3].axis[1].name = get_config_text("Y"); joy[0].button[0].name = get_config_text("B1"); joy[0].button[1].name = get_config_text("B2"); joy[0].button[2].name = get_config_text("B3"); joy[0].button[3].name = get_config_text("B4"); return 0; } /* ww_poll: * Polls the joystick state. */ static int ww_poll(void) { __dpmi_regs r; /* no wingman for you */ if (!wingman) return -1; /* read from the mouse driver */ memset(&r, 0, sizeof(r)); r.d.eax = 0x5301; r.x.es = __tb >> 4; r.d.edx = 0; __dpmi_int(0x33, &r); dosmemget(__tb, sizeof(SWIFT_T), wingman); /* main X/Y axis */ joy[0].stick[0].axis[0].pos = -wingman->data.roll >> 6; joy[0].stick[0].axis[1].pos = wingman->data.pitch >> 6; /* spin control */ joy[0].stick[1].axis[0].pos = -wingman->data.yaw * 7; /* throttle */ joy[0].stick[2].axis[0].pos = (wingman->data.z >> 6) + 128; /* setup digital controls */ joy[0].stick[0].axis[0].d1 = joy[0].stick[0].axis[0].pos < -64; joy[0].stick[0].axis[0].d2 = joy[0].stick[0].axis[0].pos > 64; joy[0].stick[0].axis[1].d1 = joy[0].stick[0].axis[1].pos < -64; joy[0].stick[0].axis[1].d2 = joy[0].stick[0].axis[1].pos > 64; joy[0].stick[1].axis[0].d1 = joy[0].stick[1].axis[0].pos < -64; joy[0].stick[1].axis[0].d2 = joy[0].stick[1].axis[0].pos > 64; joy[0].stick[2].axis[0].d2 = joy[0].stick[2].axis[0].pos > 255*2/3; /* setup buttons */ joy[0].button[0].b = wingman->data.buttons & 0x4; joy[0].button[1].b = wingman->data.buttons & 0x1; joy[0].button[2].b = wingman->data.buttons & 0x2; joy[0].button[3].b = wingman->data.buttons & 0x10; /* hat switch */ joy[0].stick[0].axis[0].d1 = wingman->data.buttons & 0x020; joy[0].stick[0].axis[0].d2 = wingman->data.buttons & 0x040; joy[0].stick[0].axis[1].d1 = wingman->data.buttons & 0x080; joy[0].stick[0].axis[1].d2 = wingman->data.buttons & 0x100; joy[0].stick[0].axis[0].pos = 128*joy[0].stick[0].axis[0].d2 - 128*joy[0].stick[0].axis[0].d1; joy[0].stick[0].axis[1].pos = 128*joy[0].stick[0].axis[1].d2 - 128*joy[0].stick[0].axis[1].d1; return 0; } /* ww_exit: * Shuts down the driver. */ static void ww_exit(void) { if (wingman) { _AL_FREE(wingman); wingman = NULL; } } allegro-4.4.3.1/src/dos/dsystem.c0000664000175000017500000003225113437077643015513 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main system driver for the DOS library. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #ifndef SCAN_DEPEND #include #include #include #include #include #include #include #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintdos.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #ifndef SCAN_DEPEND #ifdef ALLEGRO_DJGPP /* these headers only apply to djgpp */ #include #include #include #endif #ifdef ALLEGRO_WATCOM /* horrible hackery here, so the rest of the file will work unchanged */ #include #define _write write #define _get_dos_version(n) ((_osmajor << 8) | _osminor) #define ScreenRows() -1 #define _set_screen_lines(n) #endif #endif /* some DOS-specific globals */ int i_love_bill = FALSE; static int a_rez = 3; static int a_lines = -1; static int console_virgin = TRUE; /* previous signal handlers */ static void *old_sig_abrt = NULL; static void *old_sig_fpe = NULL; static void *old_sig_ill = NULL; static void *old_sig_segv = NULL; static void *old_sig_term = NULL; static void *old_sig_int = NULL; #ifdef SIGKILL static void *old_sig_kill = NULL; #endif #ifdef SIGQUIT static void *old_sig_quit = NULL; #endif #ifdef SIGTRAP static void *old_sig_trap = NULL; #endif /* system driver functions */ static int sys_dos_init(void); static void sys_dos_exit(void); static void sys_dos_get_executable_name(char *output, int size); static void sys_dos_save_console_state(void); static void sys_dos_restore_console_state(void); static void sys_dos_read_palette(void); static void sys_dos_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); static void sys_dos_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); static void sys_dos_yield_timeslice(void); #ifdef ALLEGRO_DJGPP static void sys_dos_assert(AL_CONST char *msg); #else #define sys_dos_assert NULL #endif /* the main system driver for running under dos */ SYSTEM_DRIVER system_dos = { SYSTEM_DOS, /* id */ empty_string, /* name */ empty_string, /* desc */ "DOS", /* ascii_name */ sys_dos_init, sys_dos_exit, sys_dos_get_executable_name, NULL, /* find_resource */ NULL, /* set_window_title */ NULL, /* set_close_button_callback */ NULL, /* message */ sys_dos_assert, sys_dos_save_console_state, sys_dos_restore_console_state, NULL, /* create_bitmap */ NULL, /* created_bitmap */ NULL, /* create_sub_bitmap */ NULL, /* created_sub_bitmap */ NULL, /* destroy_bitmap */ sys_dos_read_palette, sys_dos_set_palette, NULL, /* get_vtable */ NULL, /* set_display_switch_mode */ NULL, /* display_switch_lock */ NULL, /* desktop_color_depth */ NULL, /* get_desktop_resolution */ sys_dos_get_gfx_safe_mode, sys_dos_yield_timeslice, NULL, /* create_mutex */ NULL, /* destroy_mutex */ NULL, /* lock_mutex */ NULL, /* unlock_mutex */ NULL, /* gfx_drivers */ NULL, /* digi_drivers */ NULL, /* midi_drivers */ NULL, /* keyboard_drivers */ NULL, /* mouse_drivers */ NULL, /* joystick_drivers */ NULL /* timer_drivers */ }; /* list of available system drivers */ _DRIVER_INFO _system_driver_list[] = { { SYSTEM_DOS, &system_dos, TRUE }, { SYSTEM_NONE, &system_none, FALSE }, { 0, NULL, 0 } }; /* signal_handler: * Used to trap various signals, to make sure things get shut down cleanly. */ static void signal_handler(int num) { static char msg[] = "Shutting down Allegro\r\n"; allegro_exit(); _write(STDERR_FILENO, msg, sizeof(msg)-1); raise(num); } /* detect_os: * Operating system autodetection routine. */ static void detect_os(void) { __dpmi_regs r; char buf[16]; char *p; int i; os_type = OSTYPE_UNKNOWN; /* check for Windows 3.x or 9x */ r.x.ax = 0x1600; __dpmi_int(0x2F, &r); if ((r.h.al != 0) && (r.h.al != 1) && (r.h.al != 0x80) && (r.h.al != 0xFF)) { os_version = r.h.al; os_revision = r.h.ah; os_multitasking = TRUE; if (os_version == 4) { if (os_revision == 90) os_type = OSTYPE_WINME; else if (os_revision == 10) os_type = OSTYPE_WIN98; else os_type = OSTYPE_WIN95; } else os_type = OSTYPE_WIN3; i_love_bill = TRUE; return; } /* check for Windows NT */ p = getenv("OS"); if (((p) && (stricmp(p, "Windows_NT") == 0)) || (_get_dos_version(1) == 0x0532)) { os_type = OSTYPE_WINNT; os_multitasking = TRUE; i_love_bill = TRUE; return; } /* check for OS/2 */ r.x.ax = 0x4010; __dpmi_int(0x2F, &r); if (r.x.ax != 0x4010) { if (r.x.ax == 0) os_type = OSTYPE_WARP; else os_type = OSTYPE_OS2; os_multitasking = TRUE; i_love_bill = TRUE; return; } /* check for Linux DOSEMU */ _farsetsel(_dos_ds); for (i=0; i<8; i++) buf[i] = _farnspeekb(0xFFFF5+i); buf[8] = 0; if (!strcmp(buf, "02/25/93")) { r.x.ax = 0; __dpmi_int(0xE6, &r); if (r.x.ax == 0xAA55) { os_type = OSTYPE_DOSEMU; os_multitasking = TRUE; i_love_bill = TRUE; /* (evil chortle) */ return; } } /* check if running under OpenDOS */ r.x.ax = 0x4452; __dpmi_int(0x21, &r); if ((r.x.ax >= 0x1072) && !(r.x.flags & 1)) { os_type = OSTYPE_OPENDOS; /* now check for OpenDOS EMM386.EXE */ r.x.ax = 0x12FF; r.x.bx = 0x0106; __dpmi_int(0x2F, &r); if ((r.x.ax == 0) && (r.x.bx == 0xEDC0)) { i_love_bill = TRUE; } return; } /* check for that stupid win95 "stealth mode" setting */ r.x.ax = 0x8102; r.x.bx = 0; r.x.dx = 0; __dpmi_int(0x4B, &r); if ((r.x.bx == 3) && !(r.x.flags & 1)) { os_type = OSTYPE_WIN95; os_multitasking = TRUE; i_love_bill = TRUE; return; } /* fetch DOS version if pure DOS is likely to be the running OS */ if (os_type == OSTYPE_UNKNOWN) { r.x.ax = 0x3000; __dpmi_int(0x21, &r); os_version = r.h.al; os_revision = r.h.ah; } } /* sys_dos_init: * Top level system driver wakeup call. */ static int sys_dos_init(void) { #ifdef ALLEGRO_DJGPP /* make sure djgpp won't move our memory around */ _crt0_startup_flags &= ~_CRT0_FLAG_UNIX_SBRK; _crt0_startup_flags |= _CRT0_FLAG_NONMOVE_SBRK; #endif /* initialise the irq wrapper functions */ _dos_irq_init(); /* check which OS we are running under */ detect_os(); /* detect CRTC register address */ _vga_regs_init(); /* install emergency-exit signal handlers */ old_sig_abrt = signal(SIGABRT, signal_handler); old_sig_fpe = signal(SIGFPE, signal_handler); old_sig_ill = signal(SIGILL, signal_handler); old_sig_segv = signal(SIGSEGV, signal_handler); old_sig_term = signal(SIGTERM, signal_handler); old_sig_int = signal(SIGINT, signal_handler); #ifdef SIGKILL old_sig_kill = signal(SIGKILL, signal_handler); #endif #ifdef SIGQUIT old_sig_quit = signal(SIGQUIT, signal_handler); #endif #ifdef SIGTRAP old_sig_trap = signal(SIGTRAP, signal_handler); #endif return 0; } /* sys_dos_exit: * The end of the world... */ static void sys_dos_exit(void) { _dos_irq_exit(); signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); #ifdef SIGKILL signal(SIGKILL, old_sig_kill); #endif #ifdef SIGQUIT signal(SIGQUIT, old_sig_quit); #endif #ifdef SIGTRAP signal(SIGTRAP, old_sig_trap); #endif } /* sys_dos_get_executable_name: * Return full path to the current executable. */ static void sys_dos_get_executable_name(char *output, int size) { #ifdef ALLEGRO_DJGPP /* djgpp stores the program name in the __crt0_argv[] global */ do_uconvert(__crt0_argv[0], U_ASCII, output, U_CURRENT, size); #elif defined ALLEGRO_WATCOM /* Watcom has a _cmdname() function to fetch the program name */ char buf[1024]; do_uconvert(_cmdname(buf), U_ASCII, output, U_CURRENT, size); #else #error unknown platform #endif } #ifdef ALLEGRO_DJGPP /* sys_dos_assert: * Handles an assert failure, generating a stack traceback. This routine * is heavily based on dpmiexcp.c from the djgpp libc sources, by Charles * Sandmann. It is reimplemented here because we don't want the register * dump, just the stack traceback, and so we can strip off the top couple * of stack entries (users don't need to see inside the Allegro assert * mechanism). And because it is cool. */ static void sys_dos_assert(AL_CONST char *msg) { extern unsigned int end __asm__ ("end"); extern unsigned int _stklen; unsigned int *vbp, *vbp_new, *tos, veip; int max, c; jmp_buf j; setjmp(j); allegro_exit(); fprintf(stderr, "%s\n\n", msg); fprintf(stderr, "Call frame traceback EIPs:\n"); tos = (unsigned int *)__djgpp_selector_limit; vbp = (unsigned int *)j->__ebp; if (isatty(fileno(stderr))) { max = _farpeekb(_dos_ds, 0x484) + 1; if ((max < 10) || (max > 75)) max = 19; else max -= 6; } else max = _stklen/8; c = 0; while (((unsigned int)vbp >= j->__esp) && (vbp >= &end) && (vbp < tos)) { vbp_new = (unsigned int *)vbp[0]; if (!vbp_new) break; veip = vbp[1]; if (c++) fprintf(stderr, " 0x%08x\n", veip); vbp = vbp_new; if (--max <= 0) break; } exit(1); } #endif /* sys_dos_save_console_state: * Called just before switching into a graphics mode, to remember what * the text console was like. */ static void sys_dos_save_console_state(void) { __dpmi_regs r; int c; if (!console_virgin) return; for (c=0; c<256; c++) { /* store current color palette */ outportb(0x3C7, c); _current_palette[c].r = inportb(0x3C9); _current_palette[c].g = inportb(0x3C9); _current_palette[c].b = inportb(0x3C9); } r.x.ax = 0x0F00; /* store current video mode */ __dpmi_int(0x10, &r); a_rez = r.x.ax & 0xFF; if (a_rez > 19) /* ignore non-standard modes */ a_rez = 3; if (a_rez == 3) /* store current screen height */ a_lines = ScreenRows(); else a_lines = -1; console_virgin = FALSE; } /* sys_dos_restore_console_state: * Puts us back into the original text mode. */ static void sys_dos_restore_console_state(void) { __dpmi_regs r; r.x.ax = 0x0F00; __dpmi_int(0x10, &r); if ((r.x.ax & 0xFF) != a_rez) { r.x.ax = a_rez; __dpmi_int(0x10, &r); } if (a_rez == 3) { if (ScreenRows() != a_lines) _set_screen_lines(a_lines); } } /* sys_dos_read_palette: * Reads the current palette from the video hardware. */ static void sys_dos_read_palette(void) { if (console_virgin) sys_dos_save_console_state(); } /* sys_dos_set_palette: * Writes a palette to the video hardware. */ static void sys_dos_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { if (console_virgin) sys_dos_save_console_state(); _vga_set_palette_range(p, from, to, vsync); } /* sys_dos_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void sys_dos_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_VGA; mode->width = 320; mode->height = 200; mode->bpp = 8; } /* _set_vga_mode: * Helper for the VGA and mode-X drivers to set a video mode. */ uintptr_t _set_vga_mode(int modenum) { __dpmi_regs r; if (modenum >= 0x100) { /* set VESA mode */ r.x.ax = 0x4F02; r.x.bx = modenum; __dpmi_int(0x10, &r); if (r.h.ah) return 0; } else { /* set VGA mode */ r.x.ax = modenum; __dpmi_int(0x10, &r); } return 0xA0000; } /* _unset_vga_mode: * Helper for the VGA and mode-X drivers to unset a video mode. */ void _unset_vga_mode(void) { /* nothing to be done in DOS */ } /* _save_vga_mode: * Helper for VGA and mode-X drivers to save state. */ void _save_vga_mode(void) { /* nothing to be done in DOS */ } /* _restore_vga_mode: * Helper to restore previously saved mode. */ void _restore_vga_mode(void) { /* nothing to be done in DOS */ } /* sys_dos_yield_timeslice: * Yields the remaining timeslice portion to the system */ static void sys_dos_yield_timeslice(void) { #ifdef ALLEGRO_DJGPP __dpmi_yield(); #endif } allegro-4.4.3.1/src/dos/grip.c0000664000175000017500000001700113437077643014760 0ustar siegesiege/************************************************************************\ ** ** ** GrIP Prototype API Interface Library ** ** for ** ** DJGPP ** ** ** ** Revision 1.00 ** ** ** ** COPYRIGHT: ** ** ** ** (C) Copyright Advanced Gravis Computer Technology Ltd 1995. ** ** All Rights Reserved. ** ** ** ** DISCLAIMER OF WARRANTIES: ** ** ** ** The following [enclosed] code is provided to you "AS IS", ** ** without warranty of any kind. You have a royalty-free right to ** ** use, modify, reproduce and distribute the following code (and/or ** ** any modified version) provided that you agree that Advanced ** ** Gravis has no warranty obligations and shall not be liable for ** ** any damages arising out of your use of this code, even if they ** ** have been advised of the possibility of such damages. This ** ** Copyright statement and Disclaimer of Warranties may not be ** ** removed. ** ** ** ** HISTORY: ** ** ** ** 0.102 Jul 12 95 David Bollo Initial public release on ** ** GrIP hardware ** ** 0.200 Aug 10 95 David Bollo Added Gravis Loadable Library ** ** support ** ** 0.201 Aug 11 95 David Bollo Removed Borland C++ support ** ** for maintenance reasons ** ** 1.00 Nov 1 95 David Bollo First official release as ** ** part of GrIP SDK ** ** ** \************************************************************************/ #include #include "allegro.h" #include "grip.h" /* Global Thunking Data */ GRIP_THUNK GRIP_Thunk; static int GRIP_Thunked = 0; static int GRIP_CS; static int GRIP_DS; #if defined(GRIP_DEBUG) static short GRIP_ES; #endif #ifndef ALLEGRO_DJGPP #define _farpokew(ds, addr, value) *(short *)(addr) = (value) #endif #define DPMI_AllocDOS(a, b) (__dpmi_allocate_dos_memory(a, b) << 4) #define DPMI_FreeDOS(a) __dpmi_free_dos_memory(a) #define DPMI_AllocSel() __dpmi_allocate_ldt_descriptors(1) #define DPMI_FreeSel(a) __dpmi_free_ldt_descriptor(a) unsigned char _DPMI_SetCodeAR(unsigned short sel); unsigned char _DPMI_SetDataAR(unsigned short sel); static unsigned char DPMI_SetBounds(unsigned short sel, unsigned long base, unsigned short lm) { if (__dpmi_set_segment_base_address(sel, base) == -1) return -1; if (__dpmi_set_segment_limit(sel, lm - 1) == -1) return -1; return 0; } GRIP_BOOL _GrLink(GRIP_BUF image, GRIP_VALUE size) { unsigned short img_off; /* Offset of binary image */ unsigned short img_size; /* Size of binary image */ unsigned char img_check; /* Checksum of binary image */ unsigned long memory; /* Image memory */ GRIP_BUF_C header; /* Image header */ GRIP_BUF_C core; /* Image core */ int i; /* Check for duplicate GrLink calls */ if (GRIP_Thunked) return 0; /* Sanity check the inputs */ if (image == 0 || size < 16) return 0; /* Check the image header for the proper signature bytes */ header = (GRIP_BUF_C) image; if (header[0] != 'D' || header[1] != 'B') return 0; /* Extract the image offsets from the header */ img_off = ((header[2] & 0x0F) << 12) | ((header[3] & 0x0F) << 8) | ((header[4] & 0x0F) << 4) | ((header[5] & 0x0F)); img_size = ((header[6] & 0x0F) << 12) | ((header[7] & 0x0F) << 8) | ((header[8] & 0x0F) << 4) | ((header[9] & 0x0F)); img_check = ((header[10] & 0x0F) << 4) | ((header[11] & 0x0F)); /* Compute the start of image core */ if (size < ((img_off + img_size) << 4)) return 0; core = header + (img_off << 4); /* Verify the checksum */ for (i = 0; i < (img_size << 4); i++) img_check ^= core[i]; if (img_check != 0) return 0; /* Allocate memory for the core */ memory = (unsigned long)DPMI_AllocDOS(img_size, &GRIP_DS); if (!memory) return 0; /* Copy the image */ dosmemput(core, img_size << 4, memory); /* Allocate a code selector for the core */ GRIP_CS = DPMI_AllocSel(); if (GRIP_CS == 0) { DPMI_FreeDOS(GRIP_DS); return 0; } if (DPMI_SetBounds(GRIP_CS, memory, img_size << 4) != 0) { DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } if (_DPMI_SetCodeAR(GRIP_CS) != 0) { DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } /* Prepare the thunking layer */ for (i = 0; i < (int)sizeof(GRIP_THUNK); i++) GRIP_Thunk[i] = ((GRIP_BUF_C) core)[i]; *(GRIP_BUF_S) (GRIP_Thunk + 0x02) = 0; *(GRIP_BUF_S) (GRIP_Thunk + 0x06) = GRIP_CS; *(GRIP_BUF_S) (GRIP_Thunk + 0x0C) = GRIP_CS; /* Allocate a debugging selector if GRIP_DEBUG is defined */ #if defined(GRIP_DEBUG) /* I don't know what this does... at least it compiles okay */ GRIP_ES = DPMI_AllocSel(); if (GRIP_ES == 0) { DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } if (DPMI_SetBounds(GRIP_ES, 0xB0000, 80 * 25 * 2) != 0) { DPMI_FreeSel(GRIP_ES); DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } if (DPMI_SetDataAR(GRIP_ES) != 0) { DPMI_FreeSel(GRIP_ES); DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } _farpokew(_dos_ds, memory + 0x12, 0xB000); _farpokew(_dos_ds, memory + 0x16, GRIP_ES); #else _farpokew(_dos_ds, memory + 0x12, 0); _farpokew(_dos_ds, memory + 0x16, 0); #endif /* Save the data selector */ _farpokew(_dos_ds, memory + 0x10, 0); _farpokew(_dos_ds, memory + 0x14, GRIP_DS); /* Complete the link */ if (_Gr__Link() == 0) { #if defined(GRIP_DEBUG) DPMI_FreeSel(GRIP_ES); #endif DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } GRIP_Thunked = 1; return 1; } GRIP_BOOL _GrUnlink(void) { /* Check that the library has been loaded */ if (!GRIP_Thunked) return 0; /* Unlink the library */ _Gr__Unlink(); /* Free the library memory */ #if defined(GRIP_DEBUG) if (DPMI_FreeSel(GRIP_ES) != 0) return 0; #endif if (DPMI_FreeSel(GRIP_CS) != 0) return 0; if (DPMI_FreeDOS(GRIP_DS) != 0) return 0; GRIP_Thunked = 0; return 1; } allegro-4.4.3.1/src/dos/psxpad.c0000664000175000017500000010013213437077643015314 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for PSX controllers. * * By Richard Davies. * * Based on sample code by Earle F. Philhower, III. from DirectPad * Pro 4.9, for use with the DirectPad Pro parallel port interface. * * See for interface details. * * Original parallel port interface and code by Juan Berrocal. * * Digital, Analog, Dual Force (control), NegCon and Mouse * information by T. Fujita. Dual Shock (vibrate) information by * Dark Fader. Multi tap, G-con45 and Jogcon information by me * (the weird stuff ;) * * This driver recognises Digital, Analog, Dual Shock, Mouse, negCon, * G-con45, Jogcon, Konami Lightgun and Multi tap devices. * * Digital, Dual Shock, neGcon, G-con45, Jogcon and Multi tap devices * have all been tested. The Analog (green mode or joystick), Mouse * and Konami Lightgun devices have not. The position data is likely * to be broken for the Konami Lightgun, and may also be broken for * the Mouse. * * The G-con45 needs to be connected to (and pointed at) a TV type * monitor connected to your computer. The composite video out on my * video card works fine for this. * * The Sony Dual Shock or Namco Jogcon will reset themselves (to * digital mode) after not being polled for 5 seconds. This is normal, * the same thing happens on a Playstation, it's meant to stop any * vibration in case the host machine crashes. However, if this * happens to a Jogcon controller the mode button is disabled. To * reenable the mode button on the Jogcon hold down the Start and * Select buttons at the same time. Other mode switching controllers * may have similar quirks. * * Some people may have problems with the psx poll delay set at 3 * causing them twitchy controls (this depends on the controllers * more than anything else). * * It may be worthwhile to add calibration to some of the analog * controls, although most controller types aren't really meant to * be calibrated: * * - My Dual Shock controller centres really badly; most of them do. * - My neGcon centres really well (+/- 1). * - The G-con45 needs calibration for it's centre aim and velocity. * - The Jogcon calibrates itself when initialised. * * To Do List: * * - Verify Analog Joystick (Green mode) works. * - Verify Mouse position works. * - Verify MegaTap interface. * - Add calibration for the G-con45, Dual Shock and neGcon controllers. * - Implement Konami Lightgun aim. * - Implement Jogcon force feedback. * - Implement unsupported controllers (Ascii Sphere? Beat Mania Decks?) * * If you can help with any of these then please let me know. * * * ----------------------- * | o o o | o o o | o o o | Controller Port (looking into plug) * \_____________________/ * 1 2 3 4 5 6 7 8 9 * * Controller Parallel * * 1 - data 10 (conport 1, 3, 4, 5, 6), 13 (conport 2) * 2 - command 2 * 3 - 9V(shock) +9V power supply terminal for Dual Shock * 4 - gnd 18,19 also -9V and/or -5V power supply terminal * 5 - V+ 5, 6, 7, 8, 9 through diodes, or +5V power supply terminal * 6 - att 3 (conport 1, 2), 5 (conport 3), 6 (conport 4), 7 (conport 5), 8 (conport 6) * 7 - clock 4 * 9 - ack 12 (conport 1, 3, 4, 5, 6), 14 (conport 2) ** * * ** There is an error in the DirectPad Pro documentation, which states that * the second control port should have pin 9 connected to pin 15 on the * parallel port. This should actually be pin 14 on the parallel port. To * make things more confusing, this error is unlikely to prevent the * interface from working properly. It's also possible that a change to the * scanning code has been made in version 5.0 to prevent people from having * to rewire their interfaces. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_DOS #error something is wrong with the makefile #endif #define LPT1_BASE 0x378 #define LPT2_BASE 0x278 #define LPT3_BASE 0x3bc #define LPT_D0 0x01 #define LPT_D1 0x02 #define LPT_D2 0x04 #define LPT_D3 0x08 #define LPT_D4 0x10 #define LPT_D5 0x20 #define LPT_D6 0x40 #define LPT_D7 0x80 #define LPT_AUT 0x08 #define LPT_SEL 0x10 #define LPT_PAP 0x20 #define LPT_ACK 0x40 #define PSX_MAX_DATA 33 /* maximum possible length of controller packet in bytes */ #define PSX_MAX_DETECT 8 /* maximum number of controllers to install */ #define PSX_DELAY 3 /* JAP code EUR code Name */ #define PSX_MOUSE 1 /* SCPH-1030 SCPH-???? Mouse */ #define PSX_NEGCON 2 /* SLPH-0001 SLEH-0003 Namco neGcon SLPH-0007 Nasca Pachinco Handle (!) SLPH-0015 ? Volume Controller (!) SLPH-???? SLEH-0006(?)MadKatz Steering Wheel */ #define PSX_KONAMIGUN 3 /* SLPH-???? SLPH-???? Konami Lightgun */ #define PSX_DIGITAL 4 /* SCPH-1010 SCPH 1080 E Controller SCPH-1110 SCPH-???? Analog Joystick - Digital Mode SCPH-1150 SCPH-1200 E Dual Shock Analog Controller - Digital Mode SLPH-???? SLEH-0011 Ascii Resident Evil Pad SLPH-???? SLEH-0004 Namco Arcade Stick */ #define PSX_ANALOG_GREEN 5 /* SCPH-1110 SCPH-???? Analog Joystick - Analog Mode SCPH-1150 SCPH-1200 E Dual Shock Analog Controller - Analog Green Mode */ #define PSX_GUNCON 6 /* SLPH-???? SLEH-0007 Namco G-con45 */ #define PSX_ANALOG_RED 7 /* SCPH-1150 SCPH-1200 E Dual Shock Analog Controller - Analog Red Mode */ #define PSX_JOGCON 14 /* SLPH-???? SLEH-0020 Namco Jogcon */ /* PSX_MULTITAP SCPH-1070 SCPH-1070 E Multi tap */ /* driver functions */ static int psx1_init(void); static int psx2_init(void); static int psx3_init(void); static void psx_exit(int base); static void psx1_exit(void); static void psx2_exit(void); static void psx3_exit(void); static int psx1_poll(void); static int psx2_poll(void); static int psx3_poll(void); static int psx_detect(int base, int conport, int tap); JOYSTICK_DRIVER joystick_psx1 = { JOY_TYPE_PSXPAD_LPT1, NULL, NULL, "PSXpad-LPT1", psx1_init, psx1_exit, psx1_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_psx2 = { JOY_TYPE_PSXPAD_LPT2, NULL, NULL, "PSXpad-LPT2", psx2_init, psx2_exit, psx2_poll, NULL, NULL, NULL, NULL }; JOYSTICK_DRIVER joystick_psx3 = { JOY_TYPE_PSXPAD_LPT3, NULL, NULL, "PSXpad-LPT3", psx3_init, psx3_exit, psx3_poll, NULL, NULL, NULL, NULL }; static unsigned char psx_parallel_out = 0xff; static int psx_first_poll = 1; typedef struct { int conport; int tap; int type; } PSX_INFO; static PSX_INFO psx_detected[PSX_MAX_DETECT]; /* psx_init: * Initialise joy[] for Allegro depending on what's detected. */ static int psx_init(int base) { int i, j, type; num_joysticks = 0; /* test for the presence of controllers on port base */ for (i=0; i<6; i++) { for (j=1; j<5; j++) { type = psx_detect(base, i, j); if (type != -1) { psx_detected[num_joysticks].conport = i; psx_detected[num_joysticks].tap = j; psx_detected[num_joysticks].type = type; num_joysticks++; } if (num_joysticks == PSX_MAX_DETECT) i = 6; } } if (!num_joysticks) return -1; for (i=0; i> 4; packet_length = 3 + (2 * (data[1] & 0x0f)); /* if the packet is of a legal length */ if (packet_length < PSX_MAX_DATA) /* return the controller type */ return psx_type; else return -1; } /* * retrieves controller data for conport:tap connected to base */ static void psx_poll(int base, int conport, int tap, int type, int joynum) { unsigned char data[PSX_MAX_DATA]; int i, psx_type, packet_length; psx_sendinit(base, conport); data[0] = psx_sendbyte(base, conport, tap, 1); data[1] = psx_sendbyte(base, conport, 0x42, 1); psx_type = (data[1] & 0xf0) >> 4; packet_length = 3 + (2 * (data[1] & 0x0f)); /* if the packet is of a legal length */ if (packet_length < PSX_MAX_DATA) { /* read the remaining packet */ for (i=2; i 64; /* I */ joy[joynum].stick[2].axis[0].pos = data[6]; joy[joynum].stick[2].axis[0].d1 = data[6] > 0x7f; /* II */ joy[joynum].stick[2].axis[1].pos = data[7]; joy[joynum].stick[2].axis[1].d1 = data[7] > 0x7f; /* L1 */ joy[joynum].stick[2].axis[2].pos = data[7]; joy[joynum].stick[2].axis[2].d1 = data[8] > 0xdf; break; case PSX_MOUSE: /* right button */ joy[joynum].button[0].b = data[4] & 0x04 ? 0 : 1; /* left button */ joy[joynum].button[1].b = data[4] & 0x08 ? 0 : 1; /* position x axis */ joy[joynum].stick[0].axis[0].pos -= (signed char)data[6]; /* position y axis */ joy[joynum].stick[0].axis[1].pos -= (signed char)data[5]; /* setup digital controls for position */ joy[joynum].stick[0].axis[0].d1 = joy[joynum].stick[1].axis[0].pos < -64; joy[joynum].stick[0].axis[0].d2 = joy[joynum].stick[1].axis[0].pos > 64; joy[joynum].stick[0].axis[1].d1 = joy[joynum].stick[1].axis[1].pos < -64; joy[joynum].stick[0].axis[1].d2 = joy[joynum].stick[1].axis[1].pos > 64; /* set position boundaries */ if (joy[joynum].stick[0].axis[0].pos > 128) joy[joynum].stick[0].axis[0].pos = 128; else if (joy[joynum].stick[0].axis[0].pos < -128) joy[joynum].stick[0].axis[0].pos = -128; if (joy[joynum].stick[0].axis[1].pos > 128) joy[joynum].stick[0].axis[1].pos = 128; else if (joy[joynum].stick[0].axis[1].pos < -128) joy[joynum].stick[0].axis[1].pos = -128; break; case PSX_GUNCON: /* trigger */ joy[joynum].button[0].b = data[4] & 0x20 ? 0 : 1; /* A */ joy[joynum].button[1].b = data[3] & 0x08 ? 0 : 1; /* B */ joy[joynum].button[2].b = data[4] & 0x40 ? 0 : 1; /* aim */ /* bad data */ if (!(data[5] == 0x01)) { /* too light and too dark */ /*if (!(data[7] == 0x05) && !(data[7] == 0x0a)) */ { /* aim X */ joy[joynum].stick[0].axis[0].pos = (((data[6] & 0x01) << 8) + data[5]) - 256; /* aim y */ joy[joynum].stick[0].axis[1].pos = data[7] - 128; } } /* setup digital controls for aim */ joy[joynum].stick[0].axis[0].d1 = joy[joynum].stick[0].axis[0].pos < -64; joy[joynum].stick[0].axis[0].d2 = joy[joynum].stick[0].axis[0].pos > 64; joy[joynum].stick[0].axis[1].d1 = joy[joynum].stick[0].axis[1].pos < -64; joy[joynum].stick[0].axis[1].d2 = joy[joynum].stick[0].axis[1].pos > 64; break; case PSX_KONAMIGUN: /* trigger */ joy[joynum].button[0].b = data[4] & 0x80 ? 0 : 1; /* back */ joy[joynum].button[1].b = data[4] & 0x40 ? 0 : 1; /* start */ joy[joynum].button[2].b = data[3] & 0x08 ? 0 : 1; /* aim X axis - probably wrong */ joy[joynum].stick[0].axis[0].pos = data[5] - 128; /* aim Y axis - probably wrong */ joy[joynum].stick[0].axis[1].pos = data[6] - 128; /* setup digital controls for aim */ joy[joynum].stick[0].axis[0].d1 = joy[joynum].stick[0].axis[0].pos < -64; joy[joynum].stick[0].axis[0].d2 = joy[joynum].stick[0].axis[0].pos > 64; joy[joynum].stick[0].axis[1].d1 = joy[joynum].stick[0].axis[1].pos < -64; joy[joynum].stick[0].axis[1].d2 = joy[joynum].stick[0].axis[1].pos > 64; break; case PSX_DIGITAL: case PSX_ANALOG_GREEN: case PSX_ANALOG_RED: case PSX_JOGCON: default: /* direction pad left */ joy[joynum].stick[2].axis[0].d1 = data[3] & 0x80 ? 0 : 1; /* direction pad down */ joy[joynum].stick[2].axis[1].d2 = data[3] & 0x40 ? 0 : 1; /* direction pad right */ joy[joynum].stick[2].axis[0].d2 = data[3] & 0x20 ? 0 : 1; /* direction pad up */ joy[joynum].stick[2].axis[1].d1 = data[3] & 0x10 ? 0 : 1; /* setup analog controls for direction pad */ for (i=0; i<2; i++) { if (joy[joynum].stick[2].axis[i].d1) joy[joynum].stick[2].axis[i].pos = -128; else if (joy[joynum].stick[2].axis[i].d2) joy[joynum].stick[2].axis[i].pos = 128; else joy[joynum].stick[2].axis[i].pos = 0; } switch (psx_type) { case PSX_DIGITAL: /* mirror direction pad for unused axes */ joy[joynum].stick[0].axis[0].pos = joy[joynum].stick[1].axis[0].pos = joy[joynum].stick[3].axis[0].pos = joy[joynum].stick[2].axis[0].pos; joy[joynum].stick[0].axis[1].pos = joy[joynum].stick[1].axis[1].pos = joy[joynum].stick[2].axis[1].pos; joy[joynum].stick[0].axis[0].d1 = joy[joynum].stick[1].axis[0].d1 = joy[joynum].stick[3].axis[0].d1 = joy[joynum].stick[2].axis[0].d1; joy[joynum].stick[0].axis[0].d2 = joy[joynum].stick[1].axis[0].d2 = joy[joynum].stick[3].axis[0].d2 = joy[joynum].stick[2].axis[0].d2; joy[joynum].stick[0].axis[1].d1 = joy[joynum].stick[1].axis[1].d1 = joy[joynum].stick[2].axis[1].d1; joy[joynum].stick[0].axis[1].d2 = joy[joynum].stick[1].axis[1].d2 = joy[joynum].stick[2].axis[1].d2; break; case PSX_JOGCON: /* dial */ joy[joynum].stick[3].axis[0].pos = ((data[6] << 7) + (data[5] >> 1)) - (data[6] & 0x80 ? 32768 : 0); /* setup digital controls for dial */ joy[joynum].stick[3].axis[0].d1 = data[7] & 0x02; joy[joynum].stick[3].axis[0].d2 = data[7] & 0x01; /* mirror direction pad for unused axes */ joy[joynum].stick[0].axis[0].pos = joy[joynum].stick[1].axis[0].pos = joy[joynum].stick[2].axis[0].pos; joy[joynum].stick[0].axis[1].pos = joy[joynum].stick[1].axis[1].pos = joy[joynum].stick[2].axis[1].pos; joy[joynum].stick[0].axis[0].d1 = joy[joynum].stick[1].axis[0].d1 = joy[joynum].stick[2].axis[0].d1; joy[joynum].stick[0].axis[0].d2 = joy[joynum].stick[1].axis[0].d2 = joy[joynum].stick[2].axis[0].d2; joy[joynum].stick[0].axis[1].d1 = joy[joynum].stick[1].axis[1].d1 = joy[joynum].stick[2].axis[1].d1; joy[joynum].stick[0].axis[1].d2 = joy[joynum].stick[1].axis[1].d2 = joy[joynum].stick[2].axis[1].d2; break; /* analog or unknown controller */ default: /* left stick X axis */ joy[joynum].stick[0].axis[0].pos = data[7] - 128; /* left stick Y axis */ joy[joynum].stick[0].axis[1].pos = data[8] - 128; /* right stick X axis */ joy[joynum].stick[1].axis[0].pos = data[5] - 128; /* right stick Y axis */ joy[joynum].stick[1].axis[1].pos = data[6] - 128; /* setup digital controls for left and right stick */ joy[joynum].stick[0].axis[0].d1 = joy[joynum].stick[0].axis[0].pos < -64; joy[joynum].stick[0].axis[0].d2 = joy[joynum].stick[0].axis[0].pos > 64; joy[joynum].stick[0].axis[1].d1 = joy[joynum].stick[0].axis[1].pos < -64; joy[joynum].stick[0].axis[1].d2 = joy[joynum].stick[0].axis[1].pos > 64; joy[joynum].stick[1].axis[0].d1 = joy[joynum].stick[1].axis[0].pos < -64; joy[joynum].stick[1].axis[0].d2 = joy[joynum].stick[1].axis[0].pos > 64; joy[joynum].stick[1].axis[1].d1 = joy[joynum].stick[1].axis[1].pos < -64; joy[joynum].stick[1].axis[1].d2 = joy[joynum].stick[1].axis[1].pos > 64; /* mirror direction pad for unused axes */ joy[joynum].stick[3].axis[0].pos = joy[joynum].stick[2].axis[0].pos; joy[joynum].stick[3].axis[0].d1 = joy[joynum].stick[2].axis[0].d1; joy[joynum].stick[3].axis[0].d2 = joy[joynum].stick[2].axis[0].d2; break; } /* cross */ joy[joynum].button[0].b = data[4] & 0x40 ? 0 : 1; /* circle */ joy[joynum].button[1].b = data[4] & 0x20 ? 0 : 1; /* square */ joy[joynum].button[2].b = data[4] & 0x80 ? 0 : 1; /* triangle */ joy[joynum].button[3].b = data[4] & 0x10 ? 0 : 1; /* L1 */ joy[joynum].button[4].b = data[4] & 0x04 ? 0 : 1; /* R1 */ joy[joynum].button[5].b = data[4] & 0x08 ? 0 : 1; /* L2 */ joy[joynum].button[6].b = data[4] & 0x01 ? 0 : 1; /* R2 */ joy[joynum].button[7].b = data[4] & 0x02 ? 0 : 1; /* select */ joy[joynum].button[8].b = data[3] & 0x01 ? 0 : 1; /* start */ joy[joynum].button[9].b = data[3] & 0x08 ? 0 : 1; /* L3 */ joy[joynum].button[10].b = data[3] & 0x02 ? 0 : 1; /* R3 */ joy[joynum].button[11].b = data[3] & 0x04 ? 0 : 1; /* fix to allow analog mode switching for Jogcon after 5 seconds without polling */ if ((joy[joynum].button[8].b) && (joy[joynum].button[9].b)) psx_vibrate_init(base, conport, tap); break; } } static int psx1_poll(void) { int joynum; /* send Jogcon init to all controllers */ if (psx_first_poll) { for (joynum=0; joynum7) { pic = inportb(0xA1) & (~(1<<(num-8))); outportb(0xA1, pic | (default_pic2 & (1<<(num-8)))); altered_pic2 &= ~(1<<(num-8)); if (altered_pic2) return; num = 2; /* if no high IRQs remain, also restore Cascade (IRQ2) */ } pic = inportb(0x21) & (~(1< 7) { outportb(0x21, pic & 0xFB); /* unmask Cascade (IRQ2) interrupt */ pic = inportb(0xA1); outportb(0xA1, pic & (~(1<<(num-8)))); /* unmask PIC-2 interrupt */ altered_pic2 |= 1<<(num-8); } else { outportb(0x21, pic & (~(1< 7) { pic = inportb(0xA1); outportb(0xA1, pic & (1<<(num-8))); /* mask PIC-2 interrupt */ altered_pic2 |= 1<<(num-8); } else { pic = inportb(0x21); outportb(0x21, pic & (1<w) b->line[y][x] = ch; x++; } } else { while (c--) { if (xx < b->w) b->line[y][xx*3+po] = ch; x++; if (x == bytes_per_line) { xx = 0; #ifdef ALLEGRO_LITTLE_ENDIAN po = _rgb_g_shift_24/8; #elif defined ALLEGRO_BIG_ENDIAN po = 2 - _rgb_g_shift_24/8; #elif !defined SCAN_DEPEND #error endianess not defined #endif } else if (x == bytes_per_line*2) { xx = 0; #ifdef ALLEGRO_LITTLE_ENDIAN po = _rgb_b_shift_24/8; #elif defined ALLEGRO_BIG_ENDIAN po = 2 - _rgb_b_shift_24/8; #elif !defined SCAN_DEPEND #error endianess not defined #endif } else xx++; } } } } if (bpp == 8) { /* look for a 256 color palette */ while ((c = pack_getc(f)) != EOF) { if (c == 12) { for (c=0; c<256; c++) { pal[c].r = pack_getc(f) / 4; pal[c].g = pack_getc(f) / 4; pal[c].b = pack_getc(f) / 4; } break; } } } if (*allegro_errno) { destroy_bitmap(b); return NULL; } if (dest_depth != bpp) { /* restore original palette except if it comes from the bitmap */ if ((bpp != 8) && (!want_palette)) pal = NULL; b = _fixup_loaded_bitmap(b, pal, dest_depth); } /* construct a fake palette if 8-bit mode is not involved */ if ((bpp != 8) && (dest_depth != 8) && want_palette) generate_332_palette(pal); return b; } /* save_pcx: * Writes a bitmap into a PCX file, using the specified palette (this * should be an array of at least 256 RGB structures). */ int save_pcx(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) { PACKFILE *f; int ret; ASSERT(filename); f = pack_fopen(filename, F_WRITE); if (!f) return -1; ret = save_pcx_pf(f, bmp, pal); pack_fclose(f); return ret; } /* save_pcx_pf: * Like save_pcx but writes into the PACKFILE given instead of a new file. * The packfile is not closed after writing is completed. On success the * offset into the file is left after the TGA file just written. On failure * the offset is left at the end of whatever incomplete data was written. */ int save_pcx_pf(PACKFILE *f, BITMAP *bmp, AL_CONST RGB *pal) { PALETTE tmppal; int c; int x, y; int runcount; int depth, planes; char runchar; char ch; ASSERT(f); ASSERT(bmp); if (!pal) { get_palette(tmppal); pal = tmppal; } depth = bitmap_color_depth(bmp); if (depth == 8) planes = 1; else planes = 3; *allegro_errno = 0; pack_putc(10, f); /* manufacturer */ pack_putc(5, f); /* version */ pack_putc(1, f); /* run length encoding */ pack_putc(8, f); /* 8 bits per pixel */ pack_iputw(0, f); /* xmin */ pack_iputw(0, f); /* ymin */ pack_iputw(bmp->w-1, f); /* xmax */ pack_iputw(bmp->h-1, f); /* ymax */ pack_iputw(320, f); /* HDpi */ pack_iputw(200, f); /* VDpi */ for (c=0; c<16; c++) { pack_putc(_rgb_scale_6[pal[c].r], f); pack_putc(_rgb_scale_6[pal[c].g], f); pack_putc(_rgb_scale_6[pal[c].b], f); } pack_putc(0, f); /* reserved */ pack_putc(planes, f); /* one or three color planes */ pack_iputw(bmp->w, f); /* number of bytes per scanline */ pack_iputw(1, f); /* color palette */ pack_iputw(bmp->w, f); /* hscreen size */ pack_iputw(bmp->h, f); /* vscreen size */ for (c=0; c<54; c++) /* filler */ pack_putc(0, f); for (y=0; yh; y++) { /* for each scanline... */ runcount = 0; runchar = 0; for (x=0; xw*planes; x++) { /* for each pixel... */ if (depth == 8) { ch = getpixel(bmp, x, y); } else { if (xw) { c = getpixel(bmp, x, y); ch = getr_depth(depth, c); } else if (xw*2) { c = getpixel(bmp, x-bmp->w, y); ch = getg_depth(depth, c); } else { c = getpixel(bmp, x-bmp->w*2, y); ch = getb_depth(depth, c); } } if (runcount==0) { runcount = 1; runchar = ch; } else { if ((ch != runchar) || (runcount >= 0x3f)) { if ((runcount > 1) || ((runchar & 0xC0) == 0xC0)) pack_putc(0xC0 | runcount, f); pack_putc(runchar,f); runcount = 1; runchar = ch; } else runcount++; } } if ((runcount > 1) || ((runchar & 0xC0) == 0xC0)) pack_putc(0xC0 | runcount, f); pack_putc(runchar,f); } if (depth == 8) { /* 256 color palette */ pack_putc(12, f); for (c=0; c<256; c++) { pack_putc(_rgb_scale_6[pal[c].r], f); pack_putc(_rgb_scale_6[pal[c].g], f); pack_putc(_rgb_scale_6[pal[c].b], f); } } if (*allegro_errno) return -1; else return 0; } allegro-4.4.3.1/src/vtable.c0000664000175000017500000000227613437077643014517 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of available bitmap vtables, kept in a seperate file so that * they can be overriden by user programs. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_COLOR8 #undef COLOR_DEPTH_8 #define COLOR_DEPTH_8 #endif #ifndef ALLEGRO_COLOR16 #undef COLOR_DEPTH_15 #undef COLOR_DEPTH_16 #define COLOR_DEPTH_15 #define COLOR_DEPTH_16 #endif #ifndef ALLEGRO_COLOR24 #undef COLOR_DEPTH_24 #define COLOR_DEPTH_24 #endif #ifndef ALLEGRO_COLOR32 #undef COLOR_DEPTH_32 #define COLOR_DEPTH_32 #endif BEGIN_COLOR_DEPTH_LIST COLOR_DEPTH_8 COLOR_DEPTH_15 COLOR_DEPTH_16 COLOR_DEPTH_24 COLOR_DEPTH_32 END_COLOR_DEPTH_LIST allegro-4.4.3.1/src/fontbios.c0000664000175000017500000000313513437077643015060 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Font loading routine for reading a BIOS font. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* load_bios_font: * Loads a PC BIOS font from the file named filename. The palette and param * parameters are ignored by this function. */ FONT *load_bios_font(AL_CONST char *filename, RGB *pal, void *param) { PACKFILE *pack; FONT *f; FONT_MONO_DATA *mf; FONT_GLYPH **gl; int i, h; f = _AL_MALLOC(sizeof(FONT)); mf = _AL_MALLOC(sizeof(FONT_MONO_DATA)); gl = _AL_MALLOC(sizeof(FONT_GLYPH*) * 256); pack = pack_fopen(filename, F_READ); if (!pack) return 0; h = (pack->normal.todo == 2048) ? 8 : 16; for (i = 0; i < 256; i++) { gl[i] = _AL_MALLOC(sizeof(FONT_GLYPH) + h); gl[i]->w = 8; gl[i]->h = h; pack_fread(gl[i]->dat, h, pack); } f->vtable = font_vtable_mono; f->data = mf; f->height = h; mf->begin = 0; mf->end = 256; mf->glyphs = gl; mf->next = 0; pack_fclose(pack); return f; } allegro-4.4.3.1/src/libc.c0000664000175000017500000000631013437077643014144 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Emulation for libc routines that may be missing on some platforms. * * By Michael Bukin. * * Henrik Stokseth added _al_sane_realloc() and _al_sane_strncpy() functions. * * _al_srand() and _al_rand() functions based on code by Paul Pridham. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include static int _al_rand_seed = 0; #ifdef ALLEGRO_NO_STRLWR /* _alemu_strlwr: * Convert all upper case characters in string to lower case. */ char *_alemu_strlwr(char *string) { char *p; ASSERT(string); for (p=string; *p; p++) *p = utolower(*p); return string; } #endif #ifdef ALLEGRO_NO_STRUPR /* _alemu_strupr: * Convert all lower case characters in string to upper case. */ char *_alemu_strupr(char *string) { char *p; ASSERT(string); for (p=string; *p; p++) *p = utoupper(*p); return string; } #endif #ifdef ALLEGRO_NO_STRICMP /* _alemu_stricmp: * Case-insensitive comparison of strings. */ int _alemu_stricmp(AL_CONST char *s1, AL_CONST char *s2) { int c1, c2; ASSERT(s1); ASSERT(s2); do { c1 = utolower(*(s1++)); c2 = utolower(*(s2++)); } while ((c1) && (c1 == c2)); return c1 - c2; } #endif #ifdef ALLEGRO_NO_MEMCMP /* _alemu_memcmp: * Comparison of two memory blocks. */ int _alemu_memcmp(AL_CONST void *s1, AL_CONST void *s2, size_t num) { size_t i; ASSERT(s1); ASSERT(s2); ASSERT(num >= 0); for (i=0; i> 16) & _AL_RAND_MAX); } allegro-4.4.3.1/src/datafile.c0000664000175000017500000013007113437077643015006 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Datafile reading routines. * * By Shawn Hargreaves. * * Elias Pschernig made load_datafile_object() handle properties. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" static void unload_midi(MIDI *m); static void initialise_datafile(DATAFILE *data); /* hack to let the grabber prevent compiled sprites from being compiled */ int _compile_sprites = TRUE; /* flag to detect whether compiled datafiles are constructed: * A runtime flag is required because the shared version of the library may * have to deal both with executables that use constructors and with * executables that don't. */ static int constructed_datafiles = FALSE; static void (*datafile_callback)(DATAFILE *) = NULL; /* load_st_data: * I'm not using this format any more, but files created with the old * version of Allegro might have some bitmaps stored like this. It is * the 4bpp planar system used by the Atari ST low resolution mode. */ static void load_st_data(unsigned char *pos, long size, PACKFILE *f) { int c; unsigned int d1, d2, d3, d4; size /= 8; /* number of 4 word planes to read */ while (size) { d1 = pack_mgetw(f); d2 = pack_mgetw(f); d3 = pack_mgetw(f); d4 = pack_mgetw(f); for (c=0; c<16; c++) { *(pos++) = ((d1 & 0x8000) >> 15) + ((d2 & 0x8000) >> 14) + ((d3 & 0x8000) >> 13) + ((d4 & 0x8000) >> 12); d1 <<= 1; d2 <<= 1; d3 <<= 1; d4 <<= 1; } size--; } } /* read_block: * Reads a block of size bytes from a file, allocating memory to store it. */ static void *read_block(PACKFILE *f, int size, int alloc_size) { void *p; p = _AL_MALLOC_ATOMIC(MAX(size, alloc_size)); if (!p) { *allegro_errno = ENOMEM; return NULL; } pack_fread(p, size, f); if (pack_ferror(f)) { _AL_FREE(p); return NULL; } return p; } /* read_bitmap: * Reads a bitmap from a file, allocating memory to store it. */ static BITMAP *read_bitmap(PACKFILE *f, int bits, int allowconv) { int x, y, w, h, c, r, g, b, a; int destbits, rgba; unsigned short *p16; uint32_t *p32; BITMAP *bmp; if (bits < 0) { bits = -bits; rgba = TRUE; } else rgba = FALSE; if (allowconv) destbits = _color_load_depth(bits, rgba); else destbits = 8; w = pack_mgetw(f); h = pack_mgetw(f); bmp = create_bitmap_ex(MAX(bits, 8), w, h); if (!bmp) { *allegro_errno = ENOMEM; return NULL; } switch (bits) { case 4: /* old format ST data */ load_st_data(bmp->dat, w*h/2, f); break; case 8: /* 256 color bitmap */ pack_fread(bmp->dat, w*h, f); break; case 15: /* 15bit hicolor */ for (y=0; yline[y]; for (x=0; x> 11) & 0x1F]; /* stored as 16 bit */ g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; p16[x] = makecol15(r, g, b); } } break; case 16: /* 16bit hicolor */ for (y=0; yline[y]; for (x=0; x> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; p16[x] = makecol16(r, g, b); } } break; case 24: /* 24bit truecolor */ for (y=0; yline[y] + (x * 3), c); } } break; case 32: /* 32bit rgba */ for (y=0; yline[y]; for (x=0; xw, bmp->h); destroy_bitmap(tmp); } return bmp; } /* read_font_fixed: * Reads a fixed pitch font from a file. This format is no longer used. */ static FONT *read_font_fixed(PACKFILE *pack, int height, int maxchars) { FONT *f = NULL; FONT_MONO_DATA *mf = NULL; FONT_GLYPH **gl = NULL; int i = 0; f = _AL_MALLOC(sizeof(FONT)); mf = _AL_MALLOC(sizeof(FONT_MONO_DATA)); gl = _AL_MALLOC(sizeof(FONT_GLYPH *) * maxchars); if (!f || !mf || !gl) { _AL_FREE(f); _AL_FREE(mf); _AL_FREE(gl); *allegro_errno = ENOMEM; return NULL; } f->data = mf; f->height = height; f->vtable = font_vtable_mono; mf->begin = ' '; mf->end = ' ' + maxchars; mf->next = NULL; mf->glyphs = gl; memset(gl, 0, sizeof(FONT_GLYPH *) * maxchars); for (i = 0; i < maxchars; i++) { FONT_GLYPH *g = _AL_MALLOC(sizeof(FONT_GLYPH) + height); if (!g) { destroy_font(f); *allegro_errno = ENOMEM; return NULL; } gl[i] = g; g->w = 8; g->h = height; pack_fread(g->dat, height, pack); } return f; } /* read_font_prop: * Reads a proportional font from a file. This format is no longer used. */ static FONT *read_font_prop(PACKFILE *pack, int maxchars) { FONT *f = NULL; FONT_COLOR_DATA *cf = NULL; BITMAP **bits = NULL; int i = 0, h = 0; f = _AL_MALLOC(sizeof(FONT)); cf = _AL_MALLOC(sizeof(FONT_COLOR_DATA)); bits = _AL_MALLOC(sizeof(BITMAP *) * maxchars); if (!f || !cf || !bits) { _AL_FREE(f); _AL_FREE(cf); _AL_FREE(bits); *allegro_errno = ENOMEM; return NULL; } f->data = cf; f->vtable = font_vtable_color; cf->begin = ' '; cf->end = ' ' + maxchars; cf->next = NULL; cf->bitmaps = bits; memset(bits, 0, sizeof(BITMAP *) * maxchars); for (i = 0; i < maxchars; i++) { if (pack_feof(pack)) break; bits[i] = read_bitmap(pack, 8, FALSE); if (!bits[i]) { destroy_font(f); return NULL; } if (bits[i]->h > h) h = bits[i]->h; } while (i < maxchars) { bits[i] = create_bitmap_ex(8, 8, h); if (!bits[i]) { destroy_font(f); *allegro_errno = ENOMEM; return NULL; } clear_bitmap(bits[i]); i++; } f->height = h; return f; } /* read_font_mono: * Helper for read_font, below */ static FONT_MONO_DATA *read_font_mono(PACKFILE *f, int *hmax) { FONT_MONO_DATA *mf = NULL; int max = 0, i = 0; FONT_GLYPH **gl = NULL; mf = _AL_MALLOC(sizeof(FONT_MONO_DATA)); if (!mf) { *allegro_errno = ENOMEM; return NULL; } mf->begin = pack_mgetl(f); mf->end = pack_mgetl(f) + 1; mf->next = NULL; max = mf->end - mf->begin; mf->glyphs = gl = _AL_MALLOC(sizeof(FONT_GLYPH *) * max); if (!gl) { _AL_FREE(mf); *allegro_errno = ENOMEM; return NULL; } for (i = 0; i < max; i++) { int w, h, sz; w = pack_mgetw(f); h = pack_mgetw(f); sz = ((w + 7) / 8) * h; if (h > *hmax) *hmax = h; gl[i] = _AL_MALLOC(sizeof(FONT_GLYPH) + sz); if (!gl[i]) { while (i) { i--; _AL_FREE(mf->glyphs[i]); } _AL_FREE(mf); _AL_FREE(mf->glyphs); *allegro_errno = ENOMEM; return NULL; } gl[i]->w = w; gl[i]->h = h; pack_fread(gl[i]->dat, sz, f); } return mf; } /* read_font_color: * Helper for read_font, below. */ static FONT_COLOR_DATA *read_font_color(PACKFILE *pack, int *hmax, int depth) { FONT_COLOR_DATA *cf = NULL; int max = 0, i = 0; BITMAP **bits = NULL; cf = _AL_MALLOC(sizeof(FONT_COLOR_DATA)); if (!cf) { *allegro_errno = ENOMEM; return NULL; } cf->begin = pack_mgetl(pack); cf->end = pack_mgetl(pack) + 1; cf->next = NULL; max = cf->end - cf->begin; cf->bitmaps = bits = _AL_MALLOC(sizeof(BITMAP *) * max); if (!bits) { _AL_FREE(cf); *allegro_errno = ENOMEM; return NULL; } for (i = 0; i < max; i++) { /* Do not allow colour conversions for 8 bit bitmaps, but require it for * all other colour depths. */ bits[i] = read_bitmap(pack, depth, depth!=8); if (!bits[i]) { while (i) { i--; destroy_bitmap(bits[i]); } _AL_FREE(bits); _AL_FREE(cf); *allegro_errno = ENOMEM; return 0; } if (bits[i]->h > *hmax) *hmax = bits[i]->h; } return cf; } /* read_font: * Reads a new style, Unicode format font from a file. */ static FONT *read_font(PACKFILE *pack) { FONT *f = NULL; int num_ranges = 0; int height = 0; int depth; f = _AL_MALLOC(sizeof(FONT)); if (!f) { *allegro_errno = ENOMEM; return NULL; } f->data = NULL; num_ranges = pack_mgetw(pack); while (num_ranges--) { depth = pack_getc(pack); if (depth == 1 || depth == 255) { FONT_MONO_DATA *mf = 0, *iter = (FONT_MONO_DATA *)f->data; f->vtable = font_vtable_mono; mf = read_font_mono(pack, &height); if (!mf) { destroy_font(f); return NULL; } if (!iter) f->data = mf; else { while (iter->next) iter = iter->next; iter->next = mf; } } else { FONT_COLOR_DATA *cf = NULL, *iter = (FONT_COLOR_DATA *)f->data; /* Older versions of Allegro use `0' to indicate a colour font */ if (depth == 0) depth = 8; f->vtable = font_vtable_color; cf = read_font_color(pack, &height, depth); if (!cf) { destroy_font(f); return NULL; } if (!iter) f->data = cf; else { while (iter->next) iter = iter->next; iter->next = cf; } } } f->height = height; return f; } /* read_palette: * Reads a palette from a file. */ static RGB *read_palette(PACKFILE *f, int size) { RGB *p; int c, x; p = _AL_MALLOC_ATOMIC(sizeof(PALETTE)); if (!p) { *allegro_errno = ENOMEM; return NULL; } for (c=0; c> 2; p[c].g = pack_getc(f) >> 2; p[c].b = pack_getc(f) >> 2; } x = 0; while (c < PAL_SIZE) { p[c] = p[x]; c++; x++; if (x >= size) x = 0; } return p; } /* read_sample: * Reads a sample from a file. */ static SAMPLE *read_sample(PACKFILE *f) { signed short bits; SAMPLE *s; s = _AL_MALLOC(sizeof(SAMPLE)); if (!s) { *allegro_errno = ENOMEM; return NULL; } bits = pack_mgetw(f); if (bits < 0) { s->bits = -bits; s->stereo = TRUE; } else { s->bits = bits; s->stereo = FALSE; } s->freq = pack_mgetw(f); s->len = pack_mgetl(f); s->priority = 128; s->loop_start = 0; s->loop_end = s->len; s->param = 0; if (s->bits == 8) { s->data = read_block(f, s->len * ((s->stereo) ? 2 : 1), 0); } else { s->data = _AL_MALLOC_ATOMIC(s->len * sizeof(short) * ((s->stereo) ? 2 : 1)); if (s->data) { int i; for (i=0; i < (int)s->len * ((s->stereo) ? 2 : 1); i++) { ((unsigned short *)s->data)[i] = pack_igetw(f); } if (pack_ferror(f)) { _AL_FREE(s->data); s->data = NULL; } } } if (!s->data) { _AL_FREE(s); return NULL; } LOCK_DATA(s, sizeof(SAMPLE)); LOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1)); return s; } /* read_midi: * Reads MIDI data from a datafile (this is not the same thing as the * standard midi file format). */ static MIDI *read_midi(PACKFILE *f) { MIDI *m; int c; m = _AL_MALLOC(sizeof(MIDI)); if (!m) { *allegro_errno = ENOMEM; return NULL; } for (c=0; ctrack[c].len = 0; m->track[c].data = NULL; } m->divisions = pack_mgetw(f); for (c=0; ctrack[c].len = pack_mgetl(f); if (m->track[c].len > 0) { m->track[c].data = read_block(f, m->track[c].len, 0); if (!m->track[c].data) { unload_midi(m); return NULL; } } } LOCK_DATA(m, sizeof(MIDI)); for (c=0; ctrack[c].data) { LOCK_DATA(m->track[c].data, m->track[c].len); } } return m; } /* read_rle_sprite: * Reads an RLE compressed sprite from a file, allocating memory for it. */ static RLE_SPRITE *read_rle_sprite(PACKFILE *f, int bits) { int x, y, w, h, c, r, g, b, a; int destbits, size, rgba; RLE_SPRITE *s; BITMAP *b1, *b2; unsigned int eol_marker; signed short s16; signed short *p16; int32_t *p32; if (bits < 0) { bits = -bits; rgba = TRUE; } else rgba = FALSE; w = pack_mgetw(f); h = pack_mgetw(f); size = pack_mgetl(f); s = _AL_MALLOC(sizeof(RLE_SPRITE) + size); if (!s) { *allegro_errno = ENOMEM; return NULL; } s->w = w; s->h = h; s->color_depth = bits; s->size = size; switch (bits) { case 8: /* easy! */ pack_fread(s->dat, size, f); break; case 15: case 16: /* read hicolor data */ p16 = (signed short *)s->dat; eol_marker = (bits == 15) ? MASK_COLOR_15 : MASK_COLOR_16; for (y=0; y 0) { c = pack_igetw(f); r = _rgb_scale_5[(c >> 11) & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[c & 0x1F]; *p16 = makecol_depth(bits, r, g, b); p16++; } } s16 = pack_igetw(f); } /* end of line */ *p16 = eol_marker; p16++; } break; case 24: case 32: /* read truecolor data */ p32 = (int32_t *)s->dat; eol_marker = (bits == 24) ? MASK_COLOR_24 : MASK_COLOR_32; for (y=0; y 0) { r = pack_getc(f); g = pack_getc(f); b = pack_getc(f); if (rgba) a = pack_getc(f); else a = 0; *p32 = makeacol_depth(bits, r, g, b, a); p32++; } } c = pack_igetl(f); } /* end of line */ *p32 = eol_marker; p32++; } break; } destbits = _color_load_depth(bits, rgba); if (destbits != bits) { b1 = create_bitmap_ex(bits, s->w, s->h); if (!b1) { destroy_rle_sprite(s); *allegro_errno = ENOMEM; return NULL; } clear_to_color(b1, bitmap_mask_color(b1)); draw_rle_sprite(b1, s, 0, 0); b2 = create_bitmap_ex(destbits, s->w, s->h); if (!b2) { destroy_rle_sprite(s); destroy_bitmap(b1); *allegro_errno = ENOMEM; return NULL; } blit(b1, b2, 0, 0, 0, 0, s->w, s->h); destroy_rle_sprite(s); s = get_rle_sprite(b2); destroy_bitmap(b1); destroy_bitmap(b2); } return s; } /* read_compiled_sprite: * Reads a compiled sprite from a file, allocating memory for it. */ static COMPILED_SPRITE *read_compiled_sprite(PACKFILE *f, int planar, int bits) { BITMAP *b; COMPILED_SPRITE *s; b = read_bitmap(f, bits, TRUE); if (!b) return NULL; if (!_compile_sprites) return (COMPILED_SPRITE *)b; s = get_compiled_sprite(b, planar); if (!s) *allegro_errno = ENOMEM; destroy_bitmap(b); return s; } /* read_old_datafile: * Helper for reading old-format datafiles (only needed for backward * compatibility). */ static DATAFILE *read_old_datafile(PACKFILE *f, void (*callback)(DATAFILE *)) { DATAFILE *dat; int size; int type; int c; size = pack_mgetw(f); if (size == EOF) { pack_fclose(f); return NULL; } dat = _AL_MALLOC(sizeof(DATAFILE)*(size+1)); if (!dat) { pack_fclose(f); *allegro_errno = ENOMEM; return NULL; } for (c=0; c<=size; c++) { dat[c].type = DAT_END; dat[c].dat = NULL; dat[c].size = 0; dat[c].prop = NULL; } *allegro_errno = 0; for (c=0; c 0) return read_font_fixed(f, height, LESS_OLD_FONT_SIZE); else if (height < 0) return read_font_prop(f, LESS_OLD_FONT_SIZE); else return read_font(f); } /* load_sample_object: * Loads a sample object from a datafile. */ static void *load_sample_object(PACKFILE *f, long size) { return read_sample(f); } /* load_midi_object: * Loads a midifile object from a datafile. */ static void *load_midi_object(PACKFILE *f, long size) { return read_midi(f); } /* load_bitmap_object: * Loads a bitmap object from a datafile. */ static void *load_bitmap_object(PACKFILE *f, long size) { short bits = pack_mgetw(f); return read_bitmap(f, bits, TRUE); } /* load_rle_sprite_object: * Loads an RLE sprite object from a datafile. */ static void *load_rle_sprite_object(PACKFILE *f, long size) { short bits = pack_mgetw(f); return read_rle_sprite(f, bits); } /* load_compiled_sprite_object: * Loads a compiled sprite object from a datafile. */ static void *load_compiled_sprite_object(PACKFILE *f, long size) { short bits = pack_mgetw(f); return read_compiled_sprite(f, FALSE, bits); } /* load_xcompiled_sprite_object: * Loads a mode-X compiled object from a datafile. */ static void *load_xcompiled_sprite_object(PACKFILE *f, long size) { short bits = pack_mgetw(f); return read_compiled_sprite(f, TRUE, bits); } /* unload_sample: * Destroys a sample object. */ static void unload_sample(SAMPLE *s) { if (s) { if (s->data) { UNLOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1)); _AL_FREE(s->data); } UNLOCK_DATA(s, sizeof(SAMPLE)); _AL_FREE(s); } } /* unload_midi: * Destroys a MIDI object. */ static void unload_midi(MIDI *m) { int c; if (m) { for (c=0; ctrack[c].data) { UNLOCK_DATA(m->track[c].data, m->track[c].len); _AL_FREE(m->track[c].data); } } UNLOCK_DATA(m, sizeof(MIDI)); _AL_FREE(m); } } /* load_object: * Helper to load an object from a datafile and store it in 'obj'. * Returns 0 on success and -1 on failure. */ static int load_object(DATAFILE *obj, PACKFILE *f, int type) { PACKFILE *ff; int d, i; /* load actual data */ ff = pack_fopen_chunk(f, FALSE); if (ff) { d = ff->normal.todo; /* look for a load function */ for (i=0; idat = _datafile_type[i].load(ff, d); goto Found; } } /* if not found, load binary data */ obj->dat = load_data_object(ff, d); Found: pack_fclose_chunk(ff); if (!obj->dat) return -1; obj->type = type; obj->size = d; return 0; } return -1; } /* _load_property: * Helper to load a property from a datafile and store it in 'prop'. * Returns 0 on success and -1 on failure. */ int _load_property(DATAFILE_PROPERTY *prop, PACKFILE *f) { int type, size; char *p; type = pack_mgetl(f); size = pack_mgetl(f); prop->type = type; prop->dat = _AL_MALLOC_ATOMIC(size+1); /* '1' for end-of-string delimiter */ if (!prop->dat) { *allegro_errno = ENOMEM; pack_fseek(f, size); return -1; } /* read the property */ pack_fread(prop->dat, size, f); prop->dat[size] = 0; /* convert to current encoding format if needed */ if (need_uconvert(prop->dat, U_UTF8, U_CURRENT)) { int length = uconvert_size(prop->dat, U_UTF8, U_CURRENT); p = _AL_MALLOC_ATOMIC(length); if (!p) { *allegro_errno = ENOMEM; return -1; } do_uconvert(prop->dat, U_UTF8, p, U_CURRENT, length); _AL_FREE(prop->dat); prop->dat = p; } return 0; } /* _add_property: * Helper to add a new property to a property list. Returns 0 on * success or -1 on failure. */ int _add_property(DATAFILE_PROPERTY **list, DATAFILE_PROPERTY *prop) { DATAFILE_PROPERTY *iter; int length = 0; ASSERT(list); ASSERT(prop); /* find the length of the list */ if (*list) { iter = *list; while (iter->type != DAT_END) { length++; iter++; } } /* grow the list */ *list = _al_sane_realloc(*list, sizeof(DATAFILE_PROPERTY)*(length+2)); if (!(*list)) { *allegro_errno = ENOMEM; return -1; } /* copy the new property */ (*list)[length] = *prop; /* set end-of-array marker */ (*list)[length+1].type = DAT_END; (*list)[length+1].dat = NULL; return 0; } /* _destroy_property_list: * Helper to destroy a property list. */ void _destroy_property_list(DATAFILE_PROPERTY *list) { int c; for (c=0; list[c].type != DAT_END; c++) { if (list[c].dat) _AL_FREE(list[c].dat); } _AL_FREE(list); } /* load_file_object: * Loads a datafile object. */ static void *load_file_object(PACKFILE *f, long size) { DATAFILE *dat; DATAFILE_PROPERTY prop, *list; int count, c, type, failed; count = pack_mgetl(f); dat = _AL_MALLOC(sizeof(DATAFILE)*(count+1)); if (!dat) { *allegro_errno = ENOMEM; return NULL; } list = NULL; failed = FALSE; /* search the packfile for properties or objects */ for (c=0; cnormal.flags & PACKFILE_FLAG_CHUNK) && (!(f->normal.flags & PACKFILE_FLAG_EXEDAT))) type = (_packfile_type == DAT_FILE) ? DAT_MAGIC : 0; else type = pack_mgetl(f); if (type == V1_DAT_MAGIC) { dat = read_old_datafile(f, callback); } else if (type == DAT_MAGIC) { datafile_callback = callback; dat = load_file_object(f, 0); datafile_callback = NULL; } else dat = NULL; pack_fclose(f); return dat; } /* create_datafile_index * Reads offsets of all objects inside datafile. * On error, sets errno and returns NULL. */ DATAFILE_INDEX *create_datafile_index(AL_CONST char *filename) { PACKFILE *f; DATAFILE_INDEX *index; long pos = 4; int type, count, skip, i; ASSERT(filename); f = pack_fopen(filename, F_READ_PACKED); if (!f) return NULL; if ((f->normal.flags & PACKFILE_FLAG_CHUNK) && (!(f->normal.flags & PACKFILE_FLAG_EXEDAT))) type = (_packfile_type == DAT_FILE) ? DAT_MAGIC : 0; else { type = pack_mgetl(f); pos += 4; } /* only support V2 datafile format */ if (type != DAT_MAGIC) return NULL; count = pack_mgetl(f); pos += 4; index = _AL_MALLOC(sizeof(DATAFILE_INDEX)); if (!index) { pack_fclose(f); *allegro_errno = ENOMEM; return NULL; } index->filename = _al_ustrdup(filename); if (!index->filename) { pack_fclose(f); _AL_FREE(index); *allegro_errno = ENOMEM; return NULL; } index->offset = _AL_MALLOC(sizeof(long) * count); if (!index->offset) { pack_fclose(f); _AL_FREE(index->filename); _AL_FREE(index); *allegro_errno = ENOMEM; return NULL; } for (i = 0; i < count; ++i) { index->offset[i] = pos; /* Skip properties */ while (pos += 4, pack_mgetl(f) == DAT_PROPERTY) { /* Skip property name */ pack_fseek(f, 4); pos += 4; /* Skip rest of property */ skip = pack_mgetl(f); pos += 4; /* Get property size */ pack_fseek(f, skip); pos += skip; } /* Skip rest of object */ skip = pack_mgetl(f) + 4; pos += 4; pack_fseek(f, skip); pos += skip; } pack_fclose(f); return index; } /* load_datafile_object: * Loads a single object from a datafile. */ DATAFILE *load_datafile_object(AL_CONST char *filename, AL_CONST char *objectname) { PACKFILE *f; DATAFILE *dat; DATAFILE_PROPERTY prop, *list; char parent[1024], child[1024], tmp[8]; char *bufptr, *prevptr, *separator; int count, c, type, size, found; ASSERT(filename); ASSERT(objectname); /* concatenate to filename#objectname */ ustrzcpy(parent, sizeof(parent), filename); if (ustrcmp(parent, uconvert_ascii("#", tmp)) != 0) ustrzcat(parent, sizeof(parent), uconvert_ascii("#", tmp)); ustrzcat(parent, sizeof(parent), objectname); /* split into path and actual objectname (for nested files) */ prevptr = bufptr = parent; separator = NULL; while ((c = ugetx(&bufptr)) != 0) { if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR)) separator = prevptr; prevptr = bufptr; } ustrzcpy(child, sizeof(child), separator + uwidth (separator)); if (separator == parent) usetc(separator + uwidth (separator), 0); else usetc(separator, 0); /* open the parent datafile */ f = pack_fopen(parent, F_READ_PACKED); if (!f) return NULL; if ((f->normal.flags & PACKFILE_FLAG_CHUNK) && (!(f->normal.flags & PACKFILE_FLAG_EXEDAT))) type = (_packfile_type == DAT_FILE) ? DAT_MAGIC : 0; else type = pack_mgetl(f); /* only support V2 datafile format */ if (type != DAT_MAGIC) { pack_fclose(f); return NULL; } count = pack_mgetl(f); dat = NULL; list = NULL; found = FALSE; /* search the packfile for properties or objects */ for (c=0; cprop = list; list = NULL; break; } else { /* skip an unwanted object */ size = pack_mgetl(f); pack_fseek(f, size+4); /* '4' for the chunk size */ /* destroy the property list */ if (list) { _destroy_property_list(list); list = NULL; } c++; } } } /* destroy the property list if not assigned to an object */ if (list) _destroy_property_list(list); pack_fclose(f); return dat; } /* load_datafile_object_indexed * Loads a single object from a datafile using its offset. * On error, returns NULL. */ DATAFILE *load_datafile_object_indexed(AL_CONST DATAFILE_INDEX *index, int item) { int type; PACKFILE *f; DATAFILE *dat; DATAFILE_PROPERTY prop, *list = NULL; ASSERT(index); f = pack_fopen(index->filename, F_READ_PACKED); if (!f) return NULL; dat = _AL_MALLOC(sizeof(DATAFILE)); if (!dat) { pack_fclose(f); *allegro_errno = ENOMEM; return NULL; } /* pack_fopen will read first 4 bytes for us */ pack_fseek(f, index->offset[item] - 4); do type = pack_mgetl(f); while (type == DAT_PROPERTY && _load_property(&prop, f) == 0 && _add_property(&list, &prop) == 0); if (load_object(dat, f, type) != 0) { pack_fclose(f); _AL_FREE(dat); _destroy_property_list(list); return NULL; } /* attach the property list to the object */ dat->prop = list; pack_fclose(f); return dat; } /* _unload_datafile_object: * Helper to destroy a datafile object. */ void _unload_datafile_object(DATAFILE *dat) { int i; /* destroy the property list */ if (dat->prop) _destroy_property_list(dat->prop); /* look for a destructor function */ for (i=0; itype) { if (dat->dat) { if (_datafile_type[i].destroy) _datafile_type[i].destroy(dat->dat); else _AL_FREE(dat->dat); } return; } } /* if not found, just free the data */ if (dat->dat) _AL_FREE(dat->dat); } /* unload_datafile: * Frees all the objects in a datafile. */ void unload_datafile(DATAFILE *dat) { int i; if (dat) { for (i=0; dat[i].type != DAT_END; i++) _unload_datafile_object(dat+i); _AL_FREE(dat); } } /* unload_datafile_index * Frees memory used by datafile index */ void destroy_datafile_index(DATAFILE_INDEX *index) { if (index) { _AL_FREE(index->filename); _AL_FREE(index->offset); _AL_FREE(index); } } /* unload_datafile_object: * Unloads a single datafile object, returned by load_datafile_object(). */ void unload_datafile_object(DATAFILE *dat) { if (dat) { _unload_datafile_object(dat); _AL_FREE(dat); } } /* find_datafile_object: * Returns a pointer to the datafile object with the given name */ DATAFILE *find_datafile_object(AL_CONST DATAFILE *dat, AL_CONST char *objectname) { char name[512]; int recurse = FALSE; int pos, c; ASSERT(dat); ASSERT(objectname); /* split up the object name */ pos = 0; while ((c = ugetxc(&objectname)) != 0) { if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR)) { recurse = TRUE; break; } pos += usetc(name+pos, c); } usetc(name+pos, 0); /* search for the requested object */ for (pos=0; dat[pos].type != DAT_END; pos++) { if (ustricmp(name, get_datafile_property(dat+pos, DAT_NAME)) == 0) { if (recurse) { if (dat[pos].type == DAT_FILE) return find_datafile_object(dat[pos].dat, objectname); else return NULL; } else return (DATAFILE*)dat+pos; } } /* oh dear, the object isn't there... */ return NULL; } /* get_datafile_property: * Returns the specified property string for the datafile object, or * an empty string if the property does not exist. */ AL_CONST char *get_datafile_property(AL_CONST DATAFILE *dat, int type) { DATAFILE_PROPERTY *prop; ASSERT(dat); prop = dat->prop; if (prop) { while (prop->type != DAT_END) { if (prop->type == type) return (prop->dat) ? prop->dat : empty_string; prop++; } } return empty_string; } /* fixup_datafile: * For use with compiled datafiles, to initialise them if they are not * constructed and to convert truecolor images into the appropriate * pixel format. */ void fixup_datafile(DATAFILE *data) { BITMAP *bmp; RLE_SPRITE *rle; int i, c, r, g, b, a, x, y; int bpp, depth; unsigned char *p8; unsigned short *p16; uint32_t *p32; signed short *s16; int32_t *s32; int eol_marker; ASSERT(data); /* initialise the datafile if needed */ if (!constructed_datafiles) initialise_datafile(data); for (i=0; data[i].type != DAT_END; i++) { switch (data[i].type) { case DAT_BITMAP: /* fix up a bitmap object */ bmp = data[i].dat; bpp = bitmap_color_depth(bmp); switch (bpp) { #ifdef ALLEGRO_COLOR16 case 15: /* fix up a 15 bit hicolor bitmap */ if (_color_depth == 16) { GFX_VTABLE *vtable = _get_vtable(16); if (vtable != NULL) { depth = 16; bmp->vtable = vtable; } else depth = 15; } else depth = 15; for (y=0; yh; y++) { p16 = (unsigned short *)bmp->line[y]; for (x=0; xw; x++) { c = p16[x]; r = _rgb_scale_5[c & 0x1F]; g = _rgb_scale_5[(c >> 5) & 0x1F]; b = _rgb_scale_5[(c >> 10) & 0x1F]; p16[x] = makecol_depth(depth, r, g, b); } } break; case 16: /* fix up a 16 bit hicolor bitmap */ if (_color_depth == 15) { GFX_VTABLE *vtable = _get_vtable(15); if (vtable != NULL) { depth = 15; bmp->vtable = vtable; } else depth = 16; } else depth = 16; for (y=0; yh; y++) { p16 = (unsigned short *)bmp->line[y]; for (x=0; xw; x++) { c = p16[x]; r = _rgb_scale_5[c & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[(c >> 11) & 0x1F]; if (_color_conv & COLORCONV_KEEP_TRANS && depth == 15 && c == 0xf83f) g = 8; /* don't end up as mask color */ p16[x] = makecol_depth(depth, r, g, b); } } break; #endif #ifdef ALLEGRO_COLOR24 case 24: /* fix up a 24 bit truecolor bitmap */ for (y=0; yh; y++) { p8 = bmp->line[y]; for (x=0; xw; x++) { c = READ3BYTES(p8+x*3); r = (c & 0xFF); g = (c >> 8) & 0xFF; b = (c >> 16) & 0xFF; WRITE3BYTES(p8+x*3, makecol24(r, g, b)); } } break; #endif #ifdef ALLEGRO_COLOR32 case 32: /* fix up a 32 bit truecolor bitmap */ for (y=0; yh; y++) { p32 = (uint32_t *)bmp->line[y]; for (x=0; xw; x++) { c = p32[x]; r = (c & 0xFF); g = (c >> 8) & 0xFF; b = (c >> 16) & 0xFF; a = (c >> 24) & 0xFF; p32[x] = makeacol32(r, g, b, a); } } break; #endif } break; case DAT_RLE_SPRITE: /* fix up an RLE sprite object */ rle = data[i].dat; bpp = rle->color_depth; switch (bpp) { #ifdef ALLEGRO_COLOR16 case 15: /* fix up a 15 bit hicolor RLE sprite */ if (_color_depth == 16) { depth = 16; rle->color_depth = 16; eol_marker = MASK_COLOR_16; } else { depth = 15; eol_marker = MASK_COLOR_15; } s16 = (signed short *)rle->dat; for (y=0; yh; y++) { while ((unsigned short)*s16 != MASK_COLOR_15) { if (*s16 > 0) { x = *s16; s16++; while (x-- > 0) { c = *s16; r = _rgb_scale_5[c & 0x1F]; g = _rgb_scale_5[(c >> 5) & 0x1F]; b = _rgb_scale_5[(c >> 10) & 0x1F]; *s16 = makecol_depth(depth, r, g, b); s16++; } } else s16++; } *s16 = eol_marker; s16++; } break; case 16: /* fix up a 16 bit hicolor RLE sprite */ if (_color_depth == 15) { depth = 15; rle->color_depth = 15; eol_marker = MASK_COLOR_15; } else { depth = 16; eol_marker = MASK_COLOR_16; } s16 = (signed short *)rle->dat; for (y=0; yh; y++) { while ((unsigned short)*s16 != MASK_COLOR_16) { if (*s16 > 0) { x = *s16; s16++; while (x-- > 0) { c = *s16; r = _rgb_scale_5[c & 0x1F]; g = _rgb_scale_6[(c >> 5) & 0x3F]; b = _rgb_scale_5[(c >> 11) & 0x1F]; *s16 = makecol_depth(depth, r, g, b); s16++; } } else s16++; } *s16 = eol_marker; s16++; } break; #endif #ifdef ALLEGRO_COLOR24 case 24: /* fix up a 24 bit truecolor RLE sprite */ if (_color_depth == 32) { depth = 32; rle->color_depth = 32; eol_marker = MASK_COLOR_32; } else { depth = 24; eol_marker = MASK_COLOR_24; } s32 = (int32_t *)rle->dat; for (y=0; yh; y++) { while ((uint32_t)*s32 != MASK_COLOR_24) { if (*s32 > 0) { x = *s32; s32++; while (x-- > 0) { c = *s32; r = (c & 0xFF); g = (c>>8) & 0xFF; b = (c>>16) & 0xFF; *s32 = makecol_depth(depth, r, g, b); s32++; } } else s32++; } *s32 = eol_marker; s32++; } break; #endif #ifdef ALLEGRO_COLOR32 case 32: /* fix up a 32 bit truecolor RLE sprite */ if (_color_depth == 24) { depth = 24; rle->color_depth = 24; eol_marker = MASK_COLOR_24; } else { depth = 32; eol_marker = MASK_COLOR_32; } s32 = (int32_t *)rle->dat; for (y=0; yh; y++) { while ((uint32_t)*s32 != MASK_COLOR_32) { if (*s32 > 0) { x = *s32; s32++; while (x-- > 0) { c = *s32; r = (c & 0xFF); g = (c>>8) & 0xFF; b = (c>>16) & 0xFF; if (depth == 32) { a = (c>>24) & 0xFF; *s32 = makeacol32(r, g, b, a); } else *s32 = makecol24(r, g, b); s32++; } } else s32++; } *s32 = eol_marker; s32++; } break; #endif } break; } } } /* initialise_bitmap: * Helper used by the output from dat2s/c, for fixing up parts * of a BITMAP structure that can't be statically initialised. */ static void initialise_bitmap(BITMAP *bmp) { int i; for (i=0; _vtable_list[i].vtable; i++) { if (_vtable_list[i].color_depth == (int)(uintptr_t)bmp->vtable) { bmp->vtable = _vtable_list[i].vtable; bmp->write_bank = _stub_bank_switch; bmp->read_bank = _stub_bank_switch; bmp->seg = _default_ds(); return; } } ASSERT(FALSE); } /* initialise_datafile: * Helper used by the output from dat2s/c, for fixing up parts * of the data that can't be statically initialised. */ static void initialise_datafile(DATAFILE *data) { int c, c2, color_flag; FONT *f; SAMPLE *s; MIDI *m; for (c=0; data[c].type != DAT_END; c++) { switch (data[c].type) { case DAT_FILE: initialise_datafile(data[c].dat); break; case DAT_BITMAP: initialise_bitmap((BITMAP *)data[c].dat); break; case DAT_FONT: f = data[c].dat; color_flag = (int)(uintptr_t)f->vtable; if (color_flag == 1) { FONT_COLOR_DATA *cf = (FONT_COLOR_DATA *)f->data; while (cf) { for (c2 = cf->begin; c2 < cf->end; c2++) initialise_bitmap((BITMAP *)cf->bitmaps[c2 - cf->begin]); cf = cf->next; } f->vtable = font_vtable_color; } else { f->vtable = font_vtable_mono; } break; case DAT_SAMPLE: s = data[c].dat; LOCK_DATA(s, sizeof(SAMPLE)); LOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1)); break; case DAT_MIDI: m = data[c].dat; LOCK_DATA(m, sizeof(MIDI)); for (c2=0; c2track[c2].data) { LOCK_DATA(m->track[c2].data, m->track[c2].len); } } break; } } } /* _construct_datafile: * Constructor called by the output from dat2s/c. */ void _construct_datafile(DATAFILE *data) { /* record that datafiles are constructed */ constructed_datafiles = TRUE; initialise_datafile(data); } /* _initialize_datafile_types: * Register my loader functions with the code in dataregi.c. */ #ifdef ALLEGRO_USE_CONSTRUCTOR CONSTRUCTOR_FUNCTION(void _initialize_datafile_types(void)); #endif void _initialize_datafile_types(void) { register_datafile_object(DAT_FILE, load_file_object, (void (*)(void *data))unload_datafile ); register_datafile_object(DAT_FONT, load_font_object, (void (*)(void *data))destroy_font ); register_datafile_object(DAT_SAMPLE, load_sample_object, (void (*)(void *data))unload_sample ); register_datafile_object(DAT_MIDI, load_midi_object, (void (*)(void *data))unload_midi ); register_datafile_object(DAT_BITMAP, load_bitmap_object, (void (*)(void *data))destroy_bitmap ); register_datafile_object(DAT_RLE_SPRITE, load_rle_sprite_object, (void (*)(void *data))destroy_rle_sprite ); register_datafile_object(DAT_C_SPRITE, load_compiled_sprite_object, (void (*)(void *data))destroy_compiled_sprite); register_datafile_object(DAT_XC_SPRITE, load_xcompiled_sprite_object, (void (*)(void *data))destroy_compiled_sprite); } allegro-4.4.3.1/src/math.c0000664000175000017500000004476613437077643014205 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fixed point math routines and lookup tables. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" fixed _cos_tbl[512] = { /* precalculated fixed point (16.16) cosines for a full circle (0-255) */ 65536L, 65531L, 65516L, 65492L, 65457L, 65413L, 65358L, 65294L, 65220L, 65137L, 65043L, 64940L, 64827L, 64704L, 64571L, 64429L, 64277L, 64115L, 63944L, 63763L, 63572L, 63372L, 63162L, 62943L, 62714L, 62476L, 62228L, 61971L, 61705L, 61429L, 61145L, 60851L, 60547L, 60235L, 59914L, 59583L, 59244L, 58896L, 58538L, 58172L, 57798L, 57414L, 57022L, 56621L, 56212L, 55794L, 55368L, 54934L, 54491L, 54040L, 53581L, 53114L, 52639L, 52156L, 51665L, 51166L, 50660L, 50146L, 49624L, 49095L, 48559L, 48015L, 47464L, 46906L, 46341L, 45769L, 45190L, 44604L, 44011L, 43412L, 42806L, 42194L, 41576L, 40951L, 40320L, 39683L, 39040L, 38391L, 37736L, 37076L, 36410L, 35738L, 35062L, 34380L, 33692L, 33000L, 32303L, 31600L, 30893L, 30182L, 29466L, 28745L, 28020L, 27291L, 26558L, 25821L, 25080L, 24335L, 23586L, 22834L, 22078L, 21320L, 20557L, 19792L, 19024L, 18253L, 17479L, 16703L, 15924L, 15143L, 14359L, 13573L, 12785L, 11996L, 11204L, 10411L, 9616L, 8820L, 8022L, 7224L, 6424L, 5623L, 4821L, 4019L, 3216L, 2412L, 1608L, 804L, 0L, -804L, -1608L, -2412L, -3216L, -4019L, -4821L, -5623L, -6424L, -7224L, -8022L, -8820L, -9616L, -10411L, -11204L, -11996L, -12785L, -13573L, -14359L, -15143L, -15924L, -16703L, -17479L, -18253L, -19024L, -19792L, -20557L, -21320L, -22078L, -22834L, -23586L, -24335L, -25080L, -25821L, -26558L, -27291L, -28020L, -28745L, -29466L, -30182L, -30893L, -31600L, -32303L, -33000L, -33692L, -34380L, -35062L, -35738L, -36410L, -37076L, -37736L, -38391L, -39040L, -39683L, -40320L, -40951L, -41576L, -42194L, -42806L, -43412L, -44011L, -44604L, -45190L, -45769L, -46341L, -46906L, -47464L, -48015L, -48559L, -49095L, -49624L, -50146L, -50660L, -51166L, -51665L, -52156L, -52639L, -53114L, -53581L, -54040L, -54491L, -54934L, -55368L, -55794L, -56212L, -56621L, -57022L, -57414L, -57798L, -58172L, -58538L, -58896L, -59244L, -59583L, -59914L, -60235L, -60547L, -60851L, -61145L, -61429L, -61705L, -61971L, -62228L, -62476L, -62714L, -62943L, -63162L, -63372L, -63572L, -63763L, -63944L, -64115L, -64277L, -64429L, -64571L, -64704L, -64827L, -64940L, -65043L, -65137L, -65220L, -65294L, -65358L, -65413L, -65457L, -65492L, -65516L, -65531L, -65536L, -65531L, -65516L, -65492L, -65457L, -65413L, -65358L, -65294L, -65220L, -65137L, -65043L, -64940L, -64827L, -64704L, -64571L, -64429L, -64277L, -64115L, -63944L, -63763L, -63572L, -63372L, -63162L, -62943L, -62714L, -62476L, -62228L, -61971L, -61705L, -61429L, -61145L, -60851L, -60547L, -60235L, -59914L, -59583L, -59244L, -58896L, -58538L, -58172L, -57798L, -57414L, -57022L, -56621L, -56212L, -55794L, -55368L, -54934L, -54491L, -54040L, -53581L, -53114L, -52639L, -52156L, -51665L, -51166L, -50660L, -50146L, -49624L, -49095L, -48559L, -48015L, -47464L, -46906L, -46341L, -45769L, -45190L, -44604L, -44011L, -43412L, -42806L, -42194L, -41576L, -40951L, -40320L, -39683L, -39040L, -38391L, -37736L, -37076L, -36410L, -35738L, -35062L, -34380L, -33692L, -33000L, -32303L, -31600L, -30893L, -30182L, -29466L, -28745L, -28020L, -27291L, -26558L, -25821L, -25080L, -24335L, -23586L, -22834L, -22078L, -21320L, -20557L, -19792L, -19024L, -18253L, -17479L, -16703L, -15924L, -15143L, -14359L, -13573L, -12785L, -11996L, -11204L, -10411L, -9616L, -8820L, -8022L, -7224L, -6424L, -5623L, -4821L, -4019L, -3216L, -2412L, -1608L, -804L, 0L, 804L, 1608L, 2412L, 3216L, 4019L, 4821L, 5623L, 6424L, 7224L, 8022L, 8820L, 9616L, 10411L, 11204L, 11996L, 12785L, 13573L, 14359L, 15143L, 15924L, 16703L, 17479L, 18253L, 19024L, 19792L, 20557L, 21320L, 22078L, 22834L, 23586L, 24335L, 25080L, 25821L, 26558L, 27291L, 28020L, 28745L, 29466L, 30182L, 30893L, 31600L, 32303L, 33000L, 33692L, 34380L, 35062L, 35738L, 36410L, 37076L, 37736L, 38391L, 39040L, 39683L, 40320L, 40951L, 41576L, 42194L, 42806L, 43412L, 44011L, 44604L, 45190L, 45769L, 46341L, 46906L, 47464L, 48015L, 48559L, 49095L, 49624L, 50146L, 50660L, 51166L, 51665L, 52156L, 52639L, 53114L, 53581L, 54040L, 54491L, 54934L, 55368L, 55794L, 56212L, 56621L, 57022L, 57414L, 57798L, 58172L, 58538L, 58896L, 59244L, 59583L, 59914L, 60235L, 60547L, 60851L, 61145L, 61429L, 61705L, 61971L, 62228L, 62476L, 62714L, 62943L, 63162L, 63372L, 63572L, 63763L, 63944L, 64115L, 64277L, 64429L, 64571L, 64704L, 64827L, 64940L, 65043L, 65137L, 65220L, 65294L, 65358L, 65413L, 65457L, 65492L, 65516L, 65531L }; fixed _tan_tbl[256] = { /* precalculated fixed point (16.16) tangents for a half circle (0-127) */ 0L, 804L, 1609L, 2414L, 3220L, 4026L, 4834L, 5644L, 6455L, 7268L, 8083L, 8901L, 9721L, 10545L, 11372L, 12202L, 13036L, 13874L, 14717L, 15564L, 16416L, 17273L, 18136L, 19005L, 19880L, 20762L, 21650L, 22546L, 23449L, 24360L, 25280L, 26208L, 27146L, 28093L, 29050L, 30018L, 30996L, 31986L, 32988L, 34002L, 35030L, 36071L, 37126L, 38196L, 39281L, 40382L, 41500L, 42636L, 43790L, 44963L, 46156L, 47369L, 48605L, 49863L, 51145L, 52451L, 53784L, 55144L, 56532L, 57950L, 59398L, 60880L, 62395L, 63947L, 65536L, 67165L, 68835L, 70548L, 72308L, 74116L, 75974L, 77887L, 79856L, 81885L, 83977L, 86135L, 88365L, 90670L, 93054L, 95523L, 98082L, 100736L, 103493L, 106358L, 109340L, 112447L, 115687L, 119071L, 122609L, 126314L, 130198L, 134276L, 138564L, 143081L, 147847L, 152884L, 158218L, 163878L, 169896L, 176309L, 183161L, 190499L, 198380L, 206870L, 216043L, 225990L, 236817L, 248648L, 261634L, 275959L, 291845L, 309568L, 329472L, 351993L, 377693L, 407305L, 441808L, 482534L, 531352L, 590958L, 665398L, 761030L, 888450L, 1066730L,1334016L,1779314L,2669641L,5340086L, -2147483647L,-5340086L,-2669641L,-1779314L,-1334016L,-1066730L,-888450L,-761030L, -665398L,-590958L,-531352L,-482534L,-441808L,-407305L,-377693L,-351993L, -329472L,-309568L,-291845L,-275959L,-261634L,-248648L,-236817L,-225990L, -216043L,-206870L,-198380L,-190499L,-183161L,-176309L,-169896L,-163878L, -158218L,-152884L,-147847L,-143081L,-138564L,-134276L,-130198L,-126314L, -122609L,-119071L,-115687L,-112447L,-109340L,-106358L,-103493L,-100736L, -98082L, -95523L, -93054L, -90670L, -88365L, -86135L, -83977L, -81885L, -79856L, -77887L, -75974L, -74116L, -72308L, -70548L, -68835L, -67165L, -65536L, -63947L, -62395L, -60880L, -59398L, -57950L, -56532L, -55144L, -53784L, -52451L, -51145L, -49863L, -48605L, -47369L, -46156L, -44963L, -43790L, -42636L, -41500L, -40382L, -39281L, -38196L, -37126L, -36071L, -35030L, -34002L, -32988L, -31986L, -30996L, -30018L, -29050L, -28093L, -27146L, -26208L, -25280L, -24360L, -23449L, -22546L, -21650L, -20762L, -19880L, -19005L, -18136L, -17273L, -16416L, -15564L, -14717L, -13874L, -13036L, -12202L, -11372L, -10545L, -9721L, -8901L, -8083L, -7268L, -6455L, -5644L, -4834L, -4026L, -3220L, -2414L, -1609L, -804L }; fixed _acos_tbl[513] = { /* precalculated fixed point (16.16) inverse cosines (-1 to 1) */ 0x800000L, 0x7C65C7L, 0x7AE75AL, 0x79C19EL, 0x78C9BEL, 0x77EF25L, 0x772953L, 0x76733AL, 0x75C991L, 0x752A10L, 0x74930CL, 0x740345L, 0x7379C1L, 0x72F5BAL, 0x72768FL, 0x71FBBCL, 0x7184D3L, 0x711174L, 0x70A152L, 0x703426L, 0x6FC9B5L, 0x6F61C9L, 0x6EFC36L, 0x6E98D1L, 0x6E3777L, 0x6DD805L, 0x6D7A5EL, 0x6D1E68L, 0x6CC40BL, 0x6C6B2FL, 0x6C13C1L, 0x6BBDAFL, 0x6B68E6L, 0x6B1558L, 0x6AC2F5L, 0x6A71B1L, 0x6A217EL, 0x69D251L, 0x698420L, 0x6936DFL, 0x68EA85L, 0x689F0AL, 0x685465L, 0x680A8DL, 0x67C17DL, 0x67792CL, 0x673194L, 0x66EAAFL, 0x66A476L, 0x665EE5L, 0x6619F5L, 0x65D5A2L, 0x6591E7L, 0x654EBFL, 0x650C26L, 0x64CA18L, 0x648890L, 0x64478CL, 0x640706L, 0x63C6FCL, 0x63876BL, 0x63484FL, 0x6309A5L, 0x62CB6AL, 0x628D9CL, 0x625037L, 0x621339L, 0x61D69FL, 0x619A68L, 0x615E90L, 0x612316L, 0x60E7F7L, 0x60AD31L, 0x6072C3L, 0x6038A9L, 0x5FFEE3L, 0x5FC56EL, 0x5F8C49L, 0x5F5372L, 0x5F1AE7L, 0x5EE2A7L, 0x5EAAB0L, 0x5E7301L, 0x5E3B98L, 0x5E0473L, 0x5DCD92L, 0x5D96F3L, 0x5D6095L, 0x5D2A76L, 0x5CF496L, 0x5CBEF2L, 0x5C898BL, 0x5C545EL, 0x5C1F6BL, 0x5BEAB0L, 0x5BB62DL, 0x5B81E1L, 0x5B4DCAL, 0x5B19E7L, 0x5AE638L, 0x5AB2BCL, 0x5A7F72L, 0x5A4C59L, 0x5A1970L, 0x59E6B6L, 0x59B42AL, 0x5981CCL, 0x594F9BL, 0x591D96L, 0x58EBBDL, 0x58BA0EL, 0x588889L, 0x58572DL, 0x5825FAL, 0x57F4EEL, 0x57C40AL, 0x57934DL, 0x5762B5L, 0x573243L, 0x5701F5L, 0x56D1CCL, 0x56A1C6L, 0x5671E4L, 0x564224L, 0x561285L, 0x55E309L, 0x55B3ADL, 0x558471L, 0x555555L, 0x552659L, 0x54F77BL, 0x54C8BCL, 0x549A1BL, 0x546B98L, 0x543D31L, 0x540EE7L, 0x53E0B9L, 0x53B2A7L, 0x5384B0L, 0x5356D4L, 0x532912L, 0x52FB6BL, 0x52CDDDL, 0x52A068L, 0x52730CL, 0x5245C9L, 0x52189EL, 0x51EB8BL, 0x51BE8FL, 0x5191AAL, 0x5164DCL, 0x513825L, 0x510B83L, 0x50DEF7L, 0x50B280L, 0x50861FL, 0x5059D2L, 0x502D99L, 0x500175L, 0x4FD564L, 0x4FA967L, 0x4F7D7DL, 0x4F51A6L, 0x4F25E2L, 0x4EFA30L, 0x4ECE90L, 0x4EA301L, 0x4E7784L, 0x4E4C19L, 0x4E20BEL, 0x4DF574L, 0x4DCA3AL, 0x4D9F10L, 0x4D73F6L, 0x4D48ECL, 0x4D1DF1L, 0x4CF305L, 0x4CC829L, 0x4C9D5AL, 0x4C729AL, 0x4C47E9L, 0x4C1D45L, 0x4BF2AEL, 0x4BC826L, 0x4B9DAAL, 0x4B733BL, 0x4B48D9L, 0x4B1E84L, 0x4AF43BL, 0x4AC9FEL, 0x4A9FCDL, 0x4A75A7L, 0x4A4B8DL, 0x4A217EL, 0x49F77AL, 0x49CD81L, 0x49A393L, 0x4979AFL, 0x494FD5L, 0x492605L, 0x48FC3FL, 0x48D282L, 0x48A8CFL, 0x487F25L, 0x485584L, 0x482BECL, 0x48025DL, 0x47D8D6L, 0x47AF57L, 0x4785E0L, 0x475C72L, 0x47330AL, 0x4709ABL, 0x46E052L, 0x46B701L, 0x468DB7L, 0x466474L, 0x463B37L, 0x461201L, 0x45E8D0L, 0x45BFA6L, 0x459682L, 0x456D64L, 0x45444BL, 0x451B37L, 0x44F229L, 0x44C920L, 0x44A01CL, 0x44771CL, 0x444E21L, 0x44252AL, 0x43FC38L, 0x43D349L, 0x43AA5FL, 0x438178L, 0x435894L, 0x432FB4L, 0x4306D8L, 0x42DDFEL, 0x42B527L, 0x428C53L, 0x426381L, 0x423AB2L, 0x4211E5L, 0x41E91AL, 0x41C051L, 0x41978AL, 0x416EC5L, 0x414601L, 0x411D3EL, 0x40F47CL, 0x40CBBBL, 0x40A2FBL, 0x407A3CL, 0x40517DL, 0x4028BEL, 0x400000L, 0x3FD742L, 0x3FAE83L, 0x3F85C4L, 0x3F5D05L, 0x3F3445L, 0x3F0B84L, 0x3EE2C2L, 0x3EB9FFL, 0x3E913BL, 0x3E6876L, 0x3E3FAFL, 0x3E16E6L, 0x3DEE1BL, 0x3DC54EL, 0x3D9C7FL, 0x3D73ADL, 0x3D4AD9L, 0x3D2202L, 0x3CF928L, 0x3CD04CL, 0x3CA76CL, 0x3C7E88L, 0x3C55A1L, 0x3C2CB7L, 0x3C03C8L, 0x3BDAD6L, 0x3BB1DFL, 0x3B88E4L, 0x3B5FE4L, 0x3B36E0L, 0x3B0DD7L, 0x3AE4C9L, 0x3ABBB5L, 0x3A929CL, 0x3A697EL, 0x3A405AL, 0x3A1730L, 0x39EDFFL, 0x39C4C9L, 0x399B8CL, 0x397249L, 0x3948FFL, 0x391FAEL, 0x38F655L, 0x38CCF6L, 0x38A38EL, 0x387A20L, 0x3850A9L, 0x38272AL, 0x37FDA3L, 0x37D414L, 0x37AA7CL, 0x3780DBL, 0x375731L, 0x372D7EL, 0x3703C1L, 0x36D9FBL, 0x36B02BL, 0x368651L, 0x365C6DL, 0x36327FL, 0x360886L, 0x35DE82L, 0x35B473L, 0x358A59L, 0x356033L, 0x353602L, 0x350BC5L, 0x34E17CL, 0x34B727L, 0x348CC5L, 0x346256L, 0x3437DAL, 0x340D52L, 0x33E2BBL, 0x33B817L, 0x338D66L, 0x3362A6L, 0x3337D7L, 0x330CFBL, 0x32E20FL, 0x32B714L, 0x328C0AL, 0x3260F0L, 0x3235C6L, 0x320A8CL, 0x31DF42L, 0x31B3E7L, 0x31887CL, 0x315CFFL, 0x313170L, 0x3105D0L, 0x30DA1EL, 0x30AE5AL, 0x308283L, 0x305699L, 0x302A9CL, 0x2FFE8BL, 0x2FD267L, 0x2FA62EL, 0x2F79E1L, 0x2F4D80L, 0x2F2109L, 0x2EF47DL, 0x2EC7DBL, 0x2E9B24L, 0x2E6E56L, 0x2E4171L, 0x2E1475L, 0x2DE762L, 0x2DBA37L, 0x2D8CF4L, 0x2D5F98L, 0x2D3223L, 0x2D0495L, 0x2CD6EEL, 0x2CA92CL, 0x2C7B50L, 0x2C4D59L, 0x2C1F47L, 0x2BF119L, 0x2BC2CFL, 0x2B9468L, 0x2B65E5L, 0x2B3744L, 0x2B0885L, 0x2AD9A7L, 0x2AAAABL, 0x2A7B8FL, 0x2A4C53L, 0x2A1CF7L, 0x29ED7BL, 0x29BDDCL, 0x298E1CL, 0x295E3AL, 0x292E34L, 0x28FE0BL, 0x28CDBDL, 0x289D4BL, 0x286CB3L, 0x283BF6L, 0x280B12L, 0x27DA06L, 0x27A8D3L, 0x277777L, 0x2745F2L, 0x271443L, 0x26E26AL, 0x26B065L, 0x267E34L, 0x264BD6L, 0x26194AL, 0x25E690L, 0x25B3A7L, 0x25808EL, 0x254D44L, 0x2519C8L, 0x24E619L, 0x24B236L, 0x247E1FL, 0x2449D3L, 0x241550L, 0x23E095L, 0x23ABA2L, 0x237675L, 0x23410EL, 0x230B6AL, 0x22D58AL, 0x229F6BL, 0x22690DL, 0x22326EL, 0x21FB8DL, 0x21C468L, 0x218CFFL, 0x215550L, 0x211D59L, 0x20E519L, 0x20AC8EL, 0x2073B7L, 0x203A92L, 0x20011DL, 0x1FC757L, 0x1F8D3DL, 0x1F52CFL, 0x1F1809L, 0x1EDCEAL, 0x1EA170L, 0x1E6598L, 0x1E2961L, 0x1DECC7L, 0x1DAFC9L, 0x1D7264L, 0x1D3496L, 0x1CF65BL, 0x1CB7B1L, 0x1C7895L, 0x1C3904L, 0x1BF8FAL, 0x1BB874L, 0x1B7770L, 0x1B35E8L, 0x1AF3DAL, 0x1AB141L, 0x1A6E19L, 0x1A2A5EL, 0x19E60BL, 0x19A11BL, 0x195B8AL, 0x191551L, 0x18CE6CL, 0x1886D4L, 0x183E83L, 0x17F573L, 0x17AB9BL, 0x1760F6L, 0x17157BL, 0x16C921L, 0x167BE0L, 0x162DAFL, 0x15DE82L, 0x158E4FL, 0x153D0BL, 0x14EAA8L, 0x14971AL, 0x144251L, 0x13EC3FL, 0x1394D1L, 0x133BF5L, 0x12E198L, 0x1285A2L, 0x1227FBL, 0x11C889L, 0x11672FL, 0x1103CAL, 0x109E37L, 0x10364BL, 0xFCBDAL, 0xF5EAEL, 0xEEE8CL, 0xE7B2DL, 0xE0444L, 0xD8971L, 0xD0A46L, 0xC863FL, 0xBFCBBL, 0xB6CF4L, 0xAD5F0L, 0xA366FL, 0x98CC6L, 0x8D6ADL, 0x810DBL, 0x73642L, 0x63E62L, 0x518A6L, 0x39A39L, 0x0L }; /* fixatan: * Fixed point inverse tangent. Does a binary search on the tan table. */ fixed fixatan(fixed x) { int a, b, c; /* for binary search */ fixed d; /* difference value for search */ if (x >= 0) { /* search the first part of tan table */ a = 0; b = 127; } else { /* search the second half instead */ a = 128; b = 255; } do { c = (a + b) >> 1; d = x - _tan_tbl[c]; if (d > 0) a = c + 1; else if (d < 0) b = c - 1; } while ((a <= b) && (d)); if (x >= 0) return ((long)c) << 15; return (-0x00800000L + (((long)c) << 15)); } /* fixatan2: * Like the libc atan2, but for fixed point numbers. */ fixed fixatan2(fixed y, fixed x) { fixed r; if (x==0) { if (y==0) { *allegro_errno = EDOM; return 0L; } else return ((y < 0) ? -0x00400000L : 0x00400000L); } *allegro_errno = 0; r = fixdiv(y, x); if (*allegro_errno) { *allegro_errno = 0; return ((y < 0) ? -0x00400000L : 0x00400000L); } r = fixatan(r); if (x >= 0) return r; if (y >= 0) return 0x00800000L + r; return r - 0x00800000L; } /* fixtorad_r, radtofix_r: * Ratios for converting between radians and fixed point angles. */ AL_CONST fixed fixtorad_r = (fixed)1608; /* 2pi/256 */ AL_CONST fixed radtofix_r = (fixed)2670177; /* 256/2pi */ #if (defined ALLEGRO_I386) && (!defined ALLEGRO_NO_ASM) unsigned short _sqrt_table[256] = { /* this table is used by the fixsqrt() and fixhypot() routines in imisc.s */ 0x2D4, 0x103F, 0x16CD, 0x1BDB, 0x201F, 0x23E3, 0x274B, 0x2A6D, 0x2D57, 0x3015, 0x32AC, 0x3524, 0x377F, 0x39C2, 0x3BEE, 0x3E08, 0x400F, 0x4207, 0x43F0, 0x45CC, 0x479C, 0x4960, 0x4B19, 0x4CC9, 0x4E6F, 0x500C, 0x51A2, 0x532F, 0x54B6, 0x5635, 0x57AE, 0x5921, 0x5A8D, 0x5BF4, 0x5D56, 0x5EB3, 0x600A, 0x615D, 0x62AB, 0x63F5, 0x653B, 0x667D, 0x67BA, 0x68F5, 0x6A2B, 0x6B5E, 0x6C8D, 0x6DBA, 0x6EE3, 0x7009, 0x712C, 0x724C, 0x7369, 0x7484, 0x759C, 0x76B1, 0x77C4, 0x78D4, 0x79E2, 0x7AEE, 0x7BF7, 0x7CFE, 0x7E04, 0x7F07, 0x8007, 0x8106, 0x8203, 0x82FF, 0x83F8, 0x84EF, 0x85E5, 0x86D9, 0x87CB, 0x88BB, 0x89AA, 0x8A97, 0x8B83, 0x8C6D, 0x8D56, 0x8E3D, 0x8F22, 0x9007, 0x90E9, 0x91CB, 0x92AB, 0x938A, 0x9467, 0x9543, 0x961E, 0x96F8, 0x97D0, 0x98A8, 0x997E, 0x9A53, 0x9B26, 0x9BF9, 0x9CCA, 0x9D9B, 0x9E6A, 0x9F39, 0xA006, 0xA0D2, 0xA19D, 0xA268, 0xA331, 0xA3F9, 0xA4C1, 0xA587, 0xA64D, 0xA711, 0xA7D5, 0xA898, 0xA95A, 0xAA1B, 0xAADB, 0xAB9A, 0xAC59, 0xAD16, 0xADD3, 0xAE8F, 0xAF4B, 0xB005, 0xB0BF, 0xB178, 0xB230, 0xB2E8, 0xB39F, 0xB455, 0xB50A, 0xB5BF, 0xB673, 0xB726, 0xB7D9, 0xB88A, 0xB93C, 0xB9EC, 0xBA9C, 0xBB4B, 0xBBFA, 0xBCA8, 0xBD55, 0xBE02, 0xBEAE, 0xBF5A, 0xC005, 0xC0AF, 0xC159, 0xC202, 0xC2AB, 0xC353, 0xC3FA, 0xC4A1, 0xC548, 0xC5ED, 0xC693, 0xC737, 0xC7DC, 0xC87F, 0xC923, 0xC9C5, 0xCA67, 0xCB09, 0xCBAA, 0xCC4B, 0xCCEB, 0xCD8B, 0xCE2A, 0xCEC8, 0xCF67, 0xD004, 0xD0A2, 0xD13F, 0xD1DB, 0xD277, 0xD312, 0xD3AD, 0xD448, 0xD4E2, 0xD57C, 0xD615, 0xD6AE, 0xD746, 0xD7DE, 0xD876, 0xD90D, 0xD9A4, 0xDA3A, 0xDAD0, 0xDB66, 0xDBFB, 0xDC90, 0xDD24, 0xDDB8, 0xDE4C, 0xDEDF, 0xDF72, 0xE004, 0xE096, 0xE128, 0xE1B9, 0xE24A, 0xE2DB, 0xE36B, 0xE3FB, 0xE48B, 0xE51A, 0xE5A9, 0xE637, 0xE6C5, 0xE753, 0xE7E1, 0xE86E, 0xE8FB, 0xE987, 0xEA13, 0xEA9F, 0xEB2B, 0xEBB6, 0xEC41, 0xECCB, 0xED55, 0xEDDF, 0xEE69, 0xEEF2, 0xEF7B, 0xF004, 0xF08C, 0xF114, 0xF19C, 0xF223, 0xF2AB, 0xF332, 0xF3B8, 0xF43E, 0xF4C4, 0xF54A, 0xF5D0, 0xF655, 0xF6DA, 0xF75E, 0xF7E3, 0xF867, 0xF8EA, 0xF96E, 0xF9F1, 0xFA74, 0xFAF7, 0xFB79, 0xFBFB, 0xFC7D, 0xFCFF, 0xFD80, 0xFE02, 0xFE82, 0xFF03, 0xFF83 }; #else /* not i386, so use straight C versions */ /* fixsqrt: * Fixed point square root routine for non-i386. */ fixed fixsqrt(fixed x) { if (x > 0) return ftofix(sqrt(fixtof(x))); if (x < 0) *allegro_errno = EDOM; return 0; } /* fixhypot: * Fixed point sqrt (x*x+y*y) for non-i386. */ fixed fixhypot(fixed x, fixed y) { return ftofix(hypot(fixtof(x), fixtof(y))); } #endif /* i386 vs. portable C implementations */ allegro-4.4.3.1/src/file.c0000664000175000017500000021673413437077643014167 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * File I/O. * * By Shawn Hargreaves. * * _pack_fdopen() and related modifications by Annie Testes. * * Evert Glebbeek added the support for relative filenames: * make_absolute_filename(), make_relative_filename() and * is_relative_filename(). * * Peter Wang added support for packfile vtables. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #ifndef ALLEGRO_MPW #include #endif #ifdef ALLEGRO_UNIX #include /* for tilde expansion */ #endif #ifdef ALLEGRO_WINDOWS #include "winalleg.h" /* for GetTempPath */ #endif #ifndef O_BINARY #define O_BINARY 0 #endif /* permissions to use when opening files */ #ifndef ALLEGRO_MPW /* some OSes have no concept of "group" and "other" */ #ifndef S_IRGRP #define S_IRGRP 0 #define S_IWGRP 0 #endif #ifndef S_IROTH #define S_IROTH 0 #define S_IWOTH 0 #endif #define OPEN_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) #endif /* !ALLEGRO_MPW */ static char the_password[256] = EMPTY_STRING; int _packfile_filesize = 0; int _packfile_datasize = 0; int _packfile_type = 0; static PACKFILE_VTABLE normal_vtable; static PACKFILE *pack_fopen_special_file(AL_CONST char *filename, AL_CONST char *mode); static int filename_encoding = U_ASCII; #define FA_DAT_FLAGS (FA_RDONLY | FA_ARCH) typedef struct RESOURCE_PATH { int priority; char path[1024]; struct RESOURCE_PATH *next; } RESOURCE_PATH; static RESOURCE_PATH *resource_path_list = NULL; static void destroy_resource_path_list(void); /*************************************************** ****************** Path handling ****************** ***************************************************/ /* fix_filename_case: * Converts filename to upper case. */ char *fix_filename_case(char *filename) { ASSERT(filename); if (!ALLEGRO_LFN) ustrupr(filename); return filename; } /* fix_filename_slashes: * Converts '/' or '\' to system specific path separator. */ char *fix_filename_slashes(char *filename) { int pos, c; ASSERT(filename); for (pos=0; ugetc(filename+pos); pos+=uwidth(filename+pos)) { c = ugetc(filename+pos); if ((c == '/') || (c == '\\')) usetat(filename+pos, 0, OTHER_PATH_SEPARATOR); } return filename; } /* Canonicalize_filename: * Returns the canonical form of the specified filename, i.e. the * minimal absolute filename describing the same file. */ char *canonicalize_filename(char *dest, AL_CONST char *filename, int size) { int saved_errno = errno; char buf[1024], buf2[1024]; char *p; int pos = 0; int drive = -1; int c1, i; ASSERT(dest); ASSERT(filename); ASSERT(size >= 0); #if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0') /* check whether we have a drive letter */ c1 = utolower(ugetc(filename)); if ((c1 >= 'a') && (c1 <= 'z')) { int c2 = ugetat(filename, 1); if (c2 == DEVICE_SEPARATOR) { drive = c1 - 'a'; filename += uwidth(filename); filename += uwidth(filename); } } /* if not, use the current drive */ if (drive < 0) drive = _al_getdrive(); pos += usetc(buf+pos, drive+'a'); pos += usetc(buf+pos, DEVICE_SEPARATOR); #endif #ifdef ALLEGRO_UNIX /* if the filename starts with ~ then it's relative to a home directory */ if ((ugetc(filename) == '~')) { AL_CONST char *tail = filename + uwidth(filename); /* could be the username */ char *home = NULL; /* their home directory */ if (ugetc(tail) == '/' || !ugetc(tail)) { /* easy */ home = getenv("HOME"); if (home) home = _al_strdup(home); } else { /* harder */ char *username = (char *)tail, *ascii_username, *ch; int userlen; struct passwd *pwd; /* find the end of the username */ tail = ustrchr(username, '/'); if (!tail) tail = ustrchr(username, '\0'); /* this ought to be the ASCII length, but I can't see a Unicode * function to return the difference in characters between two * pointers. This code is safe on the assumption that ASCII is * the most efficient encoding, but wasteful of memory */ userlen = tail - username + ucwidth('\0'); ascii_username = _AL_MALLOC_ATOMIC(userlen); if (ascii_username) { /* convert the username to ASCII, find the password entry, * and copy their home directory. */ do_uconvert(username, U_CURRENT, ascii_username, U_ASCII, userlen); if ((ch = strchr(ascii_username, '/'))) *ch = '\0'; setpwent(); while (((pwd = getpwent()) != NULL) && (strcmp(pwd->pw_name, ascii_username) != 0)) ; _AL_FREE(ascii_username); if (pwd) home = _al_strdup(pwd->pw_dir); endpwent(); } } /* If we got a home directory, prepend it to the filename. Otherwise * we leave the filename alone, like bash but not tcsh; bash is better * anyway. :) */ if (home) { do_uconvert(home, U_ASCII, buf+pos, U_CURRENT, sizeof(buf)-pos); _AL_FREE(home); pos = ustrsize(buf); filename = tail; goto no_relativisation; } } #endif /* Unix */ /* if the filename is relative, make it absolute */ if ((ugetc(filename) != '/') && (ugetc(filename) != OTHER_PATH_SEPARATOR) && (ugetc(filename) != '#')) { _al_getdcwd(drive, buf2, sizeof(buf2) - ucwidth(OTHER_PATH_SEPARATOR)); put_backslash(buf2); p = buf2; if ((utolower(p[0]) >= 'a') && (utolower(p[0]) <= 'z') && (p[1] == DEVICE_SEPARATOR)) p += 2; ustrzcpy(buf+pos, sizeof(buf)-pos, p); pos = ustrsize(buf); } #ifdef ALLEGRO_UNIX no_relativisation: #endif /* add our filename, and clean it up a bit */ ustrzcpy(buf+pos, sizeof(buf)-pos, filename); fix_filename_case(buf); fix_filename_slashes(buf); /* remove duplicate slashes */ pos = usetc(buf2, OTHER_PATH_SEPARATOR); pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); usetc(buf2+pos, 0); while ((p = ustrstr(buf, buf2)) != NULL) uremove(p, 0); /* remove /./ patterns */ pos = usetc(buf2, OTHER_PATH_SEPARATOR); pos += usetc(buf2+pos, '.'); pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); usetc(buf2+pos, 0); while ((p = ustrstr(buf, buf2)) != NULL) { uremove(p, 0); uremove(p, 0); } /* collapse /../ patterns */ pos = usetc(buf2, OTHER_PATH_SEPARATOR); pos += usetc(buf2+pos, '.'); pos += usetc(buf2+pos, '.'); pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); usetc(buf2+pos, 0); while ((p = ustrstr(buf, buf2)) != NULL) { for (i=0; buf+uoffset(buf, i) < p; i++) ; while (--i > 0) { c1 = ugetat(buf, i); if (c1 == OTHER_PATH_SEPARATOR) break; if (c1 == DEVICE_SEPARATOR) { i++; break; } } if (i < 0) i = 0; p += ustrsize(buf2); memmove(buf+uoffset(buf, i+1), p, ustrsizez(p)); } /* all done! */ ustrzcpy(dest, size, buf); errno = saved_errno; return dest; } /* make_absolute_filename: * Makes the absolute filename corresponding to the specified relative * filename using the specified base (PATH is absolute and represents * the base, FILENAME is the relative filename), stores it in DEST * whose size in bytes is SIZE and returns a pointer to it. * It does not append '/' to the path. */ char *make_absolute_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) { char tmp[1024]; ASSERT(dest); ASSERT(path); ASSERT(filename); ASSERT(size >= 0); replace_filename(tmp, path, filename, sizeof(tmp)); canonicalize_filename(dest, tmp, size); return dest; } /* make_relative_filename: * Makes the relative filename corresponding to the specified absolute * filename using the specified base (PATH is absolute and represents * the base, FILENAME is the absolute filename), stores it in DEST * whose size in bytes is SIZE and returns a pointer to it, or returns * NULL if it cannot do so. * It does not append '/' to the path. */ char *make_relative_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) { char *my_path, *my_filename; char *reduced_path = NULL, *reduced_filename = NULL; char *p1, *p2; int c, c1, c2, pos; ASSERT(dest); ASSERT(path); ASSERT(filename); ASSERT(size >= 0); /* The first check under DOS/Windows would be for the drive: since the * paths are absolute, they will always contain a drive letter. Do this * check under Unix too where the first character should always be '/' * in order not to screw up existing DOS/Windows paths. */ if (ugetc(path) != ugetc(filename)) return NULL; my_path = _al_ustrdup(path); if (!my_path) return NULL; my_filename = _al_ustrdup(filename); if (!my_filename) { _AL_FREE(my_path); return NULL; } /* Strip the filenames to keep only the directories. */ usetc(get_filename(my_path), 0); usetc(get_filename(my_filename), 0); /* Both paths are on the same device. There are three cases: * - the filename is a "child" of the path in the directory tree, * - the filename is a "brother" of the path, * - the filename is only a "cousin" of the path. * In the two former cases, we will only need to keep a suffix of the * filename. In the latter case, we will need to back-paddle through * the directory tree. */ p1 = my_path; p2 = my_filename; while (((c1=ugetx(&p1)) == (c2=ugetx(&p2))) && c1 && c2) { if ((c1 == '/') || (c1 == OTHER_PATH_SEPARATOR)) { reduced_path = p1; reduced_filename = p2; } } if (!c1) { /* If the path is exhausted, we are in one of the two former cases. */ if (!c2) { /* If the filename is also exhausted, we are in the second case. * Prepend './' to the reduced filename. */ pos = usetc(dest, '.'); pos += usetc(dest+pos, OTHER_PATH_SEPARATOR); usetc(dest+pos, 0); } else { /* Otherwise we are in the first case. Nothing to do. */ usetc(dest, 0); } } else { /* Bail out if previously something went wrong (eg. user supplied * paths are not canonical and we can't understand them). */ if (!reduced_path) { _AL_FREE(my_path); _AL_FREE(my_filename); return NULL; } /* Otherwise, we are in the latter case and need to count the number * of remaining directories in the reduced path and prepend the same * number of '../' to the reduced filename. */ pos = 0; while ((c=ugetx(&reduced_path))) { if ((c == '/') || (c == OTHER_PATH_SEPARATOR)) { pos += usetc(dest+pos, '.'); pos += usetc(dest+pos, '.'); pos += usetc(dest+pos, OTHER_PATH_SEPARATOR); } } usetc(dest+pos, 0); } /* Bail out if previously something went wrong (eg. user supplied * paths are not canonical and we can't understand them). */ if (!reduced_filename) { _AL_FREE(my_path); _AL_FREE(my_filename); return NULL; } ustrzcat(dest, size, reduced_filename); ustrzcat(dest, size, get_filename(filename)); _AL_FREE(my_path); _AL_FREE(my_filename); /* Harmonize path separators. */ return fix_filename_slashes(dest); } /* is_relative_filename: * Checks whether the specified filename is relative. */ int is_relative_filename(AL_CONST char *filename) { ASSERT(filename); /* All filenames that start with a '.' are relative. */ if (ugetc(filename) == '.') return TRUE; /* Filenames that contain a device separator (DOS/Windows) * or start with a '/' (Unix) are considered absolute. */ #if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) if (ustrchr(filename, DEVICE_SEPARATOR)) return FALSE; #endif if ((ugetc(filename) == '/') || (ugetc(filename) == OTHER_PATH_SEPARATOR)) return FALSE; return TRUE; } /* replace_filename: * Replaces filename in path with different one. * It does not append '/' to the path. */ char *replace_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) { char tmp[1024]; int pos, c; ASSERT(dest); ASSERT(path); ASSERT(filename); ASSERT(size >= 0); pos = ustrlen(path); while (pos>0) { c = ugetat(path, pos-1); if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) break; pos--; } ustrzncpy(tmp, sizeof(tmp), path, pos); ustrzcat(tmp, sizeof(tmp), filename); ustrzcpy(dest, size, tmp); return dest; } /* replace_extension: * Replaces extension in filename with different one. * It appends '.' if it is not present in the filename. */ char *replace_extension(char *dest, AL_CONST char *filename, AL_CONST char *ext, int size) { char tmp[1024], tmp2[16]; int pos, end, c; ASSERT(dest); ASSERT(filename); ASSERT(ext); ASSERT(size >= 0); pos = end = ustrlen(filename); while (pos>0) { c = ugetat(filename, pos-1); if ((c == '.') || (c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) break; pos--; } if (ugetat(filename, pos-1) == '.') end = pos-1; ustrzncpy(tmp, sizeof(tmp), filename, end); ustrzcat(tmp, sizeof(tmp), uconvert_ascii(".", tmp2)); ustrzcat(tmp, sizeof(tmp), ext); ustrzcpy(dest, size, tmp); return dest; } /* append_filename: * Append filename to path, adding separator if necessary. */ char *append_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) { char tmp[1024]; int pos, c; ASSERT(dest); ASSERT(path); ASSERT(filename); ASSERT(size >= 0); ustrzcpy(tmp, sizeof(tmp), path); pos = ustrlen(tmp); if ((pos > 0) && (uoffset(tmp, pos) < ((int)sizeof(tmp) - ucwidth(OTHER_PATH_SEPARATOR) - ucwidth(0)))) { c = ugetat(tmp, pos-1); if ((c != '/') && (c != OTHER_PATH_SEPARATOR) && (c != DEVICE_SEPARATOR)) { pos = uoffset(tmp, pos); pos += usetc(tmp+pos, OTHER_PATH_SEPARATOR); usetc(tmp+pos, 0); } } ustrzcat(tmp, sizeof(tmp), filename); ustrzcpy(dest, size, tmp); return dest; } /* get_filename: * When passed a completely specified file path, this returns a pointer * to the filename portion. Both '\' and '/' are recognized as directory * separators. */ char *get_filename(AL_CONST char *path) { int c; const char *ptr, *ret; ASSERT(path); ptr = path; ret = ptr; for (;;) { c = ugetxc(&ptr); if (!c) break; if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) ret = (char*)ptr; } return (char*)ret; } /* get_extension: * When passed a complete filename (with or without path information) * this returns a pointer to the file extension. */ char *get_extension(AL_CONST char *filename) { int pos, c; ASSERT(filename); pos = ustrlen(filename); while (pos>0) { c = ugetat(filename, pos-1); if ((c == '.') || (c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) break; pos--; } if ((pos>0) && (ugetat(filename, pos-1) == '.')) return (char *)filename + uoffset(filename, pos); return (char *)filename + ustrsize(filename); } /* put_backslash: * If the last character of the filename is not a \, /, or #, or a device * separator (eg. : under DOS), this routine will concatenate a \ or / on * to it (depending on platform). */ void put_backslash(char *filename) { int c; ASSERT(filename); if (ugetc(filename)) { c = ugetat(filename, -1); if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR) || (c == '#')) return; } filename += ustrsize(filename); filename += usetc(filename, OTHER_PATH_SEPARATOR); usetc(filename, 0); } /*************************************************** ******************* Filesystem ******************** ***************************************************/ /* set_filename_encoding: * Sets the encoding to use for filenames. By default, UTF8 is assumed. */ void set_filename_encoding(int encoding) { filename_encoding = encoding; } /* get_filename_encoding: * Returns the encoding currently assumed for filenames. */ int get_filename_encoding(void) { return filename_encoding ; } /* file_exists: * Checks whether a file matching the given name and attributes exists, * returning non zero if it does. The file attribute may contain any of * the FA_* constants from dir.h. If aret is not null, it will be set * to the attributes of the matching file. If an error occurs the system * error code will be stored in errno. */ int file_exists(AL_CONST char *filename, int attrib, int *aret) { struct al_ffblk info; ASSERT(filename); if (ustrchr(filename, '#')) { PACKFILE *f = pack_fopen_special_file(filename, F_READ); if (f) { pack_fclose(f); if (aret) *aret = FA_DAT_FLAGS; return ((attrib & FA_DAT_FLAGS) == FA_DAT_FLAGS) ? TRUE : FALSE; } } if (!_al_file_isok(filename)) return FALSE; if (al_findfirst(filename, &info, attrib) != 0) { /* no entry is not an error for file_exists() */ if (*allegro_errno == ENOENT) *allegro_errno = 0; return FALSE; } al_findclose(&info); if (aret) *aret = info.attrib; return TRUE; } /* exists: * Shortcut version of file_exists(). */ int exists(AL_CONST char *filename) { ASSERT(filename); return file_exists(filename, FA_ARCH | FA_RDONLY, NULL); } /* file_size_ex: * Returns the size of a file, in bytes. * If the file does not exist or an error occurs, it will return zero * and store the system error code in errno. */ uint64_t file_size_ex(AL_CONST char *filename) { ASSERT(filename); if (ustrchr(filename, '#')) { PACKFILE *f = pack_fopen_special_file(filename, F_READ); if (f) { long ret; ASSERT(f->is_normal_packfile); ret = f->normal.todo; pack_fclose(f); return ret; } } if (!_al_file_isok(filename)) return 0; return _al_file_size_ex(filename); } /* For binary compatibility with 4.2.0. */ long file_size(AL_CONST char *filename) { return file_size_ex(filename); } /* For binary compatibility with 4.2.0. * This is an internal symbol and only required because _al_file_size was * exposed in the Windows DLL. */ long _al_file_size(AL_CONST char *filename) { return _al_file_size_ex(filename); } /* file_time: * Returns a file time-stamp. * If the file does not exist or an error occurs, it will return zero * and store the system error code in errno. */ time_t file_time(AL_CONST char *filename) { ASSERT(filename); if (!_al_file_isok(filename)) return 0; return _al_file_time(filename); } /* delete_file: * Removes a file from the disk. */ int delete_file(AL_CONST char *filename) { char tmp[1024]; ASSERT(filename); if (!_al_file_isok(filename)) return -1; if (_al_unlink(uconvert_tofilename(filename, tmp)) != 0) { *allegro_errno = errno; return -1; } return 0; } /* for_each_file: * Finds all the files on the disk which match the given wildcard * specification and file attributes, and executes callback() once for * each. callback() will be passed three arguments, the first a string * which contains the completed filename, the second being the attributes * of the file, and the third an int which is simply a copy of param (you * can use this for whatever you like). If an error occurs an error code * will be stored in errno, and callback() can cause for_each_file() to * abort by setting errno itself. Returns the number of successful calls * made to callback(). The file attribute may contain any of the FA_* * flags from dir.h. */ int for_each_file(AL_CONST char *name, int attrib, void (*callback)(AL_CONST char *filename, int attrib, int param), int param) { char buf[1024]; struct al_ffblk info; int c = 0; ASSERT(name); if (!_al_file_isok(name)) return 0; if (al_findfirst(name, &info, attrib) != 0) { /* no entry is not an error for for_each_file() */ if (*allegro_errno == ENOENT) *allegro_errno = 0; return 0; } *allegro_errno = 0; do { replace_filename(buf, name, info.name, sizeof(buf)); (*callback)(buf, info.attrib, param); if (*allegro_errno) /* evil, evil, evil! */ break; c++; } while (al_findnext(&info) == 0); al_findclose(&info); /* no entry is not an error for for_each_file() */ if (*allegro_errno == ENOENT) *allegro_errno = 0; return c; } /* for_each_file_ex: * Finds all the files on disk which match the given wildcard specification * and file attributes, and executes callback() once for each. callback() * will be passed three arguments: the first is a string which contains the * completed filename, the second is the actual attributes of the file, and * the third is a void pointer which is simply a copy of param (you can use * this for whatever you like). It must return 0 to let the enumeration * proceed, or any non-zero value to stop it. If an error occurs, the error * code will be stored in errno but the enumeration won't stop. Returns the * number of successful calls made to callback(), that is the number of * times callback() was called and returned 0. The file attribute masks may * contain any of the FA_* flags from dir.h. */ int for_each_file_ex(AL_CONST char *name, int in_attrib, int out_attrib, int (*callback)(AL_CONST char *filename, int attrib, void *param), void *param) { char buf[1024]; struct al_ffblk info; int ret, c = 0; ASSERT(name); if (!_al_file_isok(name)) return 0; if (al_findfirst(name, &info, ~out_attrib) != 0) { /* no entry is not an error for for_each_file_ex() */ if (*allegro_errno == ENOENT) *allegro_errno = 0; return 0; } do { if ((~info.attrib & in_attrib) == 0) { replace_filename(buf, name, info.name, sizeof(buf)); ret = (*callback)(buf, info.attrib, param); if (ret != 0) break; c++; } } while (al_findnext(&info) == 0); al_findclose(&info); /* no entry is not an error for for_each_file_ex() */ if (*allegro_errno == ENOENT) *allegro_errno = 0; return c; } /* find_resource: * Tries lots of different places that a resource file might live. */ static int find_resource(char *dest, AL_CONST char *path, AL_CONST char *name, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *subdir, int size) { char _name[128], _objectname[128], hash[8]; char tmp[16]; int i; /* convert from name.ext to name_ext (datafile object name format) */ ustrzcpy(_name, sizeof(_name), name); for (i=0; ipriority > priority) { prior_node = node; node = node->next; } if (path) { if (node && priority == node->priority) new_node = node; else { new_node = _AL_MALLOC(sizeof(RESOURCE_PATH)); if (!new_node) return 0; new_node->priority = priority; if (prior_node) { prior_node->next = new_node; new_node->next = node; } else { new_node->next = resource_path_list; resource_path_list = new_node; } if (!resource_path_list->next) _add_exit_func(destroy_resource_path_list, "destroy_resource_path_list"); } ustrzcpy(new_node->path, sizeof(new_node->path) - ucwidth(OTHER_PATH_SEPARATOR), path); fix_filename_slashes(new_node->path); put_backslash(new_node->path); } else { if (node && node->priority == priority) { if (prior_node) prior_node->next = node->next; else resource_path_list = node->next; _AL_FREE(node); if (!resource_path_list) _remove_exit_func(destroy_resource_path_list); } else return 0; } return 1; } static void destroy_resource_path_list(void) { RESOURCE_PATH *node = resource_path_list; if (node) _remove_exit_func(destroy_resource_path_list); while (node) { resource_path_list = node->next; _AL_FREE(node); node = resource_path_list; } } /* find_allegro_resource: * Searches for a support file, eg. allegro.cfg or language.dat. Passed * a resource string describing what you are looking for, along with * extra optional information such as the default extension, what datafile * to look inside, what the datafile object name is likely to be, any * special environment variable to check, and any subdirectory that you * would like to check as well as the default location, this function * looks in a hell of a lot of different places :-) Returns zero on * success, and stores a full path to the file (at most size bytes) in * the dest parameter. */ int find_allegro_resource(char *dest, AL_CONST char *resource, AL_CONST char *ext, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *envvar, AL_CONST char *subdir, int size) { int (*sys_find_resource)(char *, AL_CONST char *, int); char rname[128], path[1024], tmp[128]; char *s; int i, c; RESOURCE_PATH *rp_list_node = resource_path_list; ASSERT(dest); /* if the resource is a path with no filename, look in that location */ if ((resource) && (ugetc(resource)) && (!ugetc(get_filename(resource)))) return find_resource(dest, resource, empty_string, datafile, objectname, subdir, size); /* if we have a path+filename, just use it directly */ if ((resource) && (ustrpbrk(resource, uconvert_ascii("\\/#", tmp)))) { if (file_exists(resource, FA_RDONLY | FA_ARCH, NULL)) { ustrzcpy(dest, size, resource); /* if the resource is a datafile, try looking inside it */ if ((ustricmp(get_extension(dest), uconvert_ascii("dat", tmp)) == 0) && (objectname)) { ustrzcat(dest, size, uconvert_ascii("#", tmp)); for (i=0; ipath, rname, datafile, objectname, subdir, size) == 0) return 0; rp_list_node = rp_list_node->next; } /* try looking in the same directory as the program */ get_executable_name(path, sizeof(path)); usetc(get_filename(path), 0); if (find_resource(dest, path, rname, datafile, objectname, subdir, size) == 0) return 0; /* try the ALLEGRO environment variable */ s = getenv("ALLEGRO"); if (s) { do_uconvert(s, U_ASCII, path, U_CURRENT, sizeof(path)-ucwidth(OTHER_PATH_SEPARATOR)); put_backslash(path); if (find_resource(dest, path, rname, datafile, objectname, subdir, size) == 0) return 0; } /* try any extra environment variable that the parameters say to use */ if (envvar) { s = getenv(uconvert_tofilename(envvar, tmp)); if (s) { do_uconvert(s, U_ASCII, path, U_CURRENT, sizeof(path)-ucwidth(OTHER_PATH_SEPARATOR)); put_backslash(path); if (find_resource(dest, path, rname, datafile, objectname, subdir, size) == 0) return 0; } } /* ask the system driver */ if (system_driver) sys_find_resource = system_driver->find_resource; else sys_find_resource = NULL; if (sys_find_resource) { if ((ugetc(rname)) && (sys_find_resource(dest, (char *)rname, size) == 0)) return 0; if ((datafile) && ((ugetc(rname)) || (objectname)) && (sys_find_resource(path, (char *)datafile, sizeof(path)) == 0)) { if (!ugetc(rname)) ustrzcpy(rname, sizeof(rname), objectname); for (i=0; iis_normal_packfile); /* seek to the end and check for the magic number */ pack_fseek(f, f->normal.todo-8); if (pack_mgetl(f) != F_EXE_MAGIC) { pack_fclose(f); *allegro_errno = ENOTDIR; return NULL; } size = pack_mgetl(f); /* rewind */ pack_fclose(f); f = pack_fopen(exe_name, F_READ); if (!f) return NULL; /* seek to the start of the appended data */ pack_fseek(f, f->normal.todo-size); f = pack_fopen_chunk(f, FALSE); if (f) f->normal.flags |= PACKFILE_FLAG_EXEDAT; return f; } /* pack_fopen_datafile_object: * Recursive helper to handle opening member objects from datafiles, * given a fake filename in the form 'object_name[/nestedobject]'. */ static PACKFILE *pack_fopen_datafile_object(PACKFILE *f, AL_CONST char *objname) { char buf[512]; /* text is read into buf as UTF-8 */ char tmp[512*4]; /* this should be enough even when expanding to UCS-4 */ char name[512]; int use_next = FALSE; int recurse = FALSE; int type, size, pos, c; /* split up the object name */ pos = 0; while ((c = ugetxc(&objname)) != 0) { if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR)) { recurse = TRUE; break; } pos += usetc(name+pos, c); } usetc(name+pos, 0); pack_mgetl(f); /* search for the requested object */ while (!pack_feof(f)) { type = pack_mgetl(f); if (type == DAT_PROPERTY) { type = pack_mgetl(f); size = pack_mgetl(f); if (type == DAT_NAME) { /* examine name property */ pack_fread(buf, size, f); buf[size] = 0; if (ustricmp(uconvert(buf, U_UTF8, tmp, U_CURRENT, sizeof tmp), name) == 0) use_next = TRUE; } else { /* skip property */ pack_fseek(f, size); } } else { if (use_next) { /* found it! */ if (recurse) { if (type == DAT_FILE) return pack_fopen_datafile_object(pack_fopen_chunk(f, FALSE), objname); else break; } else { _packfile_type = type; return pack_fopen_chunk(f, FALSE); } } else { /* skip unwanted object */ size = pack_mgetl(f); pack_fseek(f, size+4); } } } /* oh dear, the object isn't there... */ pack_fclose(f); *allegro_errno = ENOENT; return NULL; } /* pack_fopen_special_file: * Helper to handle opening psuedo-files, ie. datafile objects and data * that has been appended to the end of the executable. */ static PACKFILE *pack_fopen_special_file(AL_CONST char *filename, AL_CONST char *mode) { char fname[1024], objname[512], tmp[16]; PACKFILE *f; char *p; int c; /* special files are read-only */ while ((c = *(mode++)) != 0) { if ((c == 'w') || (c == 'W')) { *allegro_errno = EROFS; return NULL; } } if (ustrcmp(filename, uconvert_ascii("#", tmp)) == 0) { /* read appended executable data */ return pack_fopen_exe_file(); } else { if (ugetc(filename) == '#') { /* read object from an appended datafile */ ustrzcpy(fname, sizeof(fname), uconvert_ascii("#", tmp)); ustrzcpy(objname, sizeof(objname), filename+uwidth(filename)); } else { /* read object from a regular datafile */ ustrzcpy(fname, sizeof(fname), filename); p = ustrrchr(fname, '#'); usetat(p, 0, 0); ustrzcpy(objname, sizeof(objname), p+uwidth(p)); } /* open the file */ f = pack_fopen(fname, F_READ_PACKED); if (!f) return NULL; if (pack_mgetl(f) != DAT_MAGIC) { pack_fclose(f); *allegro_errno = ENOTDIR; return NULL; } /* find the required object */ return pack_fopen_datafile_object(f, objname); } } /* packfile_password: * Sets the password to be used by all future read/write operations. * This only affects "normal" PACKFILEs, i.e. ones not using user-supplied * packfile vtables. */ void packfile_password(AL_CONST char *password) { int i = 0; int c; if (password) { while ((c = ugetxc(&password)) != 0) { the_password[i++] = c; if (i >= (int)sizeof(the_password)-1) break; } } the_password[i] = 0; } /* encrypt_id: * Helper for encrypting magic numbers, using the current password. */ static int32_t encrypt_id(long x, int new_format) { int32_t mask = 0; int i, pos; if (the_password[0]) { for (i=0; the_password[i]; i++) mask ^= ((int32_t)the_password[i] << ((i&3) * 8)); for (i=0, pos=0; i<4; i++) { mask ^= (int32_t)the_password[pos++] << (24-i*8); if (!the_password[pos]) pos = 0; } if (new_format) mask ^= 42; } return x ^ mask; } /* clone_password: * Sets up a local password string for use by this packfile. */ static int clone_password(PACKFILE *f) { ASSERT(f); ASSERT(f->is_normal_packfile); if (the_password[0]) { if ((f->normal.passdata = _AL_MALLOC_ATOMIC(strlen(the_password)+1)) == NULL) { *allegro_errno = ENOMEM; return FALSE; } _al_sane_strncpy(f->normal.passdata, the_password, strlen(the_password)+1); f->normal.passpos = f->normal.passdata; } else { f->normal.passpos = NULL; f->normal.passdata = NULL; } return TRUE; } /* create_packfile: * Helper function for creating a PACKFILE structure. */ static PACKFILE *create_packfile(int is_normal_packfile) { PACKFILE *f; if (is_normal_packfile) f = _AL_MALLOC(sizeof(PACKFILE)); else f = _AL_MALLOC(sizeof(PACKFILE) - sizeof(struct _al_normal_packfile_details)); if (f == NULL) { *allegro_errno = ENOMEM; return NULL; } if (!is_normal_packfile) { f->vtable = NULL; f->userdata = NULL; f->is_normal_packfile = FALSE; } else { f->vtable = &normal_vtable; f->userdata = f; f->is_normal_packfile = TRUE; f->normal.buf_pos = f->normal.buf; f->normal.flags = 0; f->normal.buf_size = 0; f->normal.filename = NULL; f->normal.passdata = NULL; f->normal.passpos = NULL; f->normal.parent = NULL; f->normal.pack_data = NULL; f->normal.unpack_data = NULL; f->normal.todo = 0; } return f; } /* free_packfile: * Helper function for freeing the PACKFILE struct. */ static void free_packfile(PACKFILE *f) { if (f) { /* These are no longer the responsibility of this function, but * these assertions help catch instances of old code which still * rely on the old behaviour. */ if (f->is_normal_packfile) { ASSERT(!f->normal.pack_data); ASSERT(!f->normal.unpack_data); ASSERT(!f->normal.passdata); ASSERT(!f->normal.passpos); } _AL_FREE(f); } } /* _pack_fdopen: * Converts the given file descriptor into a PACKFILE. The mode can have * the same values as for pack_fopen() and must be compatible with the * mode of the file descriptor. Unlike the libc fdopen(), pack_fdopen() * is unable to convert an already partially read or written file (i.e. * the file offset must be 0). * On success, it returns a pointer to a file structure, and on error it * returns NULL and stores an error code in errno. An attempt to read * a normal file in packed mode will cause errno to be set to EDOM. */ PACKFILE *_pack_fdopen(int fd, AL_CONST char *mode) { PACKFILE *f, *f2; long header = FALSE; int c; if ((f = create_packfile(TRUE)) == NULL) return NULL; ASSERT(f->is_normal_packfile); while ((c = *(mode++)) != 0) { switch (c) { case 'r': case 'R': f->normal.flags &= ~PACKFILE_FLAG_WRITE; break; case 'w': case 'W': f->normal.flags |= PACKFILE_FLAG_WRITE; break; case 'p': case 'P': f->normal.flags |= PACKFILE_FLAG_PACK; break; case '!': f->normal.flags &= ~PACKFILE_FLAG_PACK; header = TRUE; break; } } if (f->normal.flags & PACKFILE_FLAG_WRITE) { if (f->normal.flags & PACKFILE_FLAG_PACK) { /* write a packed file */ f->normal.pack_data = create_lzss_pack_data(); ASSERT(!f->normal.unpack_data); if (!f->normal.pack_data) { free_packfile(f); return NULL; } if ((f->normal.parent = _pack_fdopen(fd, F_WRITE)) == NULL) { free_lzss_pack_data(f->normal.pack_data); f->normal.pack_data = NULL; free_packfile(f); return NULL; } pack_mputl(encrypt_id(F_PACK_MAGIC, TRUE), f->normal.parent); f->normal.todo = 4; } else { /* write a 'real' file */ if (!clone_password(f)) { free_packfile(f); return NULL; } f->normal.hndl = fd; f->normal.todo = 0; errno = 0; if (header) pack_mputl(encrypt_id(F_NOPACK_MAGIC, TRUE), f); } } else { if (f->normal.flags & PACKFILE_FLAG_PACK) { /* read a packed file */ f->normal.unpack_data = create_lzss_unpack_data(); ASSERT(!f->normal.pack_data); if (!f->normal.unpack_data) { free_packfile(f); return NULL; } if ((f->normal.parent = _pack_fdopen(fd, F_READ)) == NULL) { free_lzss_unpack_data(f->normal.unpack_data); f->normal.unpack_data = NULL; free_packfile(f); return NULL; } header = pack_mgetl(f->normal.parent); if ((f->normal.parent->normal.passpos) && ((header == encrypt_id(F_PACK_MAGIC, FALSE)) || (header == encrypt_id(F_NOPACK_MAGIC, FALSE)))) { /* duplicate the file descriptor */ int fd2 = dup(fd); if (fd2<0) { pack_fclose(f->normal.parent); free_packfile(f); *allegro_errno = errno; return NULL; } /* close the parent file (logically, not physically) */ pack_fclose(f->normal.parent); /* backward compatibility mode */ if (!clone_password(f)) { free_packfile(f); return NULL; } f->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; /* re-open the parent file */ lseek(fd2, 0, SEEK_SET); if ((f->normal.parent = _pack_fdopen(fd2, F_READ)) == NULL) { free_packfile(f); return NULL; } f->normal.parent->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; pack_mgetl(f->normal.parent); if (header == encrypt_id(F_PACK_MAGIC, FALSE)) header = encrypt_id(F_PACK_MAGIC, TRUE); else header = encrypt_id(F_NOPACK_MAGIC, TRUE); } if (header == encrypt_id(F_PACK_MAGIC, TRUE)) { f->normal.todo = LONG_MAX; } else if (header == encrypt_id(F_NOPACK_MAGIC, TRUE)) { f2 = f->normal.parent; free_lzss_unpack_data(f->normal.unpack_data); f->normal.unpack_data = NULL; free_packfile(f); return f2; } else { pack_fclose(f->normal.parent); free_lzss_unpack_data(f->normal.unpack_data); f->normal.unpack_data = NULL; free_packfile(f); *allegro_errno = EDOM; return NULL; } } else { /* read a 'real' file */ f->normal.todo = lseek(fd, 0, SEEK_END); /* size of the file */ if (f->normal.todo < 0) { *allegro_errno = errno; free_packfile(f); return NULL; } lseek(fd, 0, SEEK_SET); if (!clone_password(f)) { free_packfile(f); return NULL; } f->normal.hndl = fd; } } return f; } /* pack_fopen: * Opens a file according to mode, which may contain any of the flags: * 'r': open file for reading. * 'w': open file for writing, overwriting any existing data. * 'p': open file in 'packed' mode. Data will be compressed as it is * written to the file, and automatically uncompressed during read * operations. Files created in this mode will produce garbage if * they are read without this flag being set. * '!': open file for writing in normal, unpacked mode, but add the value * F_NOPACK_MAGIC to the start of the file, so that it can be opened * in packed mode and Allegro will automatically detect that the * data does not need to be decompressed. * * Instead of these flags, one of the constants F_READ, F_WRITE, * F_READ_PACKED, F_WRITE_PACKED or F_WRITE_NOPACK may be used as the second * argument to fopen(). * * On success, fopen() returns a pointer to a file structure, and on error * it returns NULL and stores an error code in errno. An attempt to read a * normal file in packed mode will cause errno to be set to EDOM. */ PACKFILE *pack_fopen(AL_CONST char *filename, AL_CONST char *mode) { char tmp[1024]; int fd; ASSERT(filename); _packfile_type = 0; if (ustrchr(filename, '#')) { PACKFILE *special = pack_fopen_special_file(filename, mode); if (special) return special; } if (!_al_file_isok(filename)) return NULL; #ifndef ALLEGRO_MPW if (strpbrk(mode, "wW")) /* write mode? */ fd = _al_open(uconvert_tofilename(filename, tmp), O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, OPEN_PERMS); else fd = _al_open(uconvert_tofilename(filename, tmp), O_RDONLY | O_BINARY, OPEN_PERMS); #else if (strpbrk(mode, "wW")) /* write mode? */ fd = _al_open(uconvert_tofilename(filename, tmp), O_WRONLY | O_BINARY | O_CREAT | O_TRUNC); else fd = _al_open(uconvert_tofilename(filename, tmp), O_RDONLY | O_BINARY); #endif if (fd < 0) { *allegro_errno = errno; return NULL; } return _pack_fdopen(fd, mode); } /* pack_fopen_vtable: * Creates a new packfile structure that uses the functions specified in * the vtable instead of the standard functions. On success, it returns a * pointer to a file structure, and on error it returns NULL and * stores an error code in errno. * * The vtable and userdata must remain available for the lifetime of the * created packfile. * * Opening chunks using pack_fopen_chunk() on top of the returned packfile * is not possible at this time. * * packfile_password() does not have any effect on packfiles opened * with pack_fopen_vtable(). */ PACKFILE *pack_fopen_vtable(AL_CONST PACKFILE_VTABLE *vtable, void *userdata) { PACKFILE *f; ASSERT(vtable); ASSERT(vtable->pf_fclose); ASSERT(vtable->pf_getc); ASSERT(vtable->pf_ungetc); ASSERT(vtable->pf_fread); ASSERT(vtable->pf_putc); ASSERT(vtable->pf_fwrite); ASSERT(vtable->pf_fseek); ASSERT(vtable->pf_feof); ASSERT(vtable->pf_ferror); if ((f = create_packfile(FALSE)) == NULL) return NULL; f->vtable = vtable; f->userdata = userdata; ASSERT(!f->is_normal_packfile); return f; } /* pack_fclose: * Closes a file after it has been read or written. * Returns zero on success. On error it returns an error code which is * also stored in errno. This function can fail only when writing to * files: if the file was opened in read mode it will always succeed. */ int pack_fclose(PACKFILE *f) { int ret; if (!f) return 0; ASSERT(f->vtable); ASSERT(f->vtable->pf_fclose); ret = f->vtable->pf_fclose(f->userdata); if (ret != 0) *allegro_errno = errno; free_packfile(f); return ret; } /* pack_fopen_chunk: * Opens a sub-chunk of the specified file, for reading or writing depending * on the type of the file. The returned file pointer describes the sub * chunk, and replaces the original file, which will no longer be valid. * When writing to a chunk file, data is sent to the original file, but * is prefixed with two length counts (32 bit, big-endian). For uncompressed * chunks these will both be set to the length of the data in the chunk. * For compressed chunks, created by setting the pack flag, the first will * contain the raw size of the chunk, and the second will be the negative * size of the uncompressed data. When reading chunks, the pack flag is * ignored, and the compression type is detected from the sign of the * second size value. The file structure used to read chunks checks the * chunk size, and will return EOF if you try to read past the end of * the chunk. If you don't read all of the chunk data, when you call * pack_fclose_chunk(), the parent file will advance past the unused data. * When you have finished reading or writing a chunk, you should call * pack_fclose_chunk() to return to your original file. */ PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack) { PACKFILE *chunk; char tmp[1024]; char *name; ASSERT(f); /* unsupported */ if (!f->is_normal_packfile) { *allegro_errno = EINVAL; return NULL; } if (f->normal.flags & PACKFILE_FLAG_WRITE) { /* write a sub-chunk */ int tmp_fd = -1; char *tmp_dir = NULL; char *tmp_name = NULL; #ifndef ALLEGRO_HAVE_MKSTEMP char* tmpnam_string; #endif #ifdef ALLEGRO_WINDOWS int size; int new_size = 64; /* Get the path of the temporary directory */ do { size = new_size; tmp_dir = _AL_REALLOC(tmp_dir, size); new_size = GetTempPath(size, tmp_dir); } while ( (size < new_size) && (new_size > 0) ); /* Check if we retrieved the path OK */ if (new_size == 0) sprintf(tmp_dir, "%s", ""); #else /* Get the path of the temporary directory */ /* Try various possible locations to store the temporary file */ if (getenv("TEMP")) { tmp_dir = _al_strdup(getenv("TEMP")); } else if (getenv("TMP")) { tmp_dir = _al_strdup(getenv("TMP")); } else if (file_exists("/tmp", FA_DIREC, NULL)) { tmp_dir = _al_strdup("/tmp"); } else if (getenv("HOME")) { tmp_dir = _al_strdup(getenv("HOME")); } else { /* Give up - try current directory */ tmp_dir = _al_strdup("."); } #endif /* the file is open in read/write mode, even if the pack file * seems to be in write only mode */ #ifdef ALLEGRO_HAVE_MKSTEMP tmp_name = _AL_MALLOC_ATOMIC(strlen(tmp_dir) + 16); sprintf(tmp_name, "%s/XXXXXX", tmp_dir); tmp_fd = mkstemp(tmp_name); #else /* note: since the filename creation and the opening are not * an atomic operation, this is not secure */ tmpnam_string = tmpnam(NULL); tmp_name = _AL_MALLOC_ATOMIC(strlen(tmp_dir) + strlen(tmpnam_string) + 2); sprintf(tmp_name, "%s/%s", tmp_dir, tmpnam_string); if (tmp_name) { #ifndef ALLEGRO_MPW tmp_fd = open(tmp_name, O_RDWR | O_BINARY | O_CREAT | O_EXCL, OPEN_PERMS); #else tmp_fd = _al_open(tmp_name, O_RDWR | O_BINARY | O_CREAT | O_EXCL); #endif } #endif if (tmp_fd < 0) { _AL_FREE(tmp_dir); _AL_FREE(tmp_name); return NULL; } name = uconvert_ascii(tmp_name, tmp); chunk = _pack_fdopen(tmp_fd, (pack ? F_WRITE_PACKED : F_WRITE_NOPACK)); if (chunk) { chunk->normal.filename = _al_ustrdup(name); if (pack) chunk->normal.parent->normal.parent = f; else chunk->normal.parent = f; chunk->normal.flags |= PACKFILE_FLAG_CHUNK; } _AL_FREE(tmp_dir); _AL_FREE(tmp_name); } else { /* read a sub-chunk */ _packfile_filesize = pack_mgetl(f); _packfile_datasize = pack_mgetl(f); if ((chunk = create_packfile(TRUE)) == NULL) return NULL; chunk->normal.flags = PACKFILE_FLAG_CHUNK; chunk->normal.parent = f; if (f->normal.flags & PACKFILE_FLAG_OLD_CRYPT) { /* backward compatibility mode */ if (f->normal.passdata) { if ((chunk->normal.passdata = _AL_MALLOC_ATOMIC(strlen(f->normal.passdata)+1)) == NULL) { *allegro_errno = ENOMEM; _AL_FREE(chunk); return NULL; } _al_sane_strncpy(chunk->normal.passdata, f->normal.passdata, strlen(f->normal.passdata)+1); chunk->normal.passpos = chunk->normal.passdata + (long)f->normal.passpos - (long)f->normal.passdata; f->normal.passpos = f->normal.passdata; } chunk->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; } if (_packfile_datasize < 0) { /* read a packed chunk */ chunk->normal.unpack_data = create_lzss_unpack_data(); ASSERT(!chunk->normal.pack_data); if (!chunk->normal.unpack_data) { free_packfile(chunk); return NULL; } _packfile_datasize = -_packfile_datasize; chunk->normal.todo = _packfile_datasize; chunk->normal.flags |= PACKFILE_FLAG_PACK; } else { /* read an uncompressed chunk */ chunk->normal.todo = _packfile_datasize; } } return chunk; } /* pack_fclose_chunk: * Call after reading or writing a sub-chunk. This closes the chunk file, * and returns a pointer to the original file structure (the one you * passed to pack_fopen_chunk()), to allow you to read or write data * after the chunk. If an error occurs, returns NULL and sets errno. */ PACKFILE *pack_fclose_chunk(PACKFILE *f) { PACKFILE *parent; PACKFILE *tmp; char *name; int header, c; ASSERT(f); /* unsupported */ if (!f->is_normal_packfile) { *allegro_errno = EINVAL; return NULL; } parent = f->normal.parent; name = f->normal.filename; if (f->normal.flags & PACKFILE_FLAG_WRITE) { /* finish writing a chunk */ int hndl; /* duplicate the file descriptor to create a readable pack file, * the file descriptor must have been opened in read/write mode */ if (f->normal.flags & PACKFILE_FLAG_PACK) hndl = dup(f->normal.parent->normal.hndl); else hndl = dup(f->normal.hndl); if (hndl<0) { *allegro_errno = errno; return NULL; } _packfile_datasize = f->normal.todo + f->normal.buf_size - 4; if (f->normal.flags & PACKFILE_FLAG_PACK) { parent = parent->normal.parent; f->normal.parent->normal.parent = NULL; } else f->normal.parent = NULL; /* close the writeable temp file, it isn't physically closed * because the descriptor has been duplicated */ f->normal.flags &= ~PACKFILE_FLAG_CHUNK; pack_fclose(f); lseek(hndl, 0, SEEK_SET); /* create a readable pack file */ tmp = _pack_fdopen(hndl, F_READ); if (!tmp) return NULL; _packfile_filesize = tmp->normal.todo - 4; header = pack_mgetl(tmp); pack_mputl(_packfile_filesize, parent); if (header == encrypt_id(F_PACK_MAGIC, TRUE)) pack_mputl(-_packfile_datasize, parent); else pack_mputl(_packfile_datasize, parent); while ((c = pack_getc(tmp)) != EOF) pack_putc(c, parent); pack_fclose(tmp); delete_file(name); _AL_FREE(name); } else { /* finish reading a chunk */ while (f->normal.todo > 0) pack_getc(f); if (f->normal.unpack_data) { free_lzss_unpack_data(f->normal.unpack_data); f->normal.unpack_data = NULL; } if ((f->normal.passpos) && (f->normal.flags & PACKFILE_FLAG_OLD_CRYPT)) parent->normal.passpos = parent->normal.passdata + (long)f->normal.passpos - (long)f->normal.passdata; free_packfile(f); } return parent; } /* pack_fseek: * Like the stdio fseek() function, but only supports forward seeks * relative to the current file position. */ int pack_fseek(PACKFILE *f, int offset) { ASSERT(f); ASSERT(offset >= 0); return f->vtable->pf_fseek(f->userdata, offset); } /* pack_getc: * Returns the next character from the stream f, or EOF if the end of the * file has been reached. */ int pack_getc(PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_getc); return f->vtable->pf_getc(f->userdata); } /* pack_putc: * Puts a character in the stream f. */ int pack_putc(int c, PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_putc); return f->vtable->pf_putc(c, f->userdata); } /* pack_feof: * pack_feof() returns nonzero as soon as you reach the end of the file. It * does not wait for you to attempt to read beyond the end of the file, * contrary to the ISO C feof() function. */ int pack_feof(PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_feof); return f->vtable->pf_feof(f->userdata); } /* pack_ferror: * Returns nonzero if the error indicator for the stream is set, indicating * that an error has occurred during a previous operation on the stream. */ int pack_ferror(PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_ferror); return f->vtable->pf_ferror(f->userdata); } /* pack_igetw: * Reads a 16 bit word from a file, using intel byte ordering. */ int pack_igetw(PACKFILE *f) { int b1, b2; ASSERT(f); if ((b1 = pack_getc(f)) != EOF) if ((b2 = pack_getc(f)) != EOF) return ((b2 << 8) | b1); return EOF; } /* pack_igetl: * Reads a 32 bit long from a file, using intel byte ordering. */ long pack_igetl(PACKFILE *f) { int b1, b2, b3, b4; ASSERT(f); if ((b1 = pack_getc(f)) != EOF) if ((b2 = pack_getc(f)) != EOF) if ((b3 = pack_getc(f)) != EOF) if ((b4 = pack_getc(f)) != EOF) return (((long)b4 << 24) | ((long)b3 << 16) | ((long)b2 << 8) | (long)b1); return EOF; } /* pack_iputw: * Writes a 16 bit int to a file, using intel byte ordering. */ int pack_iputw(int w, PACKFILE *f) { int b1, b2; ASSERT(f); b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if (pack_putc(b2,f)==b2) if (pack_putc(b1,f)==b1) return w; return EOF; } /* pack_iputl: * Writes a 32 bit long to a file, using intel byte ordering. */ long pack_iputl(long l, PACKFILE *f) { int b1, b2, b3, b4; ASSERT(f); b1 = (int)((l & 0xFF000000L) >> 24); b2 = (int)((l & 0x00FF0000L) >> 16); b3 = (int)((l & 0x0000FF00L) >> 8); b4 = (int)l & 0x00FF; if (pack_putc(b4,f)==b4) if (pack_putc(b3,f)==b3) if (pack_putc(b2,f)==b2) if (pack_putc(b1,f)==b1) return l; return EOF; } /* pack_mgetw: * Reads a 16 bit int from a file, using motorola byte-ordering. */ int pack_mgetw(PACKFILE *f) { int b1, b2; ASSERT(f); if ((b1 = pack_getc(f)) != EOF) if ((b2 = pack_getc(f)) != EOF) return ((b1 << 8) | b2); return EOF; } /* pack_mgetl: * Reads a 32 bit long from a file, using motorola byte-ordering. */ long pack_mgetl(PACKFILE *f) { int b1, b2, b3, b4; ASSERT(f); if ((b1 = pack_getc(f)) != EOF) if ((b2 = pack_getc(f)) != EOF) if ((b3 = pack_getc(f)) != EOF) if ((b4 = pack_getc(f)) != EOF) return (((long)b1 << 24) | ((long)b2 << 16) | ((long)b3 << 8) | (long)b4); return EOF; } /* pack_mputw: * Writes a 16 bit int to a file, using motorola byte-ordering. */ int pack_mputw(int w, PACKFILE *f) { int b1, b2; ASSERT(f); b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if (pack_putc(b1,f)==b1) if (pack_putc(b2,f)==b2) return w; return EOF; } /* pack_mputl: * Writes a 32 bit long to a file, using motorola byte-ordering. */ long pack_mputl(long l, PACKFILE *f) { int b1, b2, b3, b4; ASSERT(f); b1 = (int)((l & 0xFF000000L) >> 24); b2 = (int)((l & 0x00FF0000L) >> 16); b3 = (int)((l & 0x0000FF00L) >> 8); b4 = (int)l & 0x00FF; if (pack_putc(b1,f)==b1) if (pack_putc(b2,f)==b2) if (pack_putc(b3,f)==b3) if (pack_putc(b4,f)==b4) return l; return EOF; } /* pack_fread: * Reads n bytes from f and stores them at memory location p. Returns the * number of items read, which will be less than n if EOF is reached or an * error occurs. Error codes are stored in errno. */ long pack_fread(void *p, long n, PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_fread); ASSERT(p); ASSERT(n >= 0); return f->vtable->pf_fread(p, n, f->userdata); } /* pack_fwrite: * Writes n bytes to the file f from memory location p. Returns the number * of items written, which will be less than n if an error occurs. Error * codes are stored in errno. */ long pack_fwrite(AL_CONST void *p, long n, PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_fwrite); ASSERT(p); ASSERT(n >= 0); return f->vtable->pf_fwrite(p, n, f->userdata); } /* pack_ungetc: * Puts a character back in the file's input buffer. It only works * for characters just fetched by pack_getc and, like ungetc, only a * single push back is guaranteed. */ int pack_ungetc(int c, PACKFILE *f) { ASSERT(f); ASSERT(f->vtable); ASSERT(f->vtable->pf_ungetc); return f->vtable->pf_ungetc(c, f->userdata); } /* pack_fgets: * Reads a line from a text file, storing it at location p. Stops when a * linefeed is encountered, or max bytes have been read. Returns a pointer * to where it stored the text, or NULL on error. The end of line is * handled by detecting optional '\r' characters optionally followed * by '\n' characters. This supports CR-LF (DOS/Windows), LF (Unix), and * CR (Mac) formats. */ char *pack_fgets(char *p, int max, PACKFILE *f) { char *pmax, *orig_p = p; int c; ASSERT(f); *allegro_errno = 0; pmax = p+max - ucwidth(0); if ((c = pack_getc(f)) == EOF) { if (ucwidth(0) <= max) usetc(p,0); return NULL; } do { if (c == '\r' || c == '\n') { /* Technically we should check there's space in the buffer, and if so, * add a \n. But pack_fgets has never done this. */ if (c == '\r') { /* eat the following \n, if any */ c = pack_getc(f); if ((c != '\n') && (c != EOF)) pack_ungetc(c, f); } break; } /* is there room in the buffer? */ if (ucwidth(c) > pmax - p) { pack_ungetc(c, f); c = '\0'; break; } /* write the character */ p += usetc(p, c); } while ((c = pack_getc(f)) != EOF); /* terminate the string */ usetc(p, 0); if (c == '\0' || *allegro_errno) return NULL; return orig_p; /* p has changed */ } /* pack_fputs: * Writes a string to a text file, returning zero on success, -1 on error. * The input string is converted from the current text encoding format * to UTF-8 before writing. Newline characters (\n) are written as \r\n * on DOS and Windows platforms. */ int pack_fputs(AL_CONST char *p, PACKFILE *f) { char *buf, *s; int bufsize; ASSERT(f); ASSERT(p); *allegro_errno = 0; bufsize = uconvert_size(p, U_CURRENT, U_UTF8); buf = _AL_MALLOC_ATOMIC(bufsize); if (!buf) return -1; s = uconvert(p, U_CURRENT, buf, U_UTF8, bufsize); while (*s) { #if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) if (*s == '\n') pack_putc('\r', f); #endif pack_putc(*s, f); s++; } _AL_FREE(buf); if (*allegro_errno) return -1; else return 0; } /* pack_get_userdata: * Returns the userdata field of packfiles using user-defined vtables. */ void *pack_get_userdata(PACKFILE *f) { ASSERT(f); return f->userdata; } /*************************************************** ************ "Normal" packfile vtable ************* *************************************************** Ideally this would be the only section which knows about the details of "normal" packfiles. However, this ideal is still being violated in many places (partly due to the API, and partly because it would be quite a lot of work to move the _al_normal_packfile_details field into the userdata field of the PACKFILE structure. */ static int normal_fclose(void *_f); static int normal_getc(void *_f); static int normal_ungetc(int ch, void *_f); static int normal_putc(int c, void *_f); static long normal_fread(void *p, long n, void *_f); static long normal_fwrite(AL_CONST void *p, long n, void *_f); static int normal_fseek(void *_f, int offset); static int normal_feof(void *_f); static int normal_ferror(void *_f); static int normal_refill_buffer(PACKFILE *f); static int normal_flush_buffer(PACKFILE *f, int last); static PACKFILE_VTABLE normal_vtable = { normal_fclose, normal_getc, normal_ungetc, normal_fread, normal_putc, normal_fwrite, normal_fseek, normal_feof, normal_ferror }; static int normal_fclose(void *_f) { PACKFILE *f = _f; int ret; if (f->normal.flags & PACKFILE_FLAG_WRITE) { if (f->normal.flags & PACKFILE_FLAG_CHUNK) { f = pack_fclose_chunk(_f); if (!f) return -1; return pack_fclose(f); } normal_flush_buffer(f, TRUE); } if (f->normal.parent) { ret = pack_fclose(f->normal.parent); } else { ret = close(f->normal.hndl); if (ret != 0) *allegro_errno = errno; } if (f->normal.pack_data) { free_lzss_pack_data(f->normal.pack_data); f->normal.pack_data = NULL; } if (f->normal.unpack_data) { free_lzss_unpack_data(f->normal.unpack_data); f->normal.unpack_data = NULL; } if (f->normal.passdata) { _AL_FREE(f->normal.passdata); f->normal.passdata = NULL; f->normal.passpos = NULL; } return ret; } /* normal_no_more_input: * Return non-zero if the number of bytes remaining in the file (todo) is * less than or equal to zero. * * However, there is a special case. If we are reading from a LZSS * compressed file, the latest call to lzss_read() may have suspended while * writing out a sequence of bytes due to the output buffer being too small. * In that case the `todo' count would be decremented (possibly to zero), * but the output isn't yet completely written out. */ static INLINE int normal_no_more_input(PACKFILE *f) { /* see normal_refill_buffer() to see when lzss_read() is called */ if (f->normal.parent && (f->normal.flags & PACKFILE_FLAG_PACK) && _al_lzss_incomplete_state(f->normal.unpack_data)) return 0; return (f->normal.todo <= 0); } static int normal_getc(void *_f) { PACKFILE *f = _f; f->normal.buf_size--; if (f->normal.buf_size > 0) return *(f->normal.buf_pos++); if (f->normal.buf_size == 0) { if (normal_no_more_input(f)) f->normal.flags |= PACKFILE_FLAG_EOF; return *(f->normal.buf_pos++); } return normal_refill_buffer(f); } static int normal_ungetc(int c, void *_f) { PACKFILE *f = _f; if (f->normal.buf_pos == f->normal.buf) { return EOF; } else { *(--f->normal.buf_pos) = (unsigned char)c; f->normal.buf_size++; f->normal.flags &= ~PACKFILE_FLAG_EOF; return (unsigned char)c; } } static long normal_fread(void *p, long n, void *_f) { PACKFILE *f = _f; unsigned char *cp = (unsigned char *)p; long i; int c; for (i=0; inormal.buf_size + 1 >= F_BUF_SIZE) { if (normal_flush_buffer(f, FALSE)) return EOF; } f->normal.buf_size++; return (*(f->normal.buf_pos++) = c); } static long normal_fwrite(AL_CONST void *p, long n, void *_f) { PACKFILE *f = _f; AL_CONST unsigned char *cp = (AL_CONST unsigned char *)p; long i; for (i=0; inormal.flags & PACKFILE_FLAG_WRITE) return -1; *allegro_errno = 0; /* skip forward through the buffer */ if (f->normal.buf_size > 0) { i = MIN(offset, f->normal.buf_size); f->normal.buf_size -= i; f->normal.buf_pos += i; offset -= i; if ((f->normal.buf_size <= 0) && normal_no_more_input(f)) f->normal.flags |= PACKFILE_FLAG_EOF; } /* need to seek some more? */ if (offset > 0) { i = MIN(offset, f->normal.todo); if ((f->normal.flags & PACKFILE_FLAG_PACK) || (f->normal.passpos)) { /* for compressed or encrypted files, we just have to read through the data */ while (i > 0) { pack_getc(f); i--; } } else { if (f->normal.parent) { /* pass the seek request on to the parent file */ pack_fseek(f->normal.parent, i); } else { /* do a real seek */ lseek(f->normal.hndl, i, SEEK_CUR); } f->normal.todo -= i; if (normal_no_more_input(f)) f->normal.flags |= PACKFILE_FLAG_EOF; } } if (*allegro_errno) return -1; else return 0; } static int normal_feof(void *_f) { PACKFILE *f = _f; return (f->normal.flags & PACKFILE_FLAG_EOF); } static int normal_ferror(void *_f) { PACKFILE *f = _f; return (f->normal.flags & PACKFILE_FLAG_ERROR); } /* normal_refill_buffer: * Refills the read buffer. The file must have been opened in read mode, * and the buffer must be empty. */ static int normal_refill_buffer(PACKFILE *f) { int i, sz, done, offset; if (f->normal.flags & PACKFILE_FLAG_EOF) return EOF; if (normal_no_more_input(f)) { f->normal.flags |= PACKFILE_FLAG_EOF; return EOF; } if (f->normal.parent) { if (f->normal.flags & PACKFILE_FLAG_PACK) { f->normal.buf_size = lzss_read(f->normal.parent, f->normal.unpack_data, MIN(F_BUF_SIZE, f->normal.todo), f->normal.buf); } else { f->normal.buf_size = pack_fread(f->normal.buf, MIN(F_BUF_SIZE, f->normal.todo), f->normal.parent); } if (f->normal.parent->normal.flags & PACKFILE_FLAG_EOF) f->normal.todo = 0; if (f->normal.parent->normal.flags & PACKFILE_FLAG_ERROR) goto Error; } else { f->normal.buf_size = MIN(F_BUF_SIZE, f->normal.todo); offset = lseek(f->normal.hndl, 0, SEEK_CUR); done = 0; errno = 0; sz = read(f->normal.hndl, f->normal.buf, f->normal.buf_size); while (sz+done < f->normal.buf_size) { if ((sz < 0) && ((errno != EINTR) && (errno != EAGAIN))) goto Error; if (sz > 0) done += sz; lseek(f->normal.hndl, offset+done, SEEK_SET); errno = 0; sz = read(f->normal.hndl, f->normal.buf+done, f->normal.buf_size-done); } if ((f->normal.passpos) && (!(f->normal.flags & PACKFILE_FLAG_OLD_CRYPT))) { for (i=0; inormal.buf_size; i++) { f->normal.buf[i] ^= *(f->normal.passpos++); if (!*f->normal.passpos) f->normal.passpos = f->normal.passdata; } } } f->normal.todo -= f->normal.buf_size; f->normal.buf_pos = f->normal.buf; f->normal.buf_size--; if (f->normal.buf_size <= 0) if (normal_no_more_input(f)) f->normal.flags |= PACKFILE_FLAG_EOF; if (f->normal.buf_size < 0) return EOF; else return *(f->normal.buf_pos++); Error: *allegro_errno = EFAULT; f->normal.flags |= PACKFILE_FLAG_ERROR; return EOF; } /* normal_flush_buffer: * Flushes a file buffer to the disk. The file must be open in write mode. */ static int normal_flush_buffer(PACKFILE *f, int last) { int i, sz, done, offset; if (f->normal.buf_size > 0) { if (f->normal.flags & PACKFILE_FLAG_PACK) { if (lzss_write(f->normal.parent, f->normal.pack_data, f->normal.buf_size, f->normal.buf, last)) goto Error; } else { if ((f->normal.passpos) && (!(f->normal.flags & PACKFILE_FLAG_OLD_CRYPT))) { for (i=0; inormal.buf_size; i++) { f->normal.buf[i] ^= *(f->normal.passpos++); if (!*f->normal.passpos) f->normal.passpos = f->normal.passdata; } } offset = lseek(f->normal.hndl, 0, SEEK_CUR); done = 0; errno = 0; sz = write(f->normal.hndl, f->normal.buf, f->normal.buf_size); while (sz+done < f->normal.buf_size) { if ((sz < 0) && ((errno != EINTR) && (errno != EAGAIN))) goto Error; if (sz > 0) done += sz; lseek(f->normal.hndl, offset+done, SEEK_SET); errno = 0; sz = write(f->normal.hndl, f->normal.buf+done, f->normal.buf_size-done); } } f->normal.todo += f->normal.buf_size; } f->normal.buf_pos = f->normal.buf; f->normal.buf_size = 0; return 0; Error: *allegro_errno = EFAULT; f->normal.flags |= PACKFILE_FLAG_ERROR; return EOF; } allegro-4.4.3.1/src/c/0000775000175000017500000000000013437077643013311 5ustar siegesiegeallegro-4.4.3.1/src/c/cspr8.c0000664000175000017500000000135413437077643014517 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color sprite drawing functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR8 #include "allegro/internal/aintern.h" #include "cdefs8.h" #include "cspr.h" #endif allegro-4.4.3.1/src/c/cscan16.c0000664000175000017500000000146113437077643014715 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #undef _bma_scan_gcol #include "allegro/internal/aintern.h" #include "cdefs16.h" #include "cscan.h" #endif allegro-4.4.3.1/src/c/cspr32.c0000664000175000017500000000136113437077643014572 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit color sprite drawing functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR32 #include "allegro/internal/aintern.h" #include "cdefs32.h" #include "cspr.h" #endif allegro-4.4.3.1/src/c/cgfx16.c0000664000175000017500000000136213437077643014555 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit color linear graphics functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "allegro/internal/aintern.h" #include "cdefs16.h" #include "cgfx.h" #endif allegro-4.4.3.1/src/c/cblit8.c0000664000175000017500000000131013437077643014635 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color bitmap blitting functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR8 #include "cdefs8.h" #include "cblit.h" #endif allegro-4.4.3.1/src/c/cdefs8.h0000664000175000017500000001217413437077643014643 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Defines for 256 color graphics primitives. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cdefs8_h #define __bma_cdefs8_h #define PP_DEPTH 8 #define PIXEL_PTR unsigned char* #define PTR_PER_PIXEL 1 #define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) #define INC_PIXEL_PTR(p) ((p)++) #define INC_PIXEL_PTR_N(p,d) ((p) += d) #define DEC_PIXEL_PTR(p) ((p)--) #define PUT_PIXEL(p,c) bmp_write8((uintptr_t) (p), (c)) #define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) #define PUT_RGB(p,r,g,b) bmp_write8((uintptr_t) (p), makecol8((r), (g), (b))) #define GET_PIXEL(p) bmp_read8((uintptr_t) (p)) #define GET_MEMORY_PIXEL(p) (*(p)) #define IS_MASK(c) ((c) == 0) #define IS_SPRITE_MASK(b,c) ((c) == 0) /* Blender for putpixel (DRAW_MODE_TRANS). */ #define PP_BLENDER unsigned char* #define MAKE_PP_BLENDER(c) (color_map->data[(c) & 0xFF]) #define PP_BLEND(b,o,n) ((b)[(o) & 0xFF]) /* Blender for draw_trans_*_sprite. */ #define DTS_BLENDER COLOR_MAP* #define MAKE_DTS_BLENDER() color_map #define DTS_BLEND(b,o,n) ((b)->data[(n)& 0xFF][(o) & 0xFF]) /* Blender for draw_lit_*_sprite. */ #define DLS_BLENDER unsigned char* #define MAKE_DLS_BLENDER(a) (color_map->data[(a) & 0xFF]) #define DLS_BLEND(b,a,c) ((b)[(c) & 0xFF]) #define DLSX_BLEND(b,c) ((b)[(c) & 0xFF]) /* Blender for poly_scanline_*_lit. */ #define PS_BLENDER COLOR_MAP* #define MAKE_PS_BLENDER() color_map #define PS_BLEND(b,o,c) ((b)->data[(o) & 0xFF][(c) & 0xFF]) #define PS_ALPHA_BLEND(b,o,c) ((b)->data[(o) & 0xFF][(c) & 0xFF]) #define PATTERN_LINE(y) _drawing_pattern->line[((y) - _drawing_y_anchor) & _drawing_y_mask] #define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ ((x) - _drawing_x_anchor) & _drawing_x_mask)) #define RLE_PTR signed char* #define RLE_IS_EOL(c) ((c) == 0) #define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color8 #define FUNC_LINEAR_BLIT _linear_blit8 #define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward8 #define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit8 #define FUNC_LINEAR_PUTPIXEL _linear_putpixel8 #define FUNC_LINEAR_GETPIXEL _linear_getpixel8 #define FUNC_LINEAR_HLINE _linear_hline8 #define FUNC_LINEAR_VLINE _linear_vline8 #define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite8 #define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex8 #define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite8 #define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip8 #define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip8 #define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip8 #define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite8 #define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite8 #define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite8 #define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character8 #define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite8 #define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite8 #define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite8 #define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite8 #define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite8_end #define FUNC_LINEAR_BLIT_END _linear_blit8_end #define FUNC_POLY_SCANLINE_GCOL _poly_scanline_gcol8 #define FUNC_POLY_SCANLINE_GRGB _poly_scanline_grgb8 #define FUNC_POLY_SCANLINE_ATEX _poly_scanline_atex8 #define FUNC_POLY_SCANLINE_ATEX_MASK _poly_scanline_atex_mask8 #define FUNC_POLY_SCANLINE_ATEX_LIT _poly_scanline_atex_lit8 #define FUNC_POLY_SCANLINE_ATEX_MASK_LIT _poly_scanline_atex_mask_lit8 #define FUNC_POLY_SCANLINE_PTEX _poly_scanline_ptex8 #define FUNC_POLY_SCANLINE_PTEX_MASK _poly_scanline_ptex_mask8 #define FUNC_POLY_SCANLINE_PTEX_LIT _poly_scanline_ptex_lit8 #define FUNC_POLY_SCANLINE_PTEX_MASK_LIT _poly_scanline_ptex_mask_lit8 #define FUNC_POLY_SCANLINE_ATEX_TRANS _poly_scanline_atex_trans8 #define FUNC_POLY_SCANLINE_ATEX_MASK_TRANS _poly_scanline_atex_mask_trans8 #define FUNC_POLY_SCANLINE_PTEX_TRANS _poly_scanline_ptex_trans8 #define FUNC_POLY_SCANLINE_PTEX_MASK_TRANS _poly_scanline_ptex_mask_trans8 #endif /* !__bma_cdefs8_h */ allegro-4.4.3.1/src/c/czscan8.c0000664000175000017500000000335113437077643015030 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR8 #include "allegro/internal/aintern.h" #include "cdefs8.h" #define FUNC_POLY_ZBUF_FLAT _poly_zbuf_flat8 #define FUNC_POLY_ZBUF_GCOL _poly_zbuf_gcol8 #define FUNC_POLY_ZBUF_GRGB _poly_zbuf_grgb8 #define FUNC_POLY_ZBUF_ATEX _poly_zbuf_atex8 #define FUNC_POLY_ZBUF_ATEX_MASK _poly_zbuf_atex_mask8 #define FUNC_POLY_ZBUF_ATEX_LIT _poly_zbuf_atex_lit8 #define FUNC_POLY_ZBUF_ATEX_MASK_LIT _poly_zbuf_atex_mask_lit8 #define FUNC_POLY_ZBUF_PTEX _poly_zbuf_ptex8 #define FUNC_POLY_ZBUF_PTEX_MASK _poly_zbuf_ptex_mask8 #define FUNC_POLY_ZBUF_PTEX_LIT _poly_zbuf_ptex_lit8 #define FUNC_POLY_ZBUF_PTEX_MASK_LIT _poly_zbuf_ptex_mask_lit8 #define FUNC_POLY_ZBUF_ATEX_TRANS _poly_zbuf_atex_trans8 #define FUNC_POLY_ZBUF_ATEX_MASK_TRANS _poly_zbuf_atex_mask_trans8 #define FUNC_POLY_ZBUF_PTEX_TRANS _poly_zbuf_ptex_trans8 #define FUNC_POLY_ZBUF_PTEX_MASK_TRANS _poly_zbuf_ptex_mask_trans8 #define _bma_zbuf_gcol #include "czscan.h" #undef _bma_zbuf_gcol #endif allegro-4.4.3.1/src/c/czscan15.c0000664000175000017500000000326513437077643015112 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "allegro/internal/aintern.h" #include "cdefs15.h" #define FUNC_POLY_ZBUF_FLAT _poly_zbuf_flat15 #define FUNC_POLY_ZBUF_GRGB _poly_zbuf_grgb15 #define FUNC_POLY_ZBUF_ATEX _poly_zbuf_atex15 #define FUNC_POLY_ZBUF_ATEX_MASK _poly_zbuf_atex_mask15 #define FUNC_POLY_ZBUF_ATEX_LIT _poly_zbuf_atex_lit15 #define FUNC_POLY_ZBUF_ATEX_MASK_LIT _poly_zbuf_atex_mask_lit15 #define FUNC_POLY_ZBUF_PTEX _poly_zbuf_ptex15 #define FUNC_POLY_ZBUF_PTEX_MASK _poly_zbuf_ptex_mask15 #define FUNC_POLY_ZBUF_PTEX_LIT _poly_zbuf_ptex_lit15 #define FUNC_POLY_ZBUF_PTEX_MASK_LIT _poly_zbuf_ptex_mask_lit15 #define FUNC_POLY_ZBUF_ATEX_TRANS _poly_zbuf_atex_trans15 #define FUNC_POLY_ZBUF_ATEX_MASK_TRANS _poly_zbuf_atex_mask_trans15 #define FUNC_POLY_ZBUF_PTEX_TRANS _poly_zbuf_ptex_trans15 #define FUNC_POLY_ZBUF_PTEX_MASK_TRANS _poly_zbuf_ptex_mask_trans15 #undef _bma_zbuf_gcol #include "czscan.h" #endif allegro-4.4.3.1/src/c/cblit32.c0000664000175000017500000000131513437077643014717 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit color bitmap blitting functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR32 #include "cdefs32.h" #include "cblit.h" #endif allegro-4.4.3.1/src/c/cgfx8.c0000664000175000017500000000135513437077643014500 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color linear graphics functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR8 #include "allegro/internal/aintern.h" #include "cdefs8.h" #include "cgfx.h" #endif allegro-4.4.3.1/src/c/cblit.h0000664000175000017500000000761413437077643014567 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Bitmap blitting functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cblit_h #define __bma_cblit_h /* Define USE_MEMMOVE to use libc's memmove command for doing blits. * This helps some machines, while it doesn't seem to do much for others. * Left as a define so the older blit version can be easily reactivated for * testing. */ #define USE_MEMMOVE #ifdef USE_MEMMOVE #include #endif /* _linear_clear_to_color: * Fills a linear bitmp with the specified color. */ void FUNC_LINEAR_CLEAR_TO_COLOR(BITMAP *dst, int color) { int x, y; int w; ASSERT(dst); w = dst->cr - dst->cl; bmp_select(dst); for (y = dst->ct; y < dst->cb; y++) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, y), dst->cl); for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PUT_PIXEL(d, color); } } bmp_unwrite_line(dst); } /* _linear_blit: * Normal forward blitting for linear bitmaps. */ void FUNC_LINEAR_BLIT(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h) { int y; #ifndef USE_MEMMOVE int x; #endif ASSERT(src); ASSERT(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx); #ifndef USE_MEMMOVE for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c; bmp_select(src); c = GET_PIXEL(s); bmp_select(dst); PUT_PIXEL(d, c); } #else memmove(d, s, w * sizeof(*s) * PTR_PER_PIXEL); #endif } bmp_unwrite_line(src); bmp_unwrite_line(dst); } /* _linear_blit_backward: * Reverse blitting routine, for overlapping linear bitmaps. */ void FUNC_LINEAR_BLIT_BACKWARD(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h) { int y; #ifndef USE_MEMMOVE int x; #endif ASSERT(src); ASSERT(dst); for (y = h - 1; y >= 0; y--) { #ifndef USE_MEMMOVE PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx + w - 1); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx + w - 1); for (x = w - 1; x >= 0; DEC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { unsigned long c; bmp_select(src); c = GET_PIXEL(s); bmp_select(dst); PUT_PIXEL(d, c); } #else PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx); memmove(d, s, w * sizeof(*s) * PTR_PER_PIXEL); #endif } bmp_unwrite_line(src); bmp_unwrite_line(dst); } void FUNC_LINEAR_BLIT_END(void) { } /* _linear_masked_blit: * Masked (skipping transparent pixels) blitting routine for linear bitmaps. */ void FUNC_LINEAR_MASKED_BLIT(BITMAP *src, BITMAP *dst, int sx, int sy, int dx, int dy, int w, int h) { int x, y; unsigned long mask_color; ASSERT(src); ASSERT(dst); mask_color = bitmap_mask_color(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy + y), sx); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy + y), dx); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c; bmp_select(src); c = GET_PIXEL(s); if (c != mask_color) { bmp_select(dst); PUT_PIXEL(d, c); } } } bmp_unwrite_line(src); bmp_unwrite_line(dst); } #endif /* !__bma_cblit_h */ allegro-4.4.3.1/src/c/cspr.h0000664000175000017500000011243013437077643014432 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sprite drawing functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cspr_h #define __bma_cspr_h /* _linear_draw_sprite_ex: * Draws a masked sprite onto a linear bitmap at the specified dx, dy position, * using drawing mode specified by 'mode' and flipping mode specified by * 'flip'. */ void FUNC_LINEAR_DRAW_SPRITE_EX(BITMAP * dst, BITMAP * src, int dx, int dy, int mode, int flip) { int x, y, w, h; int x_dir = 1, y_dir = 1; int dxbeg, dybeg; int sxbeg, sybeg; DLS_BLENDER lit_blender; DTS_BLENDER trans_blender; ASSERT(dst); ASSERT(src); if (flip == DRAW_SPRITE_V_FLIP) { y_dir = -1; } if (flip == DRAW_SPRITE_H_FLIP) { x_dir = -1; } if (flip == DRAW_SPRITE_VH_FLIP) { y_dir = -1; x_dir = -1; } if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = MAX(0, tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = MIN(src->w, tmp) - sxbeg; if (w <= 0) return; if (flip == DRAW_SPRITE_H_FLIP || flip == DRAW_SPRITE_VH_FLIP) { /* use backward drawing onto dst */ sxbeg = src->w - (sxbeg + w); dxbeg += w - 1; } tmp = dst->ct - dy; sybeg = MAX(0, tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = MIN(src->h, tmp) - sybeg; if (h <= 0) return; if (flip == DRAW_SPRITE_V_FLIP || flip == DRAW_SPRITE_VH_FLIP) { /* use backward drawing onto dst */ sybeg = src->h - (sybeg + h); dybeg += h - 1; } } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; if (flip == DRAW_SPRITE_H_FLIP || flip == DRAW_SPRITE_VH_FLIP) { dxbeg = dx + w - 1; } dybeg = dy; if (flip == DRAW_SPRITE_V_FLIP || flip == DRAW_SPRITE_VH_FLIP) { dybeg = dy + h - 1; } } lit_blender = MAKE_DLS_BLENDER(0); trans_blender = MAKE_DTS_BLENDER(); if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); /* flipped if y_dir is -1 */ PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg); /* d is incremented by x_dir, -1 if flipped */ for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR_N(d,x_dir), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { switch (mode) { case DRAW_SPRITE_NORMAL: break; case DRAW_SPRITE_LIT: c = DLSX_BLEND(lit_blender, c); break; case DRAW_SPRITE_TRANS: c = DTS_BLEND(trans_blender, GET_PIXEL(d), c); break; } PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR_N(d,x_dir), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { switch (mode) { case DRAW_SPRITE_NORMAL: break; case DRAW_SPRITE_LIT: c = DLSX_BLEND(lit_blender, c); break; case DRAW_SPRITE_TRANS: c = DTS_BLEND(trans_blender, GET_PIXEL(d), c); break; } PUT_MEMORY_PIXEL(d, c); } } } } } /* _linear_draw_sprite: * Draws a sprite onto a linear bitmap at the specified x, y position, * using a masked drawing mode where zero pixels are not output. */ void FUNC_LINEAR_DRAW_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_MEMORY_PIXEL(d, c); } } } } } void FUNC_LINEAR_DRAW_SPRITE_END(void) { } /* _linear_draw_256_sprite: * Draws a 256 coor sprite onto a linear bitmap at the specified x, y * position, using a masked drawing mode where zero pixels are not output. */ void FUNC_LINEAR_DRAW_256_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; int *table; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } table = _palette_expansion_table(bitmap_color_depth(dst)); ASSERT(table); if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { unsigned char *s = src->line[sybeg + y] + sxbeg; PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long c = *s; if (c != 0) { c = table[c]; PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { unsigned char *s = src->line[sybeg + y] + sxbeg; PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long c = *s; if (c != 0) { c = table[c]; PUT_MEMORY_PIXEL(d, c); } } } } } /* _linear_draw_sprite_v_flip: * Draws a sprite to a linear bitmap, flipping vertically. */ void FUNC_LINEAR_DRAW_SPRITE_V_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; /* use backward drawing onto dst */ sybeg = src->h - (sybeg + h); dybeg += h - 1; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy + h - 1; } if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg - y), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg - y], dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_MEMORY_PIXEL(d, c); } } } } } /* _linear_draw_sprite_h_flip: * Draws a sprite to a linear bitmap, flipping horizontally. */ void FUNC_LINEAR_DRAW_SPRITE_H_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; /* use backward drawing onto dst */ sxbeg = src->w - (sxbeg + w); dxbeg += w - 1; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx + w - 1; dybeg = dy; } if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_MEMORY_PIXEL(d, c); } } } } } /* _linear_draw_sprite_vh_flip: * Draws a sprite to a linear bitmap, flipping both vertically and horizontally. */ void FUNC_LINEAR_DRAW_SPRITE_VH_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; /* use backward drawing onto dst */ sxbeg = src->w - (sxbeg + w); dxbeg += w - 1; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; /* use backward drawing onto dst */ sybeg = src->h - (sybeg + h); dybeg += h - 1; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx + w - 1; dybeg = dy + h - 1; } if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg - y), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg - y], dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_SPRITE_MASK(src, c)) { PUT_MEMORY_PIXEL(d, c); } } } } } /* _linear_draw_trans_sprite: * Draws a translucent sprite onto a linear bitmap. */ void FUNC_LINEAR_DRAW_TRANS_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; DTS_BLENDER blender; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } blender = MAKE_DTS_BLENDER(); if ((src->vtable->color_depth == 8) && (dst->vtable->color_depth != 8)) { bmp_select(dst); for (y = 0; y < h; y++) { unsigned char *s = src->line[sybeg + y] + sxbeg; PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long c = *s; #if PP_DEPTH == 8 c = DTS_BLEND(blender, GET_PIXEL(ds), c); PUT_PIXEL(dd, c); #else if (!IS_SPRITE_MASK(src, c)) { c = DTS_BLEND(blender, GET_PIXEL(ds), c); PUT_PIXEL(dd, c); } #endif } } bmp_unwrite_line(dst); } else if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long c = GET_MEMORY_PIXEL(s); #if PP_DEPTH == 8 c = DTS_BLEND(blender, GET_PIXEL(ds), c); PUT_PIXEL(dd, c); #else if (!IS_SPRITE_MASK(src, c)) { c = DTS_BLEND(blender, GET_PIXEL(ds), c); PUT_PIXEL(dd, c); } #endif } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); #if PP_DEPTH == 8 c = DTS_BLEND(blender, GET_MEMORY_PIXEL(d), c); PUT_MEMORY_PIXEL(d, c); #else if (!IS_SPRITE_MASK(src, c)) { c = DTS_BLEND(blender, GET_MEMORY_PIXEL(d), c); PUT_MEMORY_PIXEL(d, c); } #endif } } } } #if (PP_DEPTH != 8) && (PP_DEPTH != 32) /* _linear_draw_trans_rgba_sprite: * Draws a translucent RGBA sprite onto a linear bitmap. */ void FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; RGBA_BLENDER blender; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } blender = MAKE_RGBA_BLENDER(); bmp_select(dst); for (y = 0; y < h; y++) { uint32_t *s = (uint32_t *)src->line[sybeg + y] + sxbeg; PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long c = *s; if (c != MASK_COLOR_32) { c = RGBA_BLEND(blender, GET_PIXEL(ds), c); PUT_PIXEL(dd, c); } } } bmp_unwrite_line(dst); } #endif /* _linear_draw_lit_sprite: * Draws a lit sprite onto a linear bitmap. */ void FUNC_LINEAR_DRAW_LIT_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy, int color) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; DLS_BLENDER blender; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } blender = MAKE_DLS_BLENDER(color); if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) { bmp_select(dst); for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_MASK(c)) { c = DLS_BLEND(blender, color, c); PUT_PIXEL(d, c); } } } bmp_unwrite_line(dst); } else { for (y = 0; y < h; y++) { PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg); PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg); for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_MASK(c)) { c = DLS_BLEND(blender, color, c); PUT_MEMORY_PIXEL(d, c); } } } } } /* _linear_draw_character: * For proportional font output onto a linear bitmap: uses the sprite as * a mask, replacing all set pixels with the specified color. */ void FUNC_LINEAR_DRAW_CHARACTER(BITMAP *dst, BITMAP *src, int dx, int dy, int color, int bg) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } bmp_select(dst); if (bg < 0) { /* Masked character. */ for (y = 0; y < h; y++) { unsigned char *s = src->line[sybeg + y] + sxbeg; PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long c = *s; if (c != 0) { PUT_PIXEL(d, color); } } } } else { /* Opaque character. */ for (y = 0; y < h; y++) { unsigned char *s = src->line[sybeg + y] + sxbeg; PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long c = *s; if (c != 0) { PUT_PIXEL(d, color); } else { PUT_PIXEL(d, bg); } } } } bmp_unwrite_line(dst); } /* _linear_draw_rle_sprite: * Draws an RLE sprite onto a linear bitmap at the specified position. */ void FUNC_LINEAR_DRAW_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; RLE_PTR s; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } s = (RLE_PTR) (src->dat); /* Clip top. */ for (y = sybeg - 1; y >= 0; y--) { long c = *s++; while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } } bmp_select(dst); /* Visible part. */ if (sxbeg || dx+src->w >= dst->cr) { for (y = 0; y < h; y++) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Clip left. */ for (x = sxbeg; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully clipped. */ x -= c; s += c; } else { /* Visible on the right. */ c -= x; s += x; break; } } else { /* Run of transparent pixels. */ if ((x + c) >= 0) { /* Fully clipped. */ x += c; } else { /* Visible on the right. */ c += x; break; } } c = *s++; } /* Visible part. */ for (x = w; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) { unsigned long col = *s; PUT_PIXEL(d, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long col = *s; PUT_PIXEL(d, col); } break; } } else { /* Run of transparent pixels. */ x += c; d = OFFSET_PIXEL_PTR(d, -c); } c = *s++; } /* Clip right. */ while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } next_line: ; } } else { for (y = 0; y < h; y++) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Visible part. */ for (x = w; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line2; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) { unsigned long col = *s; PUT_PIXEL(d, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long col = *s; PUT_PIXEL(d, col); } break; } } else { /* Run of transparent pixels. */ x += c; d = OFFSET_PIXEL_PTR(d, -c); } c = *s++; } next_line2: ; } } bmp_unwrite_line(dst); } /* _linear_draw_trans_rle_sprite: * Draws a translucent RLE sprite onto a linear bitmap. */ void FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; RLE_PTR s; DTS_BLENDER blender; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } blender = MAKE_DTS_BLENDER(); s = (RLE_PTR) (src->dat); /* Clip top. */ for (y = sybeg - 1; y >= 0; y--) { long c = *s++; while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } } bmp_select(dst); /* Visible part. */ if (sxbeg || dx+src->w >= dst->cr) { for (y = 0; y < h; y++) { PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Clip left. */ for (x = sxbeg; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully clipped. */ x -= c; s += c; } else { /* Visible on the right. */ c -= x; s += x; break; } } else { /* Run of transparent pixels. */ if ((x + c) >= 0) { /* Fully clipped. */ x += c; } else { /* Visible on the right. */ c += x; break; } } c = *s++; } /* Visible part. */ for (x = w; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) { unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } break; } } else { /* Run of transparent pixels. */ x += c; ds = OFFSET_PIXEL_PTR(ds, -c); dd = OFFSET_PIXEL_PTR(dd, -c); } c = *s++; } /* Clip right. */ while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } next_line:{} } } else { for (y = 0; y < h; y++) { PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Visible part. */ for (x = w; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line2; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) { unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } break; } } else { /* Run of transparent pixels. */ x += c; ds = OFFSET_PIXEL_PTR(ds, -c); dd = OFFSET_PIXEL_PTR(dd, -c); } c = *s++; } /* Clip right. */ while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } next_line2:{} } } bmp_unwrite_line(dst); } #if (PP_DEPTH != 8) && (PP_DEPTH != 32) /* _linear_draw_trans_rgba_rle_sprite: * Draws a translucent RGBA RLE sprite onto a linear bitmap. */ void FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; uint32_t *s; RGBA_BLENDER blender; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } blender = MAKE_RGBA_BLENDER(); s = (uint32_t *) (src->dat); /* Clip top. */ for (y = sybeg - 1; y >= 0; y--) { long c = *s++; while (c != MASK_COLOR_32) { if (c > 0) s += c; c = *s++; } } bmp_select(dst); /* Visible part. */ if (sxbeg || dx+src->w >= dst->cr) { for (y = 0; y < h; y++) { PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Clip left. */ for (x = sxbeg; x > 0; ) { if (c == MASK_COLOR_32) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully clipped. */ x -= c; s += c; } else { /* Visible on the right. */ c -= x; s += x; break; } } else { /* Run of transparent pixels. */ if ((x + c) >= 0) { /* Fully clipped. */ x += c; } else { /* Visible on the right. */ c += x; break; } } c = *s++; } /* Visible part. */ for (x = w; x > 0; ) { if (c == MASK_COLOR_32) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) { unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } break; } } else { /* Run of transparent pixels. */ x += c; ds = OFFSET_PIXEL_PTR(ds, -c); dd = OFFSET_PIXEL_PTR(dd, -c); } c = *s++; } /* Clip right. */ while (c != MASK_COLOR_32) { if (c > 0) s += c; c = *s++; } next_line:{} } } else { for (y = 0; y < h; y++) { PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg); PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Visible part. */ for (x = w; x > 0; ) { if (c == MASK_COLOR_32) goto next_line2; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) { unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) { unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s); PUT_PIXEL(dd, col); } break; } } else { /* Run of transparent pixels. */ x += c; ds = OFFSET_PIXEL_PTR(ds, -c); dd = OFFSET_PIXEL_PTR(dd, -c); } c = *s++; } next_line2:{} } } bmp_unwrite_line(dst); } #endif /* _linear_draw_lit_rle_sprite: * Draws a tinted RLE sprite onto a linear bitmap. */ void FUNC_LINEAR_DRAW_LIT_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy, int color) { int x, y, w, h; int dxbeg, dybeg; int sxbeg, sybeg; RLE_PTR s; DLS_BLENDER blender; ASSERT(dst); ASSERT(src); if (dst->clip) { int tmp; tmp = dst->cl - dx; sxbeg = ((tmp < 0) ? 0 : tmp); dxbeg = sxbeg + dx; tmp = dst->cr - dx; w = ((tmp > src->w) ? src->w : tmp) - sxbeg; if (w <= 0) return; tmp = dst->ct - dy; sybeg = ((tmp < 0) ? 0 : tmp); dybeg = sybeg + dy; tmp = dst->cb - dy; h = ((tmp > src->h) ? src->h : tmp) - sybeg; if (h <= 0) return; } else { w = src->w; h = src->h; sxbeg = 0; sybeg = 0; dxbeg = dx; dybeg = dy; } blender = MAKE_DLS_BLENDER(color); s = (RLE_PTR) (src->dat); /* Clip top. */ for (y = sybeg - 1; y >= 0; y--) { long c = *s++; while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } } bmp_select(dst); /* Visible part. */ if (sxbeg || dx+src->w >= dst->cr) { for (y = 0; y < h; y++) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Clip left. */ for (x = sxbeg; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully clipped. */ x -= c; s += c; } else { /* Visible on the right. */ c -= x; s += x; break; } } else { /* Run of transparent pixels. */ if ((x + c) >= 0) { /* Fully clipped. */ x += c; } else { /* Visible on the right. */ c += x; break; } } c = *s++; } /* Visible part. */ for (x = w; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) { unsigned long col = DLS_BLEND(blender, color, *s); PUT_PIXEL(d, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long col = DLS_BLEND(blender, color, *s); PUT_PIXEL(d, col); } break; } } else { /* Run of transparent pixels. */ x += c; d = OFFSET_PIXEL_PTR(d, -c); } c = *s++; } /* Clip right. */ while (!RLE_IS_EOL(c)) { if (c > 0) s += c; c = *s++; } next_line:{} } } else { for (y = 0; y < h; y++) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg); long c = *s++; /* Visible part. */ for (x = w; x > 0; ) { if (RLE_IS_EOL(c)) goto next_line2; else if (c > 0) { /* Run of solid pixels. */ if ((x - c) >= 0) { /* Fully visible. */ x -= c; for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) { unsigned long col = DLS_BLEND(blender, color, *s); PUT_PIXEL(d, col); } } else { /* Clipped on the right. */ c -= x; for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) { unsigned long col = DLS_BLEND(blender, color, *s); PUT_PIXEL(d, col); } break; } } else { /* Run of transparent pixels. */ x += c; d = OFFSET_PIXEL_PTR(d, -c); } c = *s++; } next_line2:{} } } bmp_unwrite_line(dst); } #endif /* !__bma_cspr_h */ allegro-4.4.3.1/src/c/cscan.h0000664000175000017500000004024313437077643014554 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Polygon scanline filler helpers (gouraud shading, tmapping, etc). * * By Michael Bukin. * * Scanline subdivision in *_PTEX functions and transparency modes * added by Bertrand Coconnier. * * See readme.txt for copyright information. */ #ifndef __bma_cscan_h #define __bma_cscan_h #ifdef _bma_scan_gcol /* _poly_scanline_gcol: * Fills a single-color gouraud shaded polygon scanline. */ void FUNC_POLY_SCANLINE_GCOL(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; fixed c, dc; PIXEL_PTR d; ASSERT(addr); ASSERT(info); c = info->c; dc = info->dc; d = (PIXEL_PTR) addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PUT_PIXEL(d, (c >> 16)); c += dc; } } #endif /* _bma_scan_gcol */ /* _poly_scanline_grgb: * Fills an gouraud shaded polygon scanline. */ void FUNC_POLY_SCANLINE_GRGB(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; fixed r, g, b; fixed dr, dg, db; PIXEL_PTR d; ASSERT(addr); ASSERT(info); r = info->r; g = info->g; b = info->b; dr = info->dr; dg = info->dg; db = info->db; d = (PIXEL_PTR) addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PUT_RGB(d, (r >> 16), (g >> 16), (b >> 16)); r += dr; g += dg; b += db; } } /* _poly_scanline_atex: * Fills an affine texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_ATEX(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, color); u += du; v += dv; } } /* _poly_scanline_atex_mask: * Fills a masked affine texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_ATEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { PUT_PIXEL(d, color); } u += du; v += dv; } } /* _poly_scanline_atex_lit: * Fills a lit affine texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_ATEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, c, du, dv, dc; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; c = info->c; du = info->du; dv = info->dv; dc = info->dc; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); u += du; v += dv; c += dc; } } /* _poly_scanline_atex_mask_lit: * Fills a masked lit affine texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_ATEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, c, du, dv, dc; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; c = info->c; du = info->du; dv = info->dv; dc = info->dc; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); } u += du; v += dv; c += dc; } } /* _poly_scanline_ptex: * Fills a perspective correct texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_PTEX(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x, i, imax = 3; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz, z1; PIXEL_PTR texture; PIXEL_PTR d; int64_t u, v; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu * 4; dfv = info->dfv * 4; dfz = info->dz * 4; z1 = 1. / fz; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; u = fu * z1; v = fv * z1; /* update depth */ fz += dfz; z1 = 1. / fz; for (x = w - 1; x >= 0; x -= 4) { int64_t nextu, nextv, du, dv; PIXEL_PTR s; unsigned long color; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; nextv = fv * z1; z1 = 1. / fz; du = (nextu - u) >> 2; dv = (nextv - v) >> 2; /* scanline subdivision */ if (x < 3) imax = x; for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) { s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); color = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, color); u += du; v += dv; } } } /* _poly_scanline_ptex_mask: * Fills a masked perspective correct texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_PTEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x, i, imax = 3; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz, z1; PIXEL_PTR texture; PIXEL_PTR d; int64_t u, v; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu * 4; dfv = info->dfv * 4; dfz = info->dz * 4; z1 = 1. / fz; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; u = fu * z1; v = fv * z1; /* update depth */ fz += dfz; z1 = 1. / fz; for (x = w - 1; x >= 0; x-= 4) { int64_t nextu, nextv, du, dv; PIXEL_PTR s; unsigned long color; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; nextv = fv * z1; z1 = 1. / fz; du = (nextu - u) >> 2; dv = (nextv - v) >> 2; /* scanline subdivision */ if (x < 3) imax = x; for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) { s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { PUT_PIXEL(d, color); } u += du; v += dv; } } } /* _poly_scanline_ptex_lit: * Fills a lit perspective correct texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_PTEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x, i, imax = 3; int vmask, vshift, umask; fixed c, dc; double fu, fv, fz, dfu, dfv, dfz, z1; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; int64_t u, v; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; c = info->c; dc = info->dc; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu * 4; dfv = info->dfv * 4; dfz = info->dz * 4; z1 = 1. / fz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; u = fu * z1; v = fv * z1; /* update depth */ fz += dfz; z1 = 1. / fz; for (x = w - 1; x >= 0; x-= 4) { int64_t nextu, nextv, du, dv; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; nextv = fv * z1; z1 = 1. / fz; du = (nextu - u) >> 2; dv = (nextv - v) >> 2; /* scanline subdivision */ if (x < 3) imax = x; for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); u += du; v += dv; c += dc; } } } /* _poly_scanline_ptex_mask_lit: * Fills a masked lit perspective correct texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_PTEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x, i, imax = 3; int vmask, vshift, umask; fixed c, dc; double fu, fv, fz, dfu, dfv, dfz, z1; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; int64_t u, v; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; c = info->c; dc = info->dc; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu * 4; dfv = info->dfv * 4; dfz = info->dz * 4; z1 = 1. / fz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; u = fu * z1; v = fv * z1; /* update depth */ fz += dfz; z1 = 1. / fz; for (x = w - 1; x >= 0; x-= 4) { int64_t nextu, nextv, du, dv; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; nextv = fv * z1; z1 = 1. / fz; du = (nextu - u) >> 2; dv = (nextv - v) >> 2; /* scanline subdivision */ if (x < 3) imax = x; for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); } u += du; v += dv; c += dc; } } } /* _poly_scanline_atex_trans: * Fills a trans affine texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_ATEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; PS_BLENDER blender; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); u += du; v += dv; } } /* _poly_scanline_atex_mask_trans: * Fills a trans masked affine texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_ATEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; PS_BLENDER blender; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); } u += du; v += dv; } } /* _poly_scanline_ptex_trans: * Fills a trans perspective correct texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_PTEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x, i, imax = 3; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz, z1; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; int64_t u, v; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu * 4; dfv = info->dfv * 4; dfz = info->dz * 4; z1 = 1. / fz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; u = fu * z1; v = fv * z1; /* update depth */ fz += dfz; z1 = 1. / fz; for (x = w - 1; x >= 0; x-= 4) { int64_t nextu, nextv, du, dv; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; nextv = fv * z1; z1 = 1. / fz; du = (nextu - u) >> 2; dv = (nextv - v) >> 2; /* scanline subdivision */ if (x < 3) imax = x; for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d), INC_PIXEL_PTR(r)) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); u += du; v += dv; } } } /* _poly_scanline_ptex_mask_trans: * Fills a trans masked perspective correct texture mapped polygon scanline. */ void FUNC_POLY_SCANLINE_PTEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x, i, imax = 3; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz, z1; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; int64_t u, v; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu * 4; dfv = info->dfv * 4; dfz = info->dz * 4; z1 = 1. / fz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; u = fu * z1; v = fv * z1; /* update depth */ fz += dfz; z1 = 1. / fz; for (x = w - 1; x >= 0; x-= 4) { int64_t nextu, nextv, du, dv; fu += dfu; fv += dfv; fz += dfz; nextu = fu * z1; nextv = fv * z1; z1 = 1. / fz; du = (nextu - u) >> 2; dv = (nextv - v) >> 2; /* scanline subdivision */ if (x < 3) imax = x; for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d), INC_PIXEL_PTR(r)) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); } u += du; v += dv; } } } #endif /* !__bma_cscan_h */ allegro-4.4.3.1/src/c/ccsprite.c0000664000175000017500000000254613437077643015300 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Compiled sprite routines for some unknown platforms. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" /* get_compiled_sprite: * Creates a compiled sprite based on the specified bitmap. */ COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar) { ASSERT(bitmap); return get_rle_sprite(bitmap); } /* destroy_compiled_sprite: * Destroys a compiled sprite structure returned by get_compiled_sprite(). */ void destroy_compiled_sprite(COMPILED_SPRITE *sprite) { ASSERT(sprite); destroy_rle_sprite(sprite); } /* draw_compiled_sprite: * Draws a compiled sprite onto the specified bitmap at the specified * position. */ void draw_compiled_sprite(BITMAP *dst, AL_CONST COMPILED_SPRITE *src, int x, int y) { ASSERT(dst); ASSERT(src); draw_rle_sprite(dst, (COMPILED_SPRITE *)src, x, y); } allegro-4.4.3.1/src/c/czscan16.c0000664000175000017500000000326513437077643015113 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "allegro/internal/aintern.h" #include "cdefs16.h" #define FUNC_POLY_ZBUF_FLAT _poly_zbuf_flat16 #define FUNC_POLY_ZBUF_GRGB _poly_zbuf_grgb16 #define FUNC_POLY_ZBUF_ATEX _poly_zbuf_atex16 #define FUNC_POLY_ZBUF_ATEX_MASK _poly_zbuf_atex_mask16 #define FUNC_POLY_ZBUF_ATEX_LIT _poly_zbuf_atex_lit16 #define FUNC_POLY_ZBUF_ATEX_MASK_LIT _poly_zbuf_atex_mask_lit16 #define FUNC_POLY_ZBUF_PTEX _poly_zbuf_ptex16 #define FUNC_POLY_ZBUF_PTEX_MASK _poly_zbuf_ptex_mask16 #define FUNC_POLY_ZBUF_PTEX_LIT _poly_zbuf_ptex_lit16 #define FUNC_POLY_ZBUF_PTEX_MASK_LIT _poly_zbuf_ptex_mask_lit16 #define FUNC_POLY_ZBUF_ATEX_TRANS _poly_zbuf_atex_trans16 #define FUNC_POLY_ZBUF_ATEX_MASK_TRANS _poly_zbuf_atex_mask_trans16 #define FUNC_POLY_ZBUF_PTEX_TRANS _poly_zbuf_ptex_trans16 #define FUNC_POLY_ZBUF_PTEX_MASK_TRANS _poly_zbuf_ptex_mask_trans16 #undef _bma_zbuf_gcol #include "czscan.h" #endif allegro-4.4.3.1/src/c/ccpu.c0000664000175000017500000000157413437077643014416 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Dummy CPU detection routines. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" /* MacOS X has its own check_cpu function, see src/macosx/pcpu.m */ #ifndef ALLEGRO_MACOSX /* check_cpu: * This is the function to call to set the globals. */ void check_cpu(void) { cpu_family = 0; cpu_model = 0; cpu_capabilities = 0; } #endif allegro-4.4.3.1/src/c/czscan.h0000664000175000017500000004026113437077643014746 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Z-buffered polygon filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #define ZBUF_PTR float* #ifndef __bma_czscan_h #define __bma_czscan_h /* _poly_zbuf_flat: * Fills a single-color polygon scanline. */ void FUNC_POLY_ZBUF_FLAT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; float z; unsigned long c; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); z = info->z; c = info->c; d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PUT_PIXEL(d, c); *zb = z; } zb++; z += info->dz; } } #ifdef _bma_zbuf_gcol /* _poly_zbuf_gcol: * Fills a single-color gouraud shaded polygon scanline. */ void FUNC_POLY_ZBUF_GCOL(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; float z; fixed c, dc; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); z = info->z; c = info->c; dc = info->dc; d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PUT_PIXEL(d, (c >> 16)); *zb = z; } c += dc; zb++; z += info->dz; } } #endif /* _bma_zbuf_gcol */ /* _poly_zbuf_grgb: * Fills an gouraud shaded polygon scanline. */ void FUNC_POLY_ZBUF_GRGB(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; fixed r, g, b, dr, dg, db; PIXEL_PTR d; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); r = info->r; g = info->g; b = info->b; dr = info->dr; dg = info->dg; db = info->db; d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PUT_RGB(d, (r >> 16), (g >> 16), (b >> 16)); *zb = z; } r += dr; g += dg; b += db; zb++; z += info->dz; } } /* _poly_zbuf_atex: * Fills an affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, color); *zb = z; } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_atex_mask: * Fills a masked affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { PUT_PIXEL(d, color); *zb = z; } } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_atex_lit: * Fills a lit affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, c, du, dv, dc; PIXEL_PTR texture; PIXEL_PTR d; PS_BLENDER blender; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; c = info->c; du = info->du; dv = info->dv; dc = info->dc; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = z; } u += du; v += dv; c += dc; zb++; z += info->dz; } } /* _poly_zbuf_atex_mask_lit: * Fills a masked lit affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, c, du, dv, dc; PIXEL_PTR texture; PIXEL_PTR d; PS_BLENDER blender; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; c = info->c; du = info->du; dv = info->dv; dc = info->dc; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = z; } } u += du; v += dv; c += dc; zb++; z += info->dz; } } /* _poly_zbuf_ptex: * Fills a perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, color); *zb = (float) fz; } fu += dfu; fv += dfv; fz += dfz; zb++; } } /* _poly_zbuf_ptex_mask: * Fills a masked perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { PUT_PIXEL(d, color); *zb = (float) fz; } } fu += dfu; fv += dfv; fz += dfz; zb++; } } /* _poly_zbuf_ptex_lit: * Fills a lit perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed c, dc; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; c = info->c; dc = info->dc; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = (float) fz; } fu += dfu; fv += dfv; fz += dfz; c += dc; zb++; } } /* _poly_zbuf_ptex_mask_lit: * Fills a masked lit perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed c, dc; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; c = info->c; dc = info->dc; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = (float) fz; } } fu += dfu; fv += dfv; fz += dfz; c += dc; zb++; } } /* _poly_zbuf_atex_trans: * Fills a trans affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = z; } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_atex_mask_trans: * Fills a trans masked affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = z; } } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_ptex_trans: * Fills a trans perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = (float) fz; } fu += dfu; fv += dfv; fz += dfz; zb++; } } /* _poly_zbuf_ptex_mask_trans: * Fills a trans masked perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = (float) fz; } } fu += dfu; fv += dfv; fz += dfz; zb++; } } #endif /* !__bma_czscan_h */ allegro-4.4.3.1/src/c/cdefs15.h0000664000175000017500000001265313437077643014723 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Defines for 15 bit color graphics primitives. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cdefs15_h #define __bma_cdefs15_h #define PP_DEPTH 15 #define PIXEL_PTR unsigned short* #define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) #define INC_PIXEL_PTR(p) ((p)++) #define INC_PIXEL_PTR_N(p,d) ((p) += d) #define DEC_PIXEL_PTR(p) ((p)--) #define PUT_PIXEL(p,c) bmp_write15((uintptr_t) (p), (c)) #define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) #define PUT_RGB(p,r,g,b) bmp_write15((uintptr_t) (p), makecol15((r), (g), (b))) #define GET_PIXEL(p) bmp_read15((uintptr_t) (p)) #define GET_MEMORY_PIXEL(p) (*(p)) #define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_15) #define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == MASK_COLOR_15) /* Blender for putpixel (DRAW_MODE_TRANS). */ #define PP_BLENDER BLENDER_FUNC #define MAKE_PP_BLENDER(c) _blender_func15 #define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_trans_*_sprite. */ #define DTS_BLENDER BLENDER_FUNC #define MAKE_DTS_BLENDER() _blender_func15 #define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_lit_*_sprite. */ #define DLS_BLENDER BLENDER_FUNC #define MAKE_DLS_BLENDER(a) _blender_func15 #define DLS_BLEND(b,a,n) ((*(b))(_blender_col_15, (n), (a))) #define DLSX_BLEND(b,n) ((*(b))(_blender_col_15, (n), _blender_alpha)) /* Blender for RGBA sprites. */ #define RGBA_BLENDER BLENDER_FUNC #define MAKE_RGBA_BLENDER() _blender_func15x #define RGBA_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for poly_scanline_*_lit. */ #define PS_BLENDER BLENDER_FUNC #define MAKE_PS_BLENDER() _blender_func15 #define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_15, (o))) #define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) #define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ & _drawing_y_mask]) #define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ ((x) - _drawing_x_anchor) & _drawing_x_mask)) #define RLE_PTR signed short* #define RLE_IS_EOL(c) ((unsigned short) (c) == MASK_COLOR_15) #define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color15 #define FUNC_LINEAR_BLIT _linear_blit15 #define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward15 #define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit15 #define FUNC_LINEAR_PUTPIXEL _linear_putpixel15 #define FUNC_LINEAR_GETPIXEL _linear_getpixel15 #define FUNC_LINEAR_HLINE _linear_hline15 #define FUNC_LINEAR_VLINE _linear_vline15 #define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite15 #define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex15 #define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite15 #define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip15 #define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip15 #define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip15 #define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite15 #define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite15 #define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite15 #define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character15 #define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite15 #define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite15 #define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite15 #define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite15 #define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite15_end #define FUNC_LINEAR_BLIT_END _linear_blit15_end #define FUNC_POLY_SCANLINE_GRGB _poly_scanline_grgb15 #define FUNC_POLY_SCANLINE_ATEX _poly_scanline_atex15 #define FUNC_POLY_SCANLINE_ATEX_MASK _poly_scanline_atex_mask15 #define FUNC_POLY_SCANLINE_ATEX_LIT _poly_scanline_atex_lit15 #define FUNC_POLY_SCANLINE_ATEX_MASK_LIT _poly_scanline_atex_mask_lit15 #define FUNC_POLY_SCANLINE_PTEX _poly_scanline_ptex15 #define FUNC_POLY_SCANLINE_PTEX_MASK _poly_scanline_ptex_mask15 #define FUNC_POLY_SCANLINE_PTEX_LIT _poly_scanline_ptex_lit15 #define FUNC_POLY_SCANLINE_PTEX_MASK_LIT _poly_scanline_ptex_mask_lit15 #define FUNC_POLY_SCANLINE_ATEX_TRANS _poly_scanline_atex_trans15 #define FUNC_POLY_SCANLINE_ATEX_MASK_TRANS _poly_scanline_atex_mask_trans15 #define FUNC_POLY_SCANLINE_PTEX_TRANS _poly_scanline_ptex_trans15 #define FUNC_POLY_SCANLINE_PTEX_MASK_TRANS _poly_scanline_ptex_mask_trans15 #endif /* !__bma_cdefs15_h */ allegro-4.4.3.1/src/c/cscan8.c0000664000175000017500000000150413437077643014634 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 256 color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR8 #define _bma_scan_gcol #include "allegro/internal/aintern.h" #include "cdefs8.h" #include "cscan.h" #undef _bma_scan_gcol #endif allegro-4.4.3.1/src/c/cscan15.c0000664000175000017500000000146113437077643014714 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #undef _bma_scan_gcol #include "allegro/internal/aintern.h" #include "cdefs15.h" #include "cscan.h" #endif allegro-4.4.3.1/src/c/cstretch.c0000664000175000017500000002472113437077643015302 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Bitmap stretching functions. * * By Michael Bukin. * Fixed and improved in 2007 by Trent Gamblin. * * See readme.txt for copyright information. */ #include "allegro.h" /* Information for stretching line */ static struct { int xcstart; /* x counter start */ int sxinc; /* amount to increment src x every time */ int xcdec; /* amount to deccrement counter by, increase sptr when this reaches 0 */ int xcinc; /* amount to increment counter by when it reaches 0 */ int linesize; /* size of a whole row of pixels */ } _al_stretch; /* Stretcher macros */ #define DECLARE_STRETCHER(type, size, put, get) \ int xc = _al_stretch.xcstart; \ uintptr_t dend = dptr + _al_stretch.linesize; \ ASSERT(dptr); \ ASSERT(sptr); \ for (; dptr < dend; dptr += size, sptr += _al_stretch.sxinc) { \ put(dptr, get((type*)sptr)); \ if (xc <= 0) { \ sptr += size; \ xc += _al_stretch.xcinc; \ } \ else \ xc -= _al_stretch.xcdec; \ } #define DECLARE_MASKED_STRETCHER(type, size, put, get, mask) \ int xc = _al_stretch.xcstart; \ uintptr_t dend = dptr + _al_stretch.linesize; \ ASSERT(dptr); \ ASSERT(sptr); \ for (; dptr < dend; dptr += size, sptr += _al_stretch.sxinc) { \ int color = get((type*)sptr); \ if (color != mask) \ put(dptr, get((type*)sptr)); \ if (xc <= 0) { \ sptr += size; \ xc += _al_stretch.xcinc; \ } \ else \ xc -= _al_stretch.xcdec; \ } #ifdef ALLEGRO_GFX_HAS_VGA /* * Mode-X line stretcher. */ static void stretch_linex(uintptr_t dptr, unsigned char *sptr) { int plane; int first_xc = _al_stretch.xcstart; int dw = _al_stretch.linesize; ASSERT(dptr); ASSERT(sptr); for (plane = 0; plane < 4; plane++) { int xc = first_xc; unsigned char *s = sptr; uintptr_t d = dptr / 4; uintptr_t dend = (dptr + dw) / 4; outportw(0x3C4, (0x100 << (dptr & 3)) | 2); for (; d < dend; d++, s += 4 * _al_stretch.sxinc) { bmp_write8(d, *s); if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; } /* Move to the beginning of next plane. */ if (first_xc <= 0) { sptr++; first_xc += _al_stretch.xcinc; } else first_xc -= _al_stretch.xcdec; dptr++; sptr += _al_stretch.sxinc; dw--; } } /* * Mode-X masked line stretcher. */ static void stretch_masked_linex(uintptr_t dptr, unsigned char *sptr) { int plane; int dw = _al_stretch.linesize; int first_xc = _al_stretch.xcstart; ASSERT(dptr); ASSERT(sptr); for (plane = 0; plane < 4; plane++) { int xc = first_xc; unsigned char *s = sptr; uintptr_t d = dptr / 4; uintptr_t dend = (dptr + dw) / 4; outportw(0x3C4, (0x100 << (dptr & 3)) | 2); for (; d < dend; d++, s += 4 * _al_stretch.sxinc) { unsigned long color = *s; if (color != 0) bmp_write8(d, color); if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; } /* Move to the beginning of next plane. */ if (first_xc <= 0) { sptr++; first_xc += _al_stretch.xcinc; } else first_xc -= _al_stretch.xcdec; dptr++; sptr += _al_stretch.sxinc; dw--; } } #endif #ifdef ALLEGRO_COLOR8 static void stretch_line8(uintptr_t dptr, unsigned char *sptr) { DECLARE_STRETCHER(unsigned char, 1, bmp_write8, *); } static void stretch_masked_line8(uintptr_t dptr, unsigned char *sptr) { DECLARE_MASKED_STRETCHER(unsigned char, 1, bmp_write8, *, 0); } #endif #ifdef ALLEGRO_COLOR16 static void stretch_line15(uintptr_t dptr, unsigned char* sptr) { DECLARE_STRETCHER(unsigned short, 2, bmp_write15, *); } static void stretch_line16(uintptr_t dptr, unsigned char* sptr) { DECLARE_STRETCHER(unsigned short, 2, bmp_write16, *); } static void stretch_masked_line15(uintptr_t dptr, unsigned char* sptr) { DECLARE_MASKED_STRETCHER(unsigned short, 2, bmp_write15, *, MASK_COLOR_15); } static void stretch_masked_line16(uintptr_t dptr, unsigned char* sptr) { DECLARE_MASKED_STRETCHER(unsigned short, 2, bmp_write16, *, MASK_COLOR_16); } #endif #ifdef ALLEGRO_COLOR24 static void stretch_line24(uintptr_t dptr, unsigned char* sptr) { DECLARE_STRETCHER(unsigned char, 3, bmp_write24, READ3BYTES); } static void stretch_masked_line24(uintptr_t dptr, unsigned char* sptr) { DECLARE_MASKED_STRETCHER(unsigned char, 3, bmp_write24, READ3BYTES, MASK_COLOR_24); } #endif #ifdef ALLEGRO_COLOR32 static void stretch_line32(uintptr_t dptr, unsigned char* sptr) { DECLARE_STRETCHER(uint32_t, 4, bmp_write32, *); } static void stretch_masked_line32(uintptr_t dptr, unsigned char* sptr) { DECLARE_MASKED_STRETCHER(uint32_t, 4, bmp_write32, *, MASK_COLOR_32); } #endif /* * Stretch blit work-horse. */ static void _al_stretch_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int masked) { int y; /* current dst y */ int yc; /* y counter */ int sxofs, dxofs; /* start offsets */ int syinc; /* amount to increment src y each time */ int ycdec; /* amount to deccrement counter by, increase sy when this reaches 0 */ int ycinc; /* amount to increment counter by when it reaches 0 */ int size = 0; /* pixel size */ int dxbeg, dxend; /* clipping information */ int dybeg, dyend; int i; void (*stretch_line)(uintptr_t, unsigned char*) = 0; ASSERT(src); ASSERT(dst); /* vtable hook; not called if dest is a memory surface */ if (src->vtable->do_stretch_blit && !is_memory_bitmap(dst)) { src->vtable->do_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, masked); return; } if ((sw <= 0) || (sh <= 0) || (dw <= 0) || (dh <= 0)) return; /* Find out which stretcher should be used */ if (masked) { switch (bitmap_color_depth(dst)) { #ifdef ALLEGRO_COLOR8 case 8: if (is_linear_bitmap(dst)) stretch_line = stretch_masked_line8; #ifdef ALLEGRO_GFX_HAS_VGA else stretch_line = stretch_masked_linex; #endif size = 1; break; #endif #ifdef ALLEGRO_COLOR16 case 15: stretch_line = stretch_masked_line15; size = 2; break; case 16: stretch_line = stretch_masked_line16; size = 2; break; #endif #ifdef ALLEGRO_COLOR24 case 24: stretch_line = stretch_masked_line24; size = 3; break; #endif #ifdef ALLEGRO_COLOR32 case 32: stretch_line = stretch_masked_line32; size = 4; break; #endif } } else { switch (bitmap_color_depth(dst)) { #ifdef ALLEGRO_COLOR8 case 8: if (is_linear_bitmap(dst)) stretch_line = stretch_line8; #ifdef ALLEGRO_GFX_HAS_VGA else stretch_line = stretch_linex; #endif size = 1; break; #endif #ifdef ALLEGRO_COLOR16 case 15: stretch_line = stretch_line15; size = 2; break; case 16: stretch_line = stretch_line16; size = 2; break; #endif #ifdef ALLEGRO_COLOR24 case 24: stretch_line = stretch_line24; size = 3; break; #endif #ifdef ALLEGRO_COLOR32 case 32: stretch_line = stretch_line32; size = 4; break; #endif } } ASSERT(stretch_line); if (dst->clip) { dybeg = ((dy > dst->ct) ? dy : dst->ct); dyend = (((dy + dh) < dst->cb) ? (dy + dh) : dst->cb); if (dybeg >= dyend) return; dxbeg = ((dx > dst->cl) ? dx : dst->cl); dxend = (((dx + dw) < dst->cr) ? (dx + dw) : dst->cr); if (dxbeg >= dxend) return; } else { dxbeg = dx; dxend = dx + dw; dybeg = dy; dyend = dy + dh; } syinc = sh / dh; ycdec = sh - (syinc*dh); ycinc = dh - ycdec; yc = ycinc; sxofs = sx * size; dxofs = dx * size; _al_stretch.sxinc = sw / dw * size; _al_stretch.xcdec = sw - ((sw/dw)*dw); _al_stretch.xcinc = dw - _al_stretch.xcdec; _al_stretch.linesize = (dxend-dxbeg)*size; /* get start state (clip) */ _al_stretch.xcstart = _al_stretch.xcinc; for (i = 0; i < dxbeg-dx; i++, sxofs += _al_stretch.sxinc) { if (_al_stretch.xcstart <= 0) { _al_stretch.xcstart += _al_stretch.xcinc; sxofs += size; } else _al_stretch.xcstart -= _al_stretch.xcdec; } dxofs += i * size; /* skip clipped lines */ for (y = dy; y < dybeg; y++, sy += syinc) { if (yc <= 0) { sy++; yc += ycinc; } else yc -= ycdec; } /* Stretch it */ bmp_select(dst); for (; y < dyend; y++, sy += syinc) { (*stretch_line)(bmp_write_line(dst, y) + dxofs, src->line[sy] + sxofs); if (yc <= 0) { sy++; yc += ycinc; } else yc -= ycdec; } bmp_unwrite_line(dst); } /* stretch_blit: * Opaque bitmap scaling function. */ void stretch_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh) { ASSERT(src); ASSERT(dst); #ifdef ALLEGRO_MPW if (is_system_bitmap(src) && is_system_bitmap(dst)) system_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh); else #endif _al_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, 0); } /* masked_stretch_blit: * Masked bitmap scaling function. */ void masked_stretch_blit(BITMAP *src, BITMAP *dst, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh) { ASSERT(src); ASSERT(dst); _al_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, 1); } /* stretch_sprite: * Masked version of stretch_blit(). */ void stretch_sprite(BITMAP *dst, BITMAP *src, int x, int y, int w, int h) { ASSERT(src); ASSERT(dst); _al_stretch_blit(src, dst, 0, 0, src->w, src->h, x, y, w, h, 1); } allegro-4.4.3.1/src/c/cdefs24.h0000664000175000017500000001274413437077643014724 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Defines for 24 bit color graphics primitives. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cdefs24_h #define __bma_cdefs24_h #define PP_DEPTH 24 #define PIXEL_PTR unsigned char* #define PTR_PER_PIXEL 3 #define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + 3 * (x)) #define INC_PIXEL_PTR(p) ((p) += 3) #define INC_PIXEL_PTR_N(p,d) ((p) += 3 * d) #define DEC_PIXEL_PTR(p) ((p) -= 3) #define PUT_PIXEL(p,c) bmp_write24((uintptr_t) (p), (c)) #define PUT_MEMORY_PIXEL(p,c) WRITE3BYTES((p), (c)) #define PUT_RGB(p,r,g,b) bmp_write24((uintptr_t) (p), makecol24((r), (g), (b))) #define GET_PIXEL(p) bmp_read24((uintptr_t) (p)) #define GET_MEMORY_PIXEL(p) READ3BYTES((p)) #define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_24) #define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == MASK_COLOR_24) /* Blender for putpixel (DRAW_MODE_TRANS). */ #define PP_BLENDER BLENDER_FUNC #define MAKE_PP_BLENDER(c) _blender_func24 #define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_trans_*_sprite. */ #define DTS_BLENDER BLENDER_FUNC #define MAKE_DTS_BLENDER() _blender_func24 #define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_lit_*_sprite. */ #define DLS_BLENDER BLENDER_FUNC #define MAKE_DLS_BLENDER(a) _blender_func24 #define DLS_BLEND(b,a,n) ((*(b))(_blender_col_24, (n), (a))) #define DLSX_BLEND(b,n) ((*(b))(_blender_col_24, (n), _blender_alpha)) /* Blender for RGBA sprites. */ #define RGBA_BLENDER BLENDER_FUNC #define MAKE_RGBA_BLENDER() _blender_func24x #define RGBA_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for poly_scanline_*_lit. */ #define PS_BLENDER BLENDER_FUNC #define MAKE_PS_BLENDER() _blender_func24 #define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_24, (o))) #define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) #define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ & _drawing_y_mask]) #define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ ((x) - _drawing_x_anchor) & _drawing_x_mask)) #define RLE_PTR int32_t* #define RLE_IS_EOL(c) ((unsigned long) (c) == MASK_COLOR_24) #define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color24 #define FUNC_LINEAR_BLIT _linear_blit24 #define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward24 #define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit24 #define FUNC_LINEAR_PUTPIXEL _linear_putpixel24 #define FUNC_LINEAR_GETPIXEL _linear_getpixel24 #define FUNC_LINEAR_HLINE _linear_hline24 #define FUNC_LINEAR_VLINE _linear_vline24 #define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite24 #define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex24 #define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite24 #define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip24 #define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip24 #define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip24 #define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite24 #define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite24 #define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite24 #define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character24 #define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite24 #define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite24 #define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite24 #define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite24 #define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite24_end #define FUNC_LINEAR_BLIT_END _linear_blit24_end #define FUNC_POLY_SCANLINE_GRGB _poly_scanline_grgb24 #define FUNC_POLY_SCANLINE_ATEX _poly_scanline_atex24 #define FUNC_POLY_SCANLINE_ATEX_MASK _poly_scanline_atex_mask24 #define FUNC_POLY_SCANLINE_ATEX_LIT _poly_scanline_atex_lit24 #define FUNC_POLY_SCANLINE_ATEX_MASK_LIT _poly_scanline_atex_mask_lit24 #define FUNC_POLY_SCANLINE_PTEX _poly_scanline_ptex24 #define FUNC_POLY_SCANLINE_PTEX_MASK _poly_scanline_ptex_mask24 #define FUNC_POLY_SCANLINE_PTEX_LIT _poly_scanline_ptex_lit24 #define FUNC_POLY_SCANLINE_PTEX_MASK_LIT _poly_scanline_ptex_mask_lit24 #define FUNC_POLY_SCANLINE_ATEX_TRANS _poly_scanline_atex_trans24 #define FUNC_POLY_SCANLINE_ATEX_MASK_TRANS _poly_scanline_atex_mask_trans24 #define FUNC_POLY_SCANLINE_PTEX_TRANS _poly_scanline_ptex_trans24 #define FUNC_POLY_SCANLINE_PTEX_MASK_TRANS _poly_scanline_ptex_mask_trans24 #endif /* !__bma_cdefs24_h */ allegro-4.4.3.1/src/c/cmiscs.s0000664000175000017500000000173513437077643014764 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Empty bank switch routines for DOS version. Should be used together * with C versions of GFX_VTABLE routines and ASM calling convention. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" .text /* empty bank switch routine for the standard VGA mode and memory bitmaps */ FUNC(_stub_bank_switch) movl BMP_LINE(%edx, %eax, 4), %eax ret FUNC(_stub_unbank_switch) ret FUNC(_stub_bank_switch_end) ret allegro-4.4.3.1/src/c/czscan32.c0000664000175000017500000000326513437077643015111 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR32 #include "allegro/internal/aintern.h" #include "cdefs32.h" #define FUNC_POLY_ZBUF_FLAT _poly_zbuf_flat32 #define FUNC_POLY_ZBUF_GRGB _poly_zbuf_grgb32 #define FUNC_POLY_ZBUF_ATEX _poly_zbuf_atex32 #define FUNC_POLY_ZBUF_ATEX_MASK _poly_zbuf_atex_mask32 #define FUNC_POLY_ZBUF_ATEX_LIT _poly_zbuf_atex_lit32 #define FUNC_POLY_ZBUF_ATEX_MASK_LIT _poly_zbuf_atex_mask_lit32 #define FUNC_POLY_ZBUF_PTEX _poly_zbuf_ptex32 #define FUNC_POLY_ZBUF_PTEX_MASK _poly_zbuf_ptex_mask32 #define FUNC_POLY_ZBUF_PTEX_LIT _poly_zbuf_ptex_lit32 #define FUNC_POLY_ZBUF_PTEX_MASK_LIT _poly_zbuf_ptex_mask_lit32 #define FUNC_POLY_ZBUF_ATEX_TRANS _poly_zbuf_atex_trans32 #define FUNC_POLY_ZBUF_ATEX_MASK_TRANS _poly_zbuf_atex_mask_trans32 #define FUNC_POLY_ZBUF_PTEX_TRANS _poly_zbuf_ptex_trans32 #define FUNC_POLY_ZBUF_PTEX_MASK_TRANS _poly_zbuf_ptex_mask_trans32 #undef _bma_zbuf_gcol #include "czscan.h" #endif allegro-4.4.3.1/src/c/cgfx.h0000664000175000017500000001431313437077643014413 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linear graphics functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cgfx_h #define __bma_cgfx_h /* _linear_putpixel: * Draws a pixel onto a linear bitmap. */ void FUNC_LINEAR_PUTPIXEL(BITMAP *dst, int dx, int dy, int color) { ASSERT(dst); if (dst->clip && ((dx < dst->cl) || (dx >= dst->cr) || (dy < dst->ct) || (dy >= dst->cb))) return; bmp_select(dst); if (_drawing_mode == DRAW_MODE_SOLID) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); PUT_PIXEL(d, color); } else if (_drawing_mode == DRAW_MODE_XOR) { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); unsigned long c = GET_PIXEL(s) ^ color; PUT_PIXEL(d, c); } else if (_drawing_mode == DRAW_MODE_TRANS) { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); PP_BLENDER blender = MAKE_PP_BLENDER(color); unsigned long c = PP_BLEND(blender, GET_PIXEL(s), color); PUT_PIXEL(d, c); } else { unsigned long c = GET_PATTERN_PIXEL(dx, dy); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx); if (_drawing_mode == DRAW_MODE_COPY_PATTERN) { PUT_PIXEL(d, c); } else if (_drawing_mode == DRAW_MODE_SOLID_PATTERN) { if (!IS_MASK(c)) { PUT_PIXEL(d, color); } else { PUT_PIXEL(d, c); } } else if (_drawing_mode == DRAW_MODE_MASKED_PATTERN) { if (!IS_MASK(c)) { PUT_PIXEL(d, color); } } } bmp_unwrite_line(dst); } /* _linear_getpixel: * Reads a pixel from a linear bitmap. */ int FUNC_LINEAR_GETPIXEL(BITMAP *src, int sx, int sy) { ASSERT(src); if ((sx < 0) || (sx >= src->w) || (sy < 0) || (sy >= src->h)) return -1; else { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(src, sy), sx); unsigned long c; bmp_select(src); c = GET_PIXEL(s); bmp_unwrite_line(src); return c; } } /* _linear_hline: * Draws a horizontal line onto a linear bitmap. */ void FUNC_LINEAR_HLINE(BITMAP *dst, int dx1, int dy, int dx2, int color) { int w; ASSERT(dst); if (dx1 > dx2) { int tmp = dx1; dx1 = dx2; dx2 = tmp; } if (dst->clip) { if (dx1 < dst->cl) dx1 = dst->cl; if (dx2 >= dst->cr) dx2 = dst->cr - 1; if ((dx1 > dx2) || (dy < dst->ct) || (dy >= dst->cb)) return; } w = dx2 - dx1; bmp_select(dst); if (_drawing_mode == DRAW_MODE_SOLID) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); do { PUT_PIXEL(d, color); INC_PIXEL_PTR(d); } while (--w >= 0); } else if (_drawing_mode == DRAW_MODE_XOR) { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx1); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); do { unsigned long c = GET_PIXEL(s) ^ color; PUT_PIXEL(d, c); INC_PIXEL_PTR(s); INC_PIXEL_PTR(d); } while (--w >= 0); } else if (_drawing_mode == DRAW_MODE_TRANS) { PIXEL_PTR s = OFFSET_PIXEL_PTR(bmp_read_line(dst, dy), dx1); PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); PP_BLENDER blender = MAKE_PP_BLENDER(color); do { unsigned long c = PP_BLEND(blender, GET_PIXEL(s), color); PUT_PIXEL(d, c); INC_PIXEL_PTR(s); INC_PIXEL_PTR(d); } while (--w >= 0); } else { int x, curw; PIXEL_PTR sline = PATTERN_LINE(dy); PIXEL_PTR s; PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dy), dx1); x = (dx1 - _drawing_x_anchor) & _drawing_x_mask; s = OFFSET_PIXEL_PTR(sline, x); w++; curw = _drawing_x_mask + 1 - x; if (curw > w) curw = w; if (_drawing_mode == DRAW_MODE_COPY_PATTERN) { do { w -= curw; do { unsigned long c = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, c); INC_PIXEL_PTR(s); INC_PIXEL_PTR(d); } while (--curw > 0); s = sline; curw = MIN(w, (int)_drawing_x_mask+1); } while (curw > 0); } else if (_drawing_mode == DRAW_MODE_SOLID_PATTERN) { do { w -= curw; do { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_MASK(c)) { PUT_PIXEL(d, color); } else { PUT_PIXEL(d, c); } INC_PIXEL_PTR(s); INC_PIXEL_PTR(d); } while (--curw > 0); s = sline; curw = MIN(w, (int)_drawing_x_mask+1); } while (curw > 0); } else if (_drawing_mode == DRAW_MODE_MASKED_PATTERN) { do { w -= curw; do { unsigned long c = GET_MEMORY_PIXEL(s); if (!IS_MASK(c)) { PUT_PIXEL(d, color); } INC_PIXEL_PTR(s); INC_PIXEL_PTR(d); } while (--curw > 0); s = sline; curw = MIN(w, (int)_drawing_x_mask+1); } while (curw > 0); } } bmp_unwrite_line(dst); } /* _linear_vline: * Draws a vertical line onto a linear bitmap. */ void FUNC_LINEAR_VLINE(BITMAP *dst, int dx, int dy1, int dy2, int color) { int y; ASSERT(dst); if (dy1 > dy2) { int tmp = dy1; dy1 = dy2; dy2 = tmp; } if (dst->clip) { if (dy1 < dst->ct) dy1 = dst->ct; if (dy2 >= dst->cb) dy2 = dst->cb - 1; if ((dx < dst->cl) || (dx >= dst->cr) || (dy1 > dy2)) return; } if (_drawing_mode == DRAW_MODE_SOLID) { bmp_select(dst); for (y = dy1; y <= dy2; y++) { PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, y), dx); PUT_PIXEL(d, color); } bmp_unwrite_line(dst); } else { int clip = dst->clip; dst->clip = 0; for (y = dy1; y <= dy2; y++) { FUNC_LINEAR_PUTPIXEL(dst, dx, y, color); } dst->clip = clip; } } #endif /* !__bma_cgfx_h */ allegro-4.4.3.1/src/c/cgfx24.c0000664000175000017500000000136213437077643014554 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit color linear graphics functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR24 #include "allegro/internal/aintern.h" #include "cdefs24.h" #include "cgfx.h" #endif allegro-4.4.3.1/src/c/cblit16.c0000664000175000017500000000131513437077643014721 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit color bitmap blitting functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "cdefs16.h" #include "cblit.h" #endif allegro-4.4.3.1/src/c/cscan24.c0000664000175000017500000000146113437077643014714 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR24 #undef _bma_scan_gcol #include "allegro/internal/aintern.h" #include "cdefs24.h" #include "cscan.h" #endif allegro-4.4.3.1/src/c/cgfx32.c0000664000175000017500000000136213437077643014553 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit color linear graphics functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR32 #include "allegro/internal/aintern.h" #include "cdefs32.h" #include "cgfx.h" #endif allegro-4.4.3.1/src/c/cspr16.c0000664000175000017500000000136113437077643014574 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 16 bit color sprite drawing functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "allegro/internal/aintern.h" #include "cdefs16.h" #include "cspr.h" #endif allegro-4.4.3.1/src/c/czscan24.c0000664000175000017500000000326513437077643015112 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR24 #include "allegro/internal/aintern.h" #include "cdefs24.h" #define FUNC_POLY_ZBUF_FLAT _poly_zbuf_flat24 #define FUNC_POLY_ZBUF_GRGB _poly_zbuf_grgb24 #define FUNC_POLY_ZBUF_ATEX _poly_zbuf_atex24 #define FUNC_POLY_ZBUF_ATEX_MASK _poly_zbuf_atex_mask24 #define FUNC_POLY_ZBUF_ATEX_LIT _poly_zbuf_atex_lit24 #define FUNC_POLY_ZBUF_ATEX_MASK_LIT _poly_zbuf_atex_mask_lit24 #define FUNC_POLY_ZBUF_PTEX _poly_zbuf_ptex24 #define FUNC_POLY_ZBUF_PTEX_MASK _poly_zbuf_ptex_mask24 #define FUNC_POLY_ZBUF_PTEX_LIT _poly_zbuf_ptex_lit24 #define FUNC_POLY_ZBUF_PTEX_MASK_LIT _poly_zbuf_ptex_mask_lit24 #define FUNC_POLY_ZBUF_ATEX_TRANS _poly_zbuf_atex_trans24 #define FUNC_POLY_ZBUF_ATEX_MASK_TRANS _poly_zbuf_atex_mask_trans24 #define FUNC_POLY_ZBUF_PTEX_TRANS _poly_zbuf_ptex_trans24 #define FUNC_POLY_ZBUF_PTEX_MASK_TRANS _poly_zbuf_ptex_mask_trans24 #undef _bma_zbuf_gcol #include "czscan.h" #endif allegro-4.4.3.1/src/c/cspr15.c0000664000175000017500000000136113437077643014573 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit color sprite drawing functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "allegro/internal/aintern.h" #include "cdefs15.h" #include "cspr.h" #endif allegro-4.4.3.1/src/c/cmisc.c0000664000175000017500000000274213437077643014560 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Math routines, etc. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_NO_ASM /* Empty bank switch routines. Should be used with C calling convention. */ uintptr_t _stub_bank_switch(BITMAP *bmp, int y) { return (uintptr_t)bmp->line[y]; } void _stub_unbank_switch(BITMAP *bmp) { } void _stub_bank_switch_end(void) { } #else /* * For ASM calling convention: * Unix version uses bank switch routines from src/i386/imisc.s. * DOS version uses bank switch routines from -#- or src/c/cmiscs.s. */ #endif /* apply_matrix_f: * Floating point vector by matrix multiplication routine. */ void apply_matrix_f(AL_CONST MATRIX_f *m, float x, float y, float z, float *xout, float *yout, float *zout) { #define CALC_ROW(n) (x * m->v[(n)][0] + y * m->v[(n)][1] + z * m->v[(n)][2] + m->t[(n)]) *xout = CALC_ROW(0); *yout = CALC_ROW(1); *zout = CALC_ROW(2); #undef CALC_ROW } allegro-4.4.3.1/src/c/cscan32.c0000664000175000017500000000146113437077643014713 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 32 bit color polygon scanline filler helpers (gouraud shading, tmapping, etc). * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR32 #undef _bma_scan_gcol #include "allegro/internal/aintern.h" #include "cdefs32.h" #include "cscan.h" #endif allegro-4.4.3.1/src/c/cblit24.c0000664000175000017500000000131513437077643014720 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit color bitmap blitting functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR24 #include "cdefs24.h" #include "cblit.h" #endif allegro-4.4.3.1/src/c/cdefs16.h0000664000175000017500000001274613437077643014727 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Defines for 16 bit color graphics primitives. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cdefs16_h #define __bma_cdefs16_h #define PP_DEPTH 16 #define PIXEL_PTR unsigned short* #define PTR_PER_PIXEL 1 #define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) #define INC_PIXEL_PTR(p) ((p)++) #define INC_PIXEL_PTR_N(p,d) ((p) += d) #define DEC_PIXEL_PTR(p) ((p)--) #define PUT_PIXEL(p,c) bmp_write16((uintptr_t) (p), (c)) #define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) #define PUT_RGB(p,r,g,b) bmp_write16((uintptr_t) (p), makecol16((r), (g), (b))) #define GET_PIXEL(p) bmp_read16((uintptr_t) (p)) #define GET_MEMORY_PIXEL(p) (*(p)) #define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_16) #define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == (unsigned long) (b)->vtable->mask_color) /* Blender for putpixel (DRAW_MODE_TRANS). */ #define PP_BLENDER BLENDER_FUNC #define MAKE_PP_BLENDER(c) _blender_func16 #define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_trans_*_sprite. */ #define DTS_BLENDER BLENDER_FUNC #define MAKE_DTS_BLENDER() _blender_func16 #define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_lit_*_sprite. */ #define DLS_BLENDER BLENDER_FUNC #define MAKE_DLS_BLENDER(a) _blender_func16 #define DLS_BLEND(b,a,n) ((*(b))(_blender_col_16, (n), (a))) #define DLSX_BLEND(b,n) ((*(b))(_blender_col_16, (n), _blender_alpha)) /* Blender for RGBA sprites. */ #define RGBA_BLENDER BLENDER_FUNC #define MAKE_RGBA_BLENDER() _blender_func16x #define RGBA_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for poly_scanline_*_lit. */ #define PS_BLENDER BLENDER_FUNC #define MAKE_PS_BLENDER() _blender_func16 #define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_16, (o))) #define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) #define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ & _drawing_y_mask]) #define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ ((x) - _drawing_x_anchor) & _drawing_x_mask)) #define RLE_PTR signed short* #define RLE_IS_EOL(c) ((unsigned short) (c) == MASK_COLOR_16) #define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color16 #define FUNC_LINEAR_BLIT _linear_blit16 #define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward16 #define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit16 #define FUNC_LINEAR_PUTPIXEL _linear_putpixel16 #define FUNC_LINEAR_GETPIXEL _linear_getpixel16 #define FUNC_LINEAR_HLINE _linear_hline16 #define FUNC_LINEAR_VLINE _linear_vline16 #define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite16 #define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex16 #define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite16 #define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip16 #define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip16 #define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip16 #define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite16 #define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite16 #define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite16 #define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character16 #define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite16 #define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite16 #define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite16 #define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite16 #define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite16_end #define FUNC_LINEAR_BLIT_END _linear_blit16_end #define FUNC_POLY_SCANLINE_GRGB _poly_scanline_grgb16 #define FUNC_POLY_SCANLINE_ATEX _poly_scanline_atex16 #define FUNC_POLY_SCANLINE_ATEX_MASK _poly_scanline_atex_mask16 #define FUNC_POLY_SCANLINE_ATEX_LIT _poly_scanline_atex_lit16 #define FUNC_POLY_SCANLINE_ATEX_MASK_LIT _poly_scanline_atex_mask_lit16 #define FUNC_POLY_SCANLINE_PTEX _poly_scanline_ptex16 #define FUNC_POLY_SCANLINE_PTEX_MASK _poly_scanline_ptex_mask16 #define FUNC_POLY_SCANLINE_PTEX_LIT _poly_scanline_ptex_lit16 #define FUNC_POLY_SCANLINE_PTEX_MASK_LIT _poly_scanline_ptex_mask_lit16 #define FUNC_POLY_SCANLINE_ATEX_TRANS _poly_scanline_atex_trans16 #define FUNC_POLY_SCANLINE_ATEX_MASK_TRANS _poly_scanline_atex_mask_trans16 #define FUNC_POLY_SCANLINE_PTEX_TRANS _poly_scanline_ptex_trans16 #define FUNC_POLY_SCANLINE_PTEX_MASK_TRANS _poly_scanline_ptex_mask_trans16 #endif /* !__bma_cdefs16_h */ allegro-4.4.3.1/src/c/cgfx15.c0000664000175000017500000000136213437077643014554 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 15 bit color linear graphics functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR16 #include "allegro/internal/aintern.h" #include "cdefs15.h" #include "cgfx.h" #endif allegro-4.4.3.1/src/c/cdefs32.h0000664000175000017500000001240013437077643014710 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Defines for 32 bit color graphics primitives. * * By Michael Bukin. * * See readme.txt for copyright information. */ #ifndef __bma_cdefs32_h #define __bma_cdefs32_h #define PP_DEPTH 32 #define PIXEL_PTR uint32_t* #define PTR_PER_PIXEL 1 #define OFFSET_PIXEL_PTR(p,x) ((PIXEL_PTR) (p) + (x)) #define INC_PIXEL_PTR(p) ((p)++) #define INC_PIXEL_PTR_N(p,d) ((p) += d) #define DEC_PIXEL_PTR(p) ((p)--) #define PUT_PIXEL(p,c) bmp_write32((uintptr_t) (p), (c)) #define PUT_MEMORY_PIXEL(p,c) (*(p) = (c)) #define PUT_RGB(p,r,g,b) bmp_write32((uintptr_t) (p), makecol32((r), (g), (b))) #define GET_PIXEL(p) bmp_read32((uintptr_t) (p)) #define GET_MEMORY_PIXEL(p) (*(p)) #define IS_MASK(c) ((unsigned long) (c) == MASK_COLOR_32) #define IS_SPRITE_MASK(b,c) ((unsigned long) (c) == MASK_COLOR_32) /* Blender for putpixel (DRAW_MODE_TRANS). */ #define PP_BLENDER BLENDER_FUNC #define MAKE_PP_BLENDER(c) _blender_func32 #define PP_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_trans_*_sprite. */ #define DTS_BLENDER BLENDER_FUNC #define MAKE_DTS_BLENDER() _blender_func32 #define DTS_BLEND(b,o,n) ((*(b))((n), (o), _blender_alpha)) /* Blender for draw_lit_*_sprite. */ #define DLS_BLENDER BLENDER_FUNC #define MAKE_DLS_BLENDER(a) _blender_func32 #define DLS_BLEND(b,a,n) ((*(b))(_blender_col_32, (n), (a))) #define DLSX_BLEND(b,n) ((*(b))(_blender_col_32, (n), _blender_alpha)) /* Blender for poly_scanline_*_lit. */ #define PS_BLENDER BLENDER_FUNC #define MAKE_PS_BLENDER() _blender_func32 #define PS_BLEND(b,o,c) ((*(b))((c), _blender_col_32, (o))) #define PS_ALPHA_BLEND(b,o,c) ((*(b))((o), (c), _blender_alpha)) #define PATTERN_LINE(y) (PIXEL_PTR) (_drawing_pattern->line[((y) - _drawing_y_anchor) \ & _drawing_y_mask]) #define GET_PATTERN_PIXEL(x,y) GET_MEMORY_PIXEL(OFFSET_PIXEL_PTR(PATTERN_LINE(y), \ ((x) - _drawing_x_anchor) & _drawing_x_mask)) #define RLE_PTR int32_t* #define RLE_IS_EOL(c) ((unsigned long) (c) == MASK_COLOR_32) #define FUNC_LINEAR_CLEAR_TO_COLOR _linear_clear_to_color32 #define FUNC_LINEAR_BLIT _linear_blit32 #define FUNC_LINEAR_BLIT_BACKWARD _linear_blit_backward32 #define FUNC_LINEAR_MASKED_BLIT _linear_masked_blit32 #define FUNC_LINEAR_PUTPIXEL _linear_putpixel32 #define FUNC_LINEAR_GETPIXEL _linear_getpixel32 #define FUNC_LINEAR_HLINE _linear_hline32 #define FUNC_LINEAR_VLINE _linear_vline32 #define FUNC_LINEAR_DRAW_SPRITE _linear_draw_sprite32 #define FUNC_LINEAR_DRAW_SPRITE_EX _linear_draw_sprite_ex32 #define FUNC_LINEAR_DRAW_256_SPRITE _linear_draw_256_sprite32 #define FUNC_LINEAR_DRAW_SPRITE_V_FLIP _linear_draw_sprite_v_flip32 #define FUNC_LINEAR_DRAW_SPRITE_H_FLIP _linear_draw_sprite_h_flip32 #define FUNC_LINEAR_DRAW_SPRITE_VH_FLIP _linear_draw_sprite_vh_flip32 #define FUNC_LINEAR_DRAW_TRANS_SPRITE _linear_draw_trans_sprite32 #define FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE _linear_draw_trans_rgba_sprite32 #define FUNC_LINEAR_DRAW_LIT_SPRITE _linear_draw_lit_sprite32 #define FUNC_LINEAR_DRAW_CHARACTER _linear_draw_character32 #define FUNC_LINEAR_DRAW_RLE_SPRITE _linear_draw_rle_sprite32 #define FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE _linear_draw_trans_rle_sprite32 #define FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE _linear_draw_trans_rgba_rle_sprite32 #define FUNC_LINEAR_DRAW_LIT_RLE_SPRITE _linear_draw_lit_rle_sprite32 #define FUNC_LINEAR_DRAW_SPRITE_END _linear_draw_sprite32_end #define FUNC_LINEAR_BLIT_END _linear_blit32_end #define FUNC_POLY_SCANLINE_GRGB _poly_scanline_grgb32 #define FUNC_POLY_SCANLINE_ATEX _poly_scanline_atex32 #define FUNC_POLY_SCANLINE_ATEX_MASK _poly_scanline_atex_mask32 #define FUNC_POLY_SCANLINE_ATEX_LIT _poly_scanline_atex_lit32 #define FUNC_POLY_SCANLINE_ATEX_MASK_LIT _poly_scanline_atex_mask_lit32 #define FUNC_POLY_SCANLINE_PTEX _poly_scanline_ptex32 #define FUNC_POLY_SCANLINE_PTEX_MASK _poly_scanline_ptex_mask32 #define FUNC_POLY_SCANLINE_PTEX_LIT _poly_scanline_ptex_lit32 #define FUNC_POLY_SCANLINE_PTEX_MASK_LIT _poly_scanline_ptex_mask_lit32 #define FUNC_POLY_SCANLINE_ATEX_TRANS _poly_scanline_atex_trans32 #define FUNC_POLY_SCANLINE_ATEX_MASK_TRANS _poly_scanline_atex_mask_trans32 #define FUNC_POLY_SCANLINE_PTEX_TRANS _poly_scanline_ptex_trans32 #define FUNC_POLY_SCANLINE_PTEX_MASK_TRANS _poly_scanline_ptex_mask_trans32 #endif /* !__bma_cdefs32_h */ allegro-4.4.3.1/src/c/cspr24.c0000664000175000017500000000136113437077643014573 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * 24 bit color sprite drawing functions. * * By Michael Bukin. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_COLOR24 #include "allegro/internal/aintern.h" #include "cdefs24.h" #include "cspr.h" #endif allegro-4.4.3.1/src/clip3df.c0000664000175000017500000001654213437077643014567 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The 3D polygon clipper. * * By Calin Andrian. * * See readme.txt for copyright information. */ #include "allegro.h" #define INT_NONE 0 #define INT_1COL 1 #define INT_3COL 2 #define INT_3COLP 4 #define INT_UV 8 /* point_inside: * Copies a vertex to the output table. */ #define point_inside(vv) \ { \ v3->x = v2->x; v3->y = v2->y; v3->z = v2->z; \ v3->u = v2->u; v3->v = v2->v; v3->c = v2->c; \ vv++; \ } /* point_interp_f: * Interpolates between v1 and v2, with slope "t", resulting vertex v3. */ #define point_interp_f(vv) \ { \ v3->x = (v2->x - v1->x) * t + v1->x; \ v3->y = (v2->y - v1->y) * t + v1->y; \ v3->z = (v2->z - v1->z) * t + v1->z; \ \ if (flags & INT_1COL) { \ v3->c = (int)((v2->c - v1->c) * t + v1->c); \ } \ else if (flags & INT_3COLP) { \ int bpp = bitmap_color_depth(screen); \ int r = (int)((getr_depth(bpp, v2->c) - getr_depth(bpp, v1->c)) * t + getr_depth(bpp, v1->c)); \ int g = (int)((getg_depth(bpp, v2->c) - getg_depth(bpp, v1->c)) * t + getg_depth(bpp, v1->c)); \ int b = (int)((getb_depth(bpp, v2->c) - getb_depth(bpp, v1->c)) * t + getb_depth(bpp, v1->c)); \ v3->c = makecol_depth(bpp, r&255, g&255, b&255); \ } \ else if (flags & INT_3COL) { \ int r = (int)(((v2->c & 0xFF0000) - (v1->c & 0xFF0000)) * t + (v1->c & 0xFF0000)); \ int g = (int)(((v2->c & 0x00FF00) - (v1->c & 0x00FF00)) * t + (v1->c & 0x00FF00)); \ int b = (int)(((v2->c & 0x0000FF) - (v1->c & 0x0000FF)) * t + (v1->c & 0x0000FF)); \ v3->c = (r & 0xFF0000) | (g & 0x00FF00) | (b & 0x0000FF); \ } \ if (flags & INT_UV) { \ v3->u = (v2->u - v1->u) * t + v1->u; \ v3->v = (v2->v - v1->v) * t + v1->v; \ } \ vv++; \ } /* clip3d_f: * Clips a 3D polygon against planes x = -z, x = z, y = -z, y = z, * z = min_z, z = max_z. If max_z <= min_z the z = max_z clipping is * not done. Type is the rendering style - POLYTYPE_*, vc is the * number of vertices, vtx contains the input vertices, vout will * receive the result, vtmp and out must be supplied for temporary * storage. The size of arrays vout, vtmp and out should be twice as * big as vtx. */ int clip3d_f(int type, float min_z, float max_z, int vc, AL_CONST V3D_f *vtx[], V3D_f *vout[], V3D_f *vtmp[], int out[]) { int i, j, vo, vt, flags; float t; V3D_f *v3; AL_CONST V3D_f *v1, *v2, **vin; static int flag_table[] = { INT_NONE, /* flat */ INT_3COLP, /* gcol */ INT_3COL, /* grgb */ INT_UV, /* atex */ INT_UV, /* ptex */ INT_UV, /* atex mask */ INT_UV, /* ptex mask */ INT_UV + INT_1COL, /* atex lit */ INT_UV + INT_1COL, /* ptex lit */ INT_UV + INT_1COL, /* atex mask lit */ INT_UV + INT_1COL, /* ptex mask lit */ INT_UV, /* atex trans */ INT_UV, /* ptex trans */ INT_UV, /* atex mask trans */ INT_UV /* ptex mask trans */ }; type &= ~POLYTYPE_ZBUF; flags = flag_table[type]; if (max_z > min_z) { vt = 0; for (i=0; iz > max_z); for (i=0, j=vc-1; iz) / (v2->z - v1->z); point_interp_f(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vin = (AL_CONST V3D_f**)vtmp; } else { vt = vc; vin = vtx; } vo = 0; for (i=0; iz < min_z); for (i=0, j=vt-1; iz) / (v2->z - v1->z); point_interp_f(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } vt = 0; for (i=0; ix < -vout[i]->z); for (i=0, j=vo-1; iz - v1->x) / (v2->x - v1->x + v2->z - v1->z); point_interp_f(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vo = 0; for (i=0; ix > vtmp[i]->z); for (i=0, j=vt-1; iz - v1->x) / (v2->x - v1->x - v2->z + v1->z); point_interp_f(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } vt = 0; for (i=0; iy < -vout[i]->z); for (i=0, j=vo-1; iz - v1->y) / (v2->y - v1->y + v2->z - v1->z); point_interp_f(vt); v3 = vtmp[vt]; if (out[j]) point_inside(vt); } vo = 0; for (i=0; iy > vtmp[i]->z); for (i=0, j=vt-1; iz - v1->y) / (v2->y - v1->y - v2->z + v1->z); point_interp_f(vo); v3 = vout[vo]; if (out[j]) point_inside(vo); } if (type == POLYTYPE_FLAT) vout[0]->c = vtx[0]->c; return vo; } allegro-4.4.3.1/src/modesel.c0000664000175000017500000005600313437077643014667 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * GUI routines. * * The graphics mode selection dialog. * * By Shawn Hargreaves. * * Rewritten by Henrik Stokseth. * * Magnus Henoch modified it to keep the current selection * across the changes as much as possible. * * gfx_mode_select_filter() added by Vincent Penquerc'h. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" static AL_CONST char *gfx_mode_getter(int index, int *list_size); static AL_CONST char *gfx_card_getter(int index, int *list_size); static AL_CONST char *gfx_depth_getter(int index, int *list_size); static int change_proc(int msg, DIALOG *d, int c); #define ALL_BPP(w, h) { w, h, { TRUE, TRUE, TRUE, TRUE, TRUE }} #define N_COLOR_DEPTH 5 static int bpp_value_list[N_COLOR_DEPTH] = {8, 15, 16, 24, 32}; typedef struct MODE_LIST { int w, h; char has_bpp[N_COLOR_DEPTH]; } MODE_LIST; #define DRVNAME_SIZE 128 typedef struct DRIVER_LIST { int id; char name[DRVNAME_SIZE]; int mode_list_owned; MODE_LIST *mode_list; int mode_count; } DRIVER_LIST; static MODE_LIST default_mode_list[] = { ALL_BPP(320, 200 ), ALL_BPP(320, 240 ), ALL_BPP(640, 400 ), ALL_BPP(640, 480 ), ALL_BPP(800, 600 ), ALL_BPP(1024, 768 ), ALL_BPP(1280, 960 ), ALL_BPP(1280, 1024), ALL_BPP(1600, 1200), ALL_BPP(80, 80 ), ALL_BPP(160, 120 ), ALL_BPP(256, 200 ), ALL_BPP(256, 224 ), ALL_BPP(256, 240 ), ALL_BPP(256, 256 ), ALL_BPP(320, 100 ), ALL_BPP(320, 350 ), ALL_BPP(320, 400 ), ALL_BPP(320, 480 ), ALL_BPP(320, 600 ), ALL_BPP(360, 200 ), ALL_BPP(360, 240 ), ALL_BPP(360, 270 ), ALL_BPP(360, 360 ), ALL_BPP(360, 400 ), ALL_BPP(360, 480 ), ALL_BPP(360, 600 ), ALL_BPP(376, 282 ), ALL_BPP(376, 308 ), ALL_BPP(376, 564 ), ALL_BPP(400, 150 ), ALL_BPP(400, 300 ), ALL_BPP(400, 600 ), ALL_BPP(0, 0 ) }; typedef int (*FILTER_FUNCTION)(int, int, int, int); static DRIVER_LIST *driver_list; static int driver_count; static char mode_string[64]; static DIALOG *what_dialog; static DIALOG gfx_mode_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { _gui_shadow_box_proc, 0, 0, 313, 159, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { change_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { _gui_ctext_proc, 156, 8, 1, 1, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 196, 105, 101, 17, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 196, 127, 101, 17, 0, 0, 27, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_list_proc, 16, 28, 165, 116, 0, 0, 0, D_EXIT, 0, 0, (void*)gfx_card_getter, NULL, NULL }, { _gui_list_proc, 196, 28, 101, 68, 0, 0, 0, D_EXIT, 3, 0, (void*)gfx_mode_getter, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; static DIALOG gfx_mode_ex_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { _gui_shadow_box_proc, 0, 0, 313, 159, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { change_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { _gui_ctext_proc, 156, 8, 1, 1, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 196, 105, 101, 17, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 196, 127, 101, 17, 0, 0, 27, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_list_proc, 16, 28, 165, 68, 0, 0, 0, D_EXIT, 0, 0, (void*)gfx_card_getter, NULL, NULL }, { _gui_list_proc, 196, 28, 101, 68, 0, 0, 0, D_EXIT, 3, 0, (void*)gfx_mode_getter, NULL, NULL }, { _gui_list_proc, 16, 105, 165, 44, 0, 0, 0, D_EXIT, 0, 0, (void*)gfx_depth_getter, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; #define GFX_CHANGEPROC 1 #define GFX_TITLE 2 #define GFX_OK 3 #define GFX_CANCEL 4 #define GFX_DRIVERLIST 5 #define GFX_MODELIST 6 #define GFX_DEPTHLIST 7 /* bpp_value: * Returns the bpp value of the color depth pointed to by INDEX. */ static INLINE int bpp_value(int index) { ASSERT(index < N_COLOR_DEPTH); return bpp_value_list[index]; } /* bpp_value_for_mode: * Returns the bpp value of the color depth pointed to by INDEX * for the specified MODE of the specified DRIVER or -1 if INDEX * is out of bound. */ static int bpp_value_for_mode(int index, int driver, int mode) { int i, j = -1; ASSERT(index < N_COLOR_DEPTH); for (i=0; i < N_COLOR_DEPTH; i++) { if (driver_list[driver].mode_list[mode].has_bpp[i]) { if (++j == index) return bpp_value(i); } } return -1; } /* bpp_index: * Returns the bpp index of the color depth given by DEPTH. */ static int bpp_index(int depth) { int i; for (i=0; i < N_COLOR_DEPTH; i++) { if (bpp_value_list[i] == depth) return i; } ASSERT(FALSE); return -1; } /* bpp_index_for_mode: * Returns the bpp index of the color depth given by DEPTH for * the specified MODE of the specified DRIVER or -1 if DEPTH * is not supported. */ static int bpp_index_for_mode(int depth, int driver, int mode) { int i, index = -1; for (i=0; i < N_COLOR_DEPTH; i++) { if (driver_list[driver].mode_list[mode].has_bpp[i]) { index++; if (bpp_value_list[i] == depth) return index; } } return -1; } /* change_proc: * Stores the current driver in d1 and graphics mode in d2; if a new * driver is selected in the listbox, it updates the resolution and * color depth listboxes so that they redraw; if a new resolution is * selected in the listbox, it updates the color depth listbox. The * current selection is kept across the changes as much as possible. */ static int change_proc(int msg, DIALOG *d, int c) { int width = driver_list[d->d1].mode_list[d->d2].w; int height = driver_list[d->d1].mode_list[d->d2].h; int depth = bpp_value_for_mode(what_dialog[GFX_DEPTHLIST].d1, d->d1, d->d2); int i; ASSERT(d); if (msg != MSG_IDLE) return D_O_K; if (what_dialog[GFX_DRIVERLIST].d1 != d->d1) { /* record the new setting */ d->d1 = what_dialog[GFX_DRIVERLIST].d1; /* try to preserve the resolution */ what_dialog[GFX_MODELIST].d1 = 0; for (i = 0; i < driver_list[d->d1].mode_count; i++) { if (driver_list[d->d1].mode_list[i].w == width && driver_list[d->d1].mode_list[i].h == height) { what_dialog[GFX_MODELIST].d1 = i; break; } } what_dialog[GFX_MODELIST].d2 = 0; object_message(&what_dialog[GFX_MODELIST], MSG_DRAW, 0); /* record the new setting */ d->d2 = what_dialog[GFX_MODELIST].d1; if (what_dialog == gfx_mode_ex_dialog) { /* try to preserve the color depth */ what_dialog[GFX_DEPTHLIST].d1 = bpp_index_for_mode(depth, d->d1, d->d2); if (what_dialog[GFX_DEPTHLIST].d1 < 0) what_dialog[GFX_DEPTHLIST].d1 = 0; what_dialog[GFX_DEPTHLIST].d2 = 0; object_message(&what_dialog[GFX_DEPTHLIST], MSG_DRAW, 0); } } if (what_dialog[GFX_MODELIST].d1 != d->d2) { /* record the new setting */ d->d2 = what_dialog[GFX_MODELIST].d1; if (what_dialog == gfx_mode_ex_dialog) { /* try to preserve the color depth */ what_dialog[GFX_DEPTHLIST].d1 = bpp_index_for_mode(depth, d->d1, d->d2); if (what_dialog[GFX_DEPTHLIST].d1 < 0) what_dialog[GFX_DEPTHLIST].d1 = 0; what_dialog[GFX_DEPTHLIST].d2 = 0; object_message(&what_dialog[GFX_DEPTHLIST], MSG_DRAW, 0); } } return D_O_K; } /* add_mode: * Helper function for adding a mode to a mode list. * Returns 0 on success and -1 on failure. */ static int add_mode(MODE_LIST **list, int *size, int w, int h, int bpp) { int mode, n; /* Resolution already there? */ for (mode = 0; mode < *size; mode++) { if ((w == (*list)[mode].w) && (h == (*list)[mode].h)) { (*list)[mode].has_bpp[bpp_index(bpp)] = TRUE; return 0; } } /* Add new resolution. */ *list = _al_sane_realloc(*list, sizeof(MODE_LIST) * ++(*size)); if (!list) return -1; mode = *size - 1; (*list)[mode].w = w; (*list)[mode].h = h; for (n = 0; n < N_COLOR_DEPTH; n++) (*list)[mode].has_bpp[n] = (bpp == bpp_value(n)); return 0; } /* terminate_list: * Helper function for terminating a mode list. */ static int terminate_list(MODE_LIST **list, int size) { *list = _al_sane_realloc(*list, sizeof(MODE_LIST) * (size + 1)); if (!list) return -1; /* Add terminating marker. */ (*list)[size].w = 0; (*list)[size].h = 0; return 0; } /* create_mode_list: * Creates a mode list table. * Returns 0 on success and -1 on failure. */ static int create_mode_list(DRIVER_LIST *driver_list_entry, FILTER_FUNCTION filter) { MODE_LIST *temp_mode_list = NULL; GFX_MODE_LIST *gfx_mode_list; GFX_MODE *gfx_mode_entry; int mode, n, w, h, bpp; int is_autodetected = ((driver_list_entry->id == GFX_AUTODETECT) || (driver_list_entry->id == GFX_AUTODETECT_WINDOWED) || (driver_list_entry->id == GFX_AUTODETECT_FULLSCREEN)); /* Start with zero modes. */ driver_list_entry->mode_count = 0; /* We use the default mode list in two cases: * - the driver is GFX_AUTODETECT*, * - the driver doesn't support get_gfx_mode_list(). */ if (is_autodetected || !(gfx_mode_list = get_gfx_mode_list(driver_list_entry->id))) { /* Simply return the default mode list if we can. */ if (!filter) { driver_list_entry->mode_count = sizeof(default_mode_list) / sizeof(MODE_LIST) - 1; driver_list_entry->mode_list = default_mode_list; driver_list_entry->mode_list_owned = FALSE; return 0; } /* Build mode list from the default list. */ for (mode = 0; default_mode_list[mode].w; mode++) { w = default_mode_list[mode].w; h = default_mode_list[mode].h; for (n = 0; n < N_COLOR_DEPTH; n++) { bpp = bpp_value(n); if (filter(driver_list_entry->id, w, h, bpp) == 0) { if (add_mode(&temp_mode_list, &driver_list_entry->mode_count, w, h, bpp) != 0) return -1; } } } /* We should not terminate the list if the list is empty since the caller * of this function will simply discard this driver_list entry in that * case. */ if (driver_list_entry->mode_count > 0) { if (terminate_list(&temp_mode_list, driver_list_entry->mode_count) != 0) return -1; } driver_list_entry->mode_list = temp_mode_list; driver_list_entry->mode_list_owned = TRUE; return 0; } /* Build mode list from the fetched list. */ for (gfx_mode_entry = gfx_mode_list->mode; gfx_mode_entry->width; gfx_mode_entry++) { w = gfx_mode_entry->width; h = gfx_mode_entry->height; bpp = gfx_mode_entry->bpp; if (!filter || filter(driver_list_entry->id, w, h, bpp) == 0) { if (add_mode(&temp_mode_list, &driver_list_entry->mode_count, w, h, bpp) != 0) { destroy_gfx_mode_list(gfx_mode_list); return -1; } } } if (driver_list_entry->mode_count > 0) { if (terminate_list(&temp_mode_list, driver_list_entry->mode_count) != 0) { destroy_gfx_mode_list(gfx_mode_list); return -1; } } driver_list_entry->mode_list = temp_mode_list; driver_list_entry->mode_list_owned = TRUE; destroy_gfx_mode_list(gfx_mode_list); return 0; } /* create_driver_list: * Fills the list of video cards with info about the available drivers. * Returns -1 on failure. */ static int create_driver_list(FILTER_FUNCTION filter) { _DRIVER_INFO *driver_info; GFX_DRIVER *gfx_driver; int i; int list_pos; if (system_driver->gfx_drivers) driver_info = system_driver->gfx_drivers(); else driver_info = _gfx_driver_list; driver_list = _AL_MALLOC(sizeof(DRIVER_LIST) * 3); if (!driver_list) return -1; list_pos = 0; driver_list[list_pos].id = GFX_AUTODETECT; ustrzcpy(driver_list[list_pos].name, DRVNAME_SIZE, get_config_text("Autodetect")); create_mode_list(&driver_list[list_pos], filter); if (driver_list[list_pos].mode_count > 0) list_pos++; driver_list[list_pos].id = GFX_AUTODETECT_FULLSCREEN; ustrzcpy(driver_list[list_pos].name, DRVNAME_SIZE, get_config_text("Auto fullscreen")); create_mode_list(&driver_list[list_pos], filter); if (driver_list[list_pos].mode_count > 0) list_pos++; driver_list[list_pos].id = GFX_AUTODETECT_WINDOWED; ustrzcpy(driver_list[list_pos].name, DRVNAME_SIZE, get_config_text("Auto windowed")); create_mode_list(&driver_list[list_pos], filter); if (driver_list[list_pos].mode_count > 0) list_pos++; for (i = 0; driver_info[i].driver; i++) { driver_list = _al_sane_realloc(driver_list, sizeof(DRIVER_LIST) * (list_pos + 1)); if (!driver_list) return -1; driver_list[list_pos].id = driver_info[i].id; gfx_driver = driver_info[i].driver; do_uconvert(gfx_driver->ascii_name, U_ASCII, driver_list[list_pos].name, U_CURRENT, DRVNAME_SIZE); create_mode_list(&driver_list[list_pos], filter); if (driver_list[list_pos].mode_count > 0) { list_pos++; } else { ASSERT(driver_list[list_pos].mode_list == NULL); } } /* update global variable */ driver_count = list_pos; return 0; } /* destroy_driver_list: * Frees allocated memory used by driver lists and mode lists. */ static void destroy_driver_list(void) { int driver; for (driver=0; driver < driver_count; driver++) { if (driver_list[driver].mode_list_owned) _AL_FREE(driver_list[driver].mode_list); } _AL_FREE(driver_list); driver_list = NULL; driver_count = 0; } /* gfx_card_getter: * Listbox data getter routine for the graphics card list. */ static AL_CONST char *gfx_card_getter(int index, int *list_size) { if (index < 0) { if (list_size) *list_size = driver_count; return NULL; } return driver_list[index].name; } /* gfx_mode_getter: * Listbox data getter routine for the graphics mode list. */ static AL_CONST char *gfx_mode_getter(int index, int *list_size) { int entry; char tmp[32]; entry = what_dialog[GFX_DRIVERLIST].d1; if (index < 0) { if (list_size) { *list_size = driver_list[entry].mode_count; return NULL; } } uszprintf(mode_string, sizeof(mode_string), uconvert_ascii("%ix%i", tmp), driver_list[entry].mode_list[index].w, driver_list[entry].mode_list[index].h); return mode_string; } /* gfx_depth_getter: * Listbox data getter routine for the color depth list. */ static AL_CONST char *gfx_depth_getter(int index, int *list_size) { static char *bpp_string_list[N_COLOR_DEPTH] = {"256", "32K", "64K", "16M", "16M"}; MODE_LIST *mode; int card_entry, mode_entry, bpp_entry, bpp_count, bpp_index; char tmp[128]; card_entry = what_dialog[GFX_DRIVERLIST].d1; mode_entry = what_dialog[GFX_MODELIST].d1; mode = &driver_list[card_entry].mode_list[mode_entry]; if (index < 0) { if (list_size) { /* Count the number of BPP entries for the mode. */ for (bpp_count = 0, bpp_entry = 0; bpp_entry < N_COLOR_DEPTH; bpp_entry++) { if (mode->has_bpp[bpp_entry]) bpp_count++; } *list_size = bpp_count; return NULL; } } /* Find the BPP entry for the mode corresponding to the zero-based index. */ bpp_index = -1; bpp_entry = -1; while (bpp_index < index) { if (mode->has_bpp[++bpp_entry]) bpp_index++; } uszprintf(mode_string, sizeof(mode_string), uconvert_ascii("%2d ", tmp), bpp_value(bpp_entry)); ustrzcat(mode_string, sizeof(mode_string), get_config_text("bpp")); ustrzcat(mode_string, sizeof(mode_string), uconvert_ascii(" (", tmp)); ustrzcat(mode_string, sizeof(mode_string), uconvert_ascii(bpp_string_list[bpp_entry], tmp)); ustrzcat(mode_string, sizeof(mode_string), uconvert_ascii(" ", tmp)); ustrzcat(mode_string, sizeof(mode_string), get_config_text("colors")); ustrzcat(mode_string, sizeof(mode_string), uconvert_ascii(")", tmp)); return mode_string; } /* gfx_mode_select_filter: * Extended version of the graphics mode selection dialog, which allows the * user to select the color depth as well as the resolution and hardware * driver. An optional filter can be passed to check whether a particular * entry should be displayed or not. Initial values for the selections may be * given at the addresses passed to the function, and the user's selection * will be stored at those addresses if the dialog is OK'd. Initial values * at the addresses passed to the function may be set to 0 or -1 to indicate * not to search for the values but to default to the first entries in each * selection list. * In the case of an error, *card is set to GFX_NONE and FALSE is returned. * In the case that the filter filtered out all of the modes, *card is set to * GFX_NONE and TRUE is returned. */ int gfx_mode_select_filter(int *card, int *w, int *h, int *color_depth, FILTER_FUNCTION filter) { int i, ret, what_driver, what_mode, what_bpp, extd; MODE_LIST* mode_iter; ASSERT(card); ASSERT(w); ASSERT(h); clear_keybuf(); extd = color_depth ? TRUE : FALSE; while (gui_mouse_b()); what_dialog = extd ? gfx_mode_ex_dialog : gfx_mode_dialog; what_dialog[GFX_TITLE].dp = (void*)get_config_text("Graphics Mode"); what_dialog[GFX_OK].dp = (void*)get_config_text("OK"); what_dialog[GFX_CANCEL].dp = (void*)get_config_text("Cancel"); ret = create_driver_list(filter); if (ret == -1) { *card = GFX_NONE; return FALSE; } if (!driver_count) { *card = GFX_NONE; return TRUE; } /* The data stored at the addresses passed to this function is used to * search for initial selections in the dialog lists. If the requested * entries are not found, default to the first selection in each list in * order of the driver, the mode w/h, and also the color depth when in * extended mode (called directly or from gfx_mode_select_ex). */ /* Check for the user suggested driver first */ what_driver = 0;/* Default to first entry if not found */ /* Don't search for initial values if *card is 0 or -1 */ if (!((*card == 0) || (*card == -1))) { for (i = 0 ; i < driver_count ; ++i) { if (driver_list[i].id == *card) { what_driver = i; } } } what_dialog[GFX_DRIVERLIST].d1 = what_driver; what_dialog[GFX_CHANGEPROC].d1 = what_driver; /* Check for suggested resolution dimensions second */ what_mode = 0;/* Default to first entry if not found */ mode_iter = &(driver_list[what_driver].mode_list[0]); /* Don't search for initial values if *w or *h is 0 or -1 */ if (!(((*w == 0) || (*w == -1)) || ((*h == 0) || (*h == -1)))) { for (i = 0 ; i < driver_list[what_driver].mode_count ; ++i) { if ((mode_iter->w == *w) && (mode_iter->h == *h)) { what_mode = i; break; } ++mode_iter; } } what_dialog[GFX_MODELIST].d1 = what_mode; what_dialog[GFX_CHANGEPROC].d2 = what_mode; /* Check for suggested color depth when in extended mode */ if (extd) { what_bpp = 0; /* Don't search for initial values if *color_depth is 0 or -1 */ if (!((*color_depth == 0) || (*color_depth == -1))) { what_bpp = bpp_index_for_mode(*color_depth , what_driver , what_mode); if (what_bpp < 0) {what_bpp = 0;} /* Default to first entry if not found */ } what_dialog[GFX_DEPTHLIST].d1 = what_bpp; } centre_dialog(what_dialog); set_dialog_color(what_dialog, gui_fg_color, gui_bg_color); ret = popup_dialog(what_dialog, GFX_DRIVERLIST); what_driver = what_dialog[GFX_DRIVERLIST].d1; what_mode = what_dialog[GFX_MODELIST].d1; if (extd) what_bpp = what_dialog[GFX_DEPTHLIST].d1; else what_bpp = 0; if (ret != GFX_CANCEL) { *card = driver_list[what_driver].id; *w = driver_list[what_driver].mode_list[what_mode].w; *h = driver_list[what_driver].mode_list[what_mode].h; if (extd) { *color_depth = bpp_value_for_mode(what_bpp, what_driver, what_mode); } } destroy_driver_list(); if (ret == GFX_CANCEL) return FALSE; else return TRUE; } /* gfx_mode_select_ex: * Extended version of the graphics mode selection dialog, which allows the * user to select the color depth as well as the resolution and hardware * driver. Initial values for the selections will be looked for at the * addresses passed to the function, and selections will be stored there if * the user does not cancel the dialog. See gfx_mode_select_filter for * details and return values. */ int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth) { ASSERT(card); ASSERT(w); ASSERT(h); ASSERT(color_depth); return gfx_mode_select_filter(card, w, h, color_depth, NULL); } /* gfx_mode_select: * Displays the Allegro graphics mode selection dialog, which allows the * user to select a screen mode and graphics card. Initial values for the * selection will be looked for at the addresses passed to the function, and * the selection will be stored in the three variables if the dialog is not * cancelled. See gfx_mode_select_filter for details and return values. */ int gfx_mode_select(int *card, int *w, int *h) { ASSERT(card); ASSERT(w); ASSERT(h); return gfx_mode_select_filter(card, w, h, NULL, NULL); } allegro-4.4.3.1/src/joystick.c0000664000175000017500000001672313437077643015103 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * High level joystick input framework. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* dummy driver for when no joystick is present */ static int nojoy_ret0(void) { return 0; } static void nojoy_void(void) { } JOYSTICK_DRIVER joystick_none = { JOY_TYPE_NONE, empty_string, empty_string, "No joystick", nojoy_ret0, nojoy_void, nojoy_ret0, NULL, NULL, NULL, NULL }; int _joystick_installed = FALSE; JOYSTICK_DRIVER *joystick_driver = NULL; int _joy_type = JOY_TYPE_NONE; JOYSTICK_INFO joy[MAX_JOYSTICKS]; int num_joysticks = 0; static int joy_loading = FALSE; /* clear_joystick_vars: * Resets the joystick state variables to their default values. */ static void clear_joystick_vars(void) { AL_CONST char *unused = get_config_text("unused"); int i, j, k; #define ARRAY_SIZE(a) ((int)sizeof((a)) / (int)sizeof((a)[0])) for (i=0; ijoystick_drivers) driver_list = system_driver->joystick_drivers(); else driver_list = _joystick_driver_list; /* search table for a specific driver */ for (c=0; driver_list[c].driver; c++) { if (driver_list[c].id == type) { joystick_driver = driver_list[c].driver; joystick_driver->name = joystick_driver->desc = get_config_text(joystick_driver->ascii_name); _joy_type = type; if (joystick_driver->init() != 0) { if (!ugetc(allegro_error)) uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s not found"), joystick_driver->name); joystick_driver = NULL; _joy_type = JOY_TYPE_NONE; return -1; } break; } } /* autodetect driver */ if (!joystick_driver) { if (!joy_loading) { if (load_joystick_data(NULL) != -1) return 0; } for (c=0; driver_list[c].driver; c++) { if (driver_list[c].autodetect) { joystick_driver = driver_list[c].driver; joystick_driver->name = joystick_driver->desc = get_config_text(joystick_driver->ascii_name); _joy_type = driver_list[c].id; if (joystick_driver->init() == 0) break; } } } if (!driver_list[c].driver) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("No joysticks found")); return -1; } for (c=0; cexit(); joystick_driver = NULL; _joy_type = JOY_TYPE_NONE; clear_joystick_vars(); _remove_exit_func(remove_joystick); _joystick_installed = FALSE; } } /* poll_joystick: * Reads the current input state into the joystick status variables. */ int poll_joystick(void) { if ((joystick_driver) && (joystick_driver->poll)) return joystick_driver->poll(); return -1; } /* save_joystick_data: * After calibrating a joystick, this function can be used to save the * information into the specified file, from where it can later be * restored by calling load_joystick_data(). */ int save_joystick_data(AL_CONST char *filename) { char tmp1[64], tmp2[64]; if (filename) { push_config_state(); set_config_file(filename); } set_config_id(uconvert_ascii("joystick", tmp1), uconvert_ascii("joytype", tmp2), _joy_type); if ((joystick_driver) && (joystick_driver->save_data)) joystick_driver->save_data(); if (filename) pop_config_state(); return 0; } /* load_joystick_data: * Restores a set of joystick calibration data previously saved by * save_joystick_data(). */ int load_joystick_data(AL_CONST char *filename) { char tmp1[64], tmp2[64]; int ret, c; joy_loading = TRUE; if (_joystick_installed) remove_joystick(); if (filename) { push_config_state(); set_config_file(filename); } _joy_type = get_config_id(uconvert_ascii("joystick", tmp1), uconvert_ascii("joytype", tmp2), -1); if (_joy_type < 0) { _joy_type = JOY_TYPE_NONE; ret = -1; } else { ret = install_joystick(_joy_type); if (ret == 0) { if (joystick_driver->load_data) ret = joystick_driver->load_data(); } else ret = -2; } if (filename) pop_config_state(); if (ret == 0) { for (c=0; ccalibrate_name) || (!(joy[n].flags & JOYFLAG_CALIBRATE))) return NULL; return joystick_driver->calibrate_name(n); } /* calibrate_joystick: * Performs the next caliabration operation required for the specified stick. */ int calibrate_joystick(int n) { int ret; if ((!joystick_driver) || (!joystick_driver->calibrate) || (!(joy[n].flags & JOYFLAG_CALIBRATE))) return -1; ret = joystick_driver->calibrate(n); if (ret == 0) update_calib(n); return ret; } /* initialise_joystick: * Bodge function to preserve backward compatibility with the old API. */ int initialise_joystick(void) { int type = _joy_type; if (_joystick_installed) remove_joystick(); #ifdef JOY_TYPE_STANDARD if (type == JOY_TYPE_NONE) type = JOY_TYPE_STANDARD; #endif return install_joystick(type); } allegro-4.4.3.1/src/allegro.c0000664000175000017500000005231213437077643014663 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Assorted globals and setup/cleanup routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #define PREFIX_I "al-main INFO: " #define PREFIX_W "al-main WARNING: " #define PREFIX_E "al-main ERROR: " #ifdef ALLEGRO_AMIGA #define LOGFILE "RAM:allegro.log" #else #define LOGFILE "allegro.log" #endif /* in case you want to report version numbers */ char allegro_id[] = "Allegro " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR; /* error message for sound and gfx init routines */ char allegro_error[ALLEGRO_ERROR_SIZE] = EMPTY_STRING; /* current system driver */ SYSTEM_DRIVER *system_driver = NULL; /* error value, which will work even with DLL linkage */ int *allegro_errno = NULL; /* flag for how many times we have been initialised */ int _allegro_count = 0; /* flag to know whether we are being called by the exit mechanism */ int _allegro_in_exit = FALSE; /* flag to decide whether to disable the screensaver */ int _screensaver_policy = FULLSCREEN_DISABLED; /* the graphics driver currently in use */ GFX_DRIVER *gfx_driver = NULL; /* abilities of the current graphics driver */ int gfx_capabilities = 0; /* a bitmap structure for accessing the physical screen */ BITMAP *screen = NULL; /* info about the current graphics drawing mode */ int _drawing_mode = DRAW_MODE_SOLID; BITMAP *_drawing_pattern = NULL; int _drawing_x_anchor = 0; int _drawing_y_anchor = 0; unsigned int _drawing_x_mask = 0; unsigned int _drawing_y_mask = 0; /* default palette structures */ PALETTE black_palette; PALETTE _current_palette; int _current_palette_changed = 0xFFFFFFFF; PALETTE desktop_palette = { { 63, 63, 63, 0 }, { 63, 0, 0, 0 }, { 0, 63, 0, 0 }, { 63, 63, 0, 0 }, { 0, 0, 63, 0 }, { 63, 0, 63, 0 }, { 0, 63, 63, 0 }, { 16, 16, 16, 0 }, { 31, 31, 31, 0 }, { 63, 31, 31, 0 }, { 31, 63, 31, 0 }, { 63, 63, 31, 0 }, { 31, 31, 63, 0 }, { 63, 31, 63, 0 }, { 31, 63, 63, 0 }, { 0, 0, 0, 0 } }; PALETTE default_palette = { { 0, 0, 0, 0 }, { 0, 0, 42, 0 }, { 0, 42, 0, 0 }, { 0, 42, 42, 0 }, { 42, 0, 0, 0 }, { 42, 0, 42, 0 }, { 42, 21, 0, 0 }, { 42, 42, 42, 0 }, { 21, 21, 21, 0 }, { 21, 21, 63, 0 }, { 21, 63, 21, 0 }, { 21, 63, 63, 0 }, { 63, 21, 21, 0 }, { 63, 21, 63, 0 }, { 63, 63, 21, 0 }, { 63, 63, 63, 0 }, { 0, 0, 0, 0 }, { 5, 5, 5, 0 }, { 8, 8, 8, 0 }, { 11, 11, 11, 0 }, { 14, 14, 14, 0 }, { 17, 17, 17, 0 }, { 20, 20, 20, 0 }, { 24, 24, 24, 0 }, { 28, 28, 28, 0 }, { 32, 32, 32, 0 }, { 36, 36, 36, 0 }, { 40, 40, 40, 0 }, { 45, 45, 45, 0 }, { 50, 50, 50, 0 }, { 56, 56, 56, 0 }, { 63, 63, 63, 0 }, { 0, 0, 63, 0 }, { 16, 0, 63, 0 }, { 31, 0, 63, 0 }, { 47, 0, 63, 0 }, { 63, 0, 63, 0 }, { 63, 0, 47, 0 }, { 63, 0, 31, 0 }, { 63, 0, 16, 0 }, { 63, 0, 0, 0 }, { 63, 16, 0, 0 }, { 63, 31, 0, 0 }, { 63, 47, 0, 0 }, { 63, 63, 0, 0 }, { 47, 63, 0, 0 }, { 31, 63, 0, 0 }, { 16, 63, 0, 0 }, { 0, 63, 0, 0 }, { 0, 63, 16, 0 }, { 0, 63, 31, 0 }, { 0, 63, 47, 0 }, { 0, 63, 63, 0 }, { 0, 47, 63, 0 }, { 0, 31, 63, 0 }, { 0, 16, 63, 0 }, { 31, 31, 63, 0 }, { 39, 31, 63, 0 }, { 47, 31, 63, 0 }, { 55, 31, 63, 0 }, { 63, 31, 63, 0 }, { 63, 31, 55, 0 }, { 63, 31, 47, 0 }, { 63, 31, 39, 0 }, { 63, 31, 31, 0 }, { 63, 39, 31, 0 }, { 63, 47, 31, 0 }, { 63, 55, 31, 0 }, { 63, 63, 31, 0 }, { 55, 63, 31, 0 }, { 47, 63, 31, 0 }, { 39, 63, 31, 0 }, { 31, 63, 31, 0 }, { 31, 63, 39, 0 }, { 31, 63, 47, 0 }, { 31, 63, 55, 0 }, { 31, 63, 63, 0 }, { 31, 55, 63, 0 }, { 31, 47, 63, 0 }, { 31, 39, 63, 0 }, { 45, 45, 63, 0 }, { 49, 45, 63, 0 }, { 54, 45, 63, 0 }, { 58, 45, 63, 0 }, { 63, 45, 63, 0 }, { 63, 45, 58, 0 }, { 63, 45, 54, 0 }, { 63, 45, 49, 0 }, { 63, 45, 45, 0 }, { 63, 49, 45, 0 }, { 63, 54, 45, 0 }, { 63, 58, 45, 0 }, { 63, 63, 45, 0 }, { 58, 63, 45, 0 }, { 54, 63, 45, 0 }, { 49, 63, 45, 0 }, { 45, 63, 45, 0 }, { 45, 63, 49, 0 }, { 45, 63, 54, 0 }, { 45, 63, 58, 0 }, { 45, 63, 63, 0 }, { 45, 58, 63, 0 }, { 45, 54, 63, 0 }, { 45, 49, 63, 0 }, { 0, 0, 28, 0 }, { 7, 0, 28, 0 }, { 14, 0, 28, 0 }, { 21, 0, 28, 0 }, { 28, 0, 28, 0 }, { 28, 0, 21, 0 }, { 28, 0, 14, 0 }, { 28, 0, 7, 0 }, { 28, 0, 0, 0 }, { 28, 7, 0, 0 }, { 28, 14, 0, 0 }, { 28, 21, 0, 0 }, { 28, 28, 0, 0 }, { 21, 28, 0, 0 }, { 14, 28, 0, 0 }, { 7, 28, 0, 0 }, { 0, 28, 0, 0 }, { 0, 28, 7, 0 }, { 0, 28, 14, 0 }, { 0, 28, 21, 0 }, { 0, 28, 28, 0 }, { 0, 21, 28, 0 }, { 0, 14, 28, 0 }, { 0, 7, 28, 0 }, { 14, 14, 28, 0 }, { 17, 14, 28, 0 }, { 21, 14, 28, 0 }, { 24, 14, 28, 0 }, { 28, 14, 28, 0 }, { 28, 14, 24, 0 }, { 28, 14, 21, 0 }, { 28, 14, 17, 0 }, { 28, 14, 14, 0 }, { 28, 17, 14, 0 }, { 28, 21, 14, 0 }, { 28, 24, 14, 0 }, { 28, 28, 14, 0 }, { 24, 28, 14, 0 }, { 21, 28, 14, 0 }, { 17, 28, 14, 0 }, { 14, 28, 14, 0 }, { 14, 28, 17, 0 }, { 14, 28, 21, 0 }, { 14, 28, 24, 0 }, { 14, 28, 28, 0 }, { 14, 24, 28, 0 }, { 14, 21, 28, 0 }, { 14, 17, 28, 0 }, { 20, 20, 28, 0 }, { 22, 20, 28, 0 }, { 24, 20, 28, 0 }, { 26, 20, 28, 0 }, { 28, 20, 28, 0 }, { 28, 20, 26, 0 }, { 28, 20, 24, 0 }, { 28, 20, 22, 0 }, { 28, 20, 20, 0 }, { 28, 22, 20, 0 }, { 28, 24, 20, 0 }, { 28, 26, 20, 0 }, { 28, 28, 20, 0 }, { 26, 28, 20, 0 }, { 24, 28, 20, 0 }, { 22, 28, 20, 0 }, { 20, 28, 20, 0 }, { 20, 28, 22, 0 }, { 20, 28, 24, 0 }, { 20, 28, 26, 0 }, { 20, 28, 28, 0 }, { 20, 26, 28, 0 }, { 20, 24, 28, 0 }, { 20, 22, 28, 0 }, { 0, 0, 16, 0 }, { 4, 0, 16, 0 }, { 8, 0, 16, 0 }, { 12, 0, 16, 0 }, { 16, 0, 16, 0 }, { 16, 0, 12, 0 }, { 16, 0, 8, 0 }, { 16, 0, 4, 0 }, { 16, 0, 0, 0 }, { 16, 4, 0, 0 }, { 16, 8, 0, 0 }, { 16, 12, 0, 0 }, { 16, 16, 0, 0 }, { 12, 16, 0, 0 }, { 8, 16, 0, 0 }, { 4, 16, 0, 0 }, { 0, 16, 0, 0 }, { 0, 16, 4, 0 }, { 0, 16, 8, 0 }, { 0, 16, 12, 0 }, { 0, 16, 16, 0 }, { 0, 12, 16, 0 }, { 0, 8, 16, 0 }, { 0, 4, 16, 0 }, { 8, 8, 16, 0 }, { 10, 8, 16, 0 }, { 12, 8, 16, 0 }, { 14, 8, 16, 0 }, { 16, 8, 16, 0 }, { 16, 8, 14, 0 }, { 16, 8, 12, 0 }, { 16, 8, 10, 0 }, { 16, 8, 8, 0 }, { 16, 10, 8, 0 }, { 16, 12, 8, 0 }, { 16, 14, 8, 0 }, { 16, 16, 8, 0 }, { 14, 16, 8, 0 }, { 12, 16, 8, 0 }, { 10, 16, 8, 0 }, { 8, 16, 8, 0 }, { 8, 16, 10, 0 }, { 8, 16, 12, 0 }, { 8, 16, 14, 0 }, { 8, 16, 16, 0 }, { 8, 14, 16, 0 }, { 8, 12, 16, 0 }, { 8, 10, 16, 0 }, { 11, 11, 16, 0 }, { 12, 11, 16, 0 }, { 13, 11, 16, 0 }, { 15, 11, 16, 0 }, { 16, 11, 16, 0 }, { 16, 11, 15, 0 }, { 16, 11, 13, 0 }, { 16, 11, 12, 0 }, { 16, 11, 11, 0 }, { 16, 12, 11, 0 }, { 16, 13, 11, 0 }, { 16, 15, 11, 0 }, { 16, 16, 11, 0 }, { 15, 16, 11, 0 }, { 13, 16, 11, 0 }, { 12, 16, 11, 0 }, { 11, 16, 11, 0 }, { 11, 16, 12, 0 }, { 11, 16, 13, 0 }, { 11, 16, 15, 0 }, { 11, 16, 16, 0 }, { 11, 15, 16, 0 }, { 11, 13, 16, 0 }, { 11, 12, 16, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 63, 63, 63, 0 } }; /* colors for the standard GUI dialogs (alerts, file selector, etc) */ int gui_fg_color = 255; int gui_mg_color = 8; int gui_bg_color = 0; /* a block of temporary working memory */ void *_scratch_mem = NULL; int _scratch_mem_size = 0; /* SVGA bank switching tables */ int _last_bank_1 = -1; int _last_bank_2 = -1; int *_gfx_bank = NULL; /* what OS are we running under? */ int os_type = OSTYPE_UNKNOWN; int os_version = -1; int os_revision = -1; int os_multitasking = FALSE; /* processor information */ char cpu_vendor[_AL_CPU_VENDOR_SIZE] = EMPTY_STRING; int cpu_family = 0; int cpu_model = 0; int cpu_capabilities = 0; /* debugging stuff */ static int debug_assert_virgin = TRUE; static int debug_trace_virgin = TRUE; static FILE *assert_file = NULL; static FILE *trace_file = NULL; static int (*assert_handler)(AL_CONST char *msg) = NULL; int (*_al_trace_handler)(AL_CONST char *msg) = NULL; /* Module linking system stuff: if an object file is linked in, then its * constructor function is executed; this function should fill in the * data structures below (declared in aintern.h). If the module is not * linked in, then the structure pointers will be null, so we don't need * to bother with that bit of code elsewhere. */ struct _AL_LINKER_MIDI *_al_linker_midi = NULL; struct _AL_LINKER_MOUSE *_al_linker_mouse = NULL; /* dynamic registration system for cleanup code */ struct al_exit_func { void (*funcptr)(void); AL_CONST char *desc; struct al_exit_func *next; }; static struct al_exit_func *exit_func_list = NULL; /* _add_exit_func: * Adds a function to the list that need to be called by allegro_exit(). * `desc' should point to a statically allocated string to help with * debugging. */ void _add_exit_func(void (*func)(void), AL_CONST char *desc) { struct al_exit_func *n; for (n = exit_func_list; n; n = n->next) if (n->funcptr == func) return; n = _AL_MALLOC(sizeof(struct al_exit_func)); if (!n) return; n->next = exit_func_list; n->funcptr = func; n->desc = desc; exit_func_list = n; } /* _remove_exit_func: * Removes a function from the list that need to be called by allegro_exit(). */ void _remove_exit_func(void (*func)(void)) { struct al_exit_func *iter = exit_func_list, *prev = NULL; while (iter) { if (iter->funcptr == func) { if (prev) prev->next = iter->next; else exit_func_list = iter->next; _AL_FREE(iter); return; } prev = iter; iter = iter->next; } } /* allegro_exit_stub: * Stub function registered by the library via atexit. */ static void allegro_exit_stub(void) { _allegro_in_exit = TRUE; allegro_exit(); } /* _install_allegro: * Initialises the Allegro library, activating the system driver. */ static int _install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)(void (*func)(void))) { RGB black_rgb = {0, 0, 0, 0}; char tmp1[64], tmp2[64]; int i; #ifndef ALLEGRO_USE_CONSTRUCTOR /* call constructor functions manually */ extern void _initialize_datafile_types(); extern void _midi_constructor(); extern void _mouse_constructor(); _initialize_datafile_types(); _midi_constructor(); _mouse_constructor(); _register_bitmap_file_type_init(); _register_sample_file_type_init(); _register_font_file_type_init(); #endif if (errno_ptr) allegro_errno = errno_ptr; else allegro_errno = &errno; /* set up default palette structures */ for (i=0; i<256; i++) black_palette[i] = black_rgb; for (i=16; i<256; i++) desktop_palette[i] = desktop_palette[i & 15]; /* lock some important variables */ LOCK_VARIABLE(screen); LOCK_VARIABLE(gfx_driver); LOCK_VARIABLE(gfx_capabilities); LOCK_VARIABLE(_last_bank_1); LOCK_VARIABLE(_last_bank_2); LOCK_VARIABLE(_gfx_bank); LOCK_VARIABLE(_drawing_mode); LOCK_VARIABLE(_drawing_pattern); LOCK_VARIABLE(_drawing_x_anchor); LOCK_VARIABLE(_drawing_y_anchor); LOCK_VARIABLE(_drawing_x_mask); LOCK_VARIABLE(_drawing_y_mask); LOCK_VARIABLE(_current_palette); LOCK_VARIABLE(os_type); /* nasty stuff to set up the config system before the system driver */ system_driver = _system_driver_list[0].driver; /* needed in case set_config_file was called before allegro_init */ _reload_config(); reload_config_texts(NULL); if (system_id == SYSTEM_AUTODETECT) system_id = get_config_id(uconvert_ascii("system", tmp1), uconvert_ascii("system", tmp2), SYSTEM_AUTODETECT); system_driver = NULL; /* initialise the system driver */ usetc(allegro_error, 0); for (i=0; _system_driver_list[i].driver; i++) { if ((_system_driver_list[i].id == system_id) || ((_system_driver_list[i].autodetect) && (system_id == SYSTEM_AUTODETECT))) { system_driver = _system_driver_list[i].driver; system_driver->name = system_driver->desc = get_config_text(system_driver->ascii_name); if (system_driver->init() != 0) { system_driver = NULL; if (system_id != SYSTEM_AUTODETECT) break; } else break; } } if (!system_driver) return -1; /* disable close button */ set_close_button_callback(NULL); /* detect CPU type */ check_cpu(); #if defined(ALLEGRO_UNIX) || defined(ALLEGRO_WINDOWS) /* detect filename encoding used by libc */ /* XXX This should be done for all platforms but I'm not set up to check * that all platforms have been covered before making the 4.2.3 release. * --pw */ _al_detect_filename_encoding(); #endif /* set up screensaver policy */ _screensaver_policy = get_config_int(uconvert_ascii("system", tmp1), uconvert_ascii("disable_screensaver", tmp2), FULLSCREEN_DISABLED); /* install shutdown handler */ if (_allegro_count == 0) { if (atexit_ptr) atexit_ptr(allegro_exit_stub); } _allegro_count++; TRACE(PREFIX_I "Allegro initialised (instance %d)\n", _allegro_count); return 0; } /* _install_allegro_version_check: * Initialises the Allegro library, but return with an error if an * incompatible version is found. */ int _install_allegro_version_check(int system_id, int *errno_ptr, int (*atexit_ptr)(void (*func)(void)), int version) { int r = _install_allegro(system_id, errno_ptr, atexit_ptr); int build_wip = version & 255; int build_ver = version & ~255; int version_ok; if (r != 0) { /* failed */ return r; } #if ALLEGRO_SUB_VERSION & 1 /* This is a WIP runtime, so enforce strict compatibility. */ version_ok = version == MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION); #else /* This is a stable runtime, so the runtime should be at least as new * as the build headers (otherwise we may get a crash, since some * functions may have been used which aren't available in this runtime). */ version_ok = (MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, 0) == build_ver) && (ALLEGRO_WIP_VERSION >= build_wip); #endif if (!version_ok) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text( "The detected dynamic Allegro library (%d.%d.%d) is " "not compatible with this program (%d.%d.%d)."), ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION, build_ver >> 16, (build_ver >> 8) & 255, build_wip); return -1; } return 0; } /* allegro_exit: * Closes down the Allegro system. */ void allegro_exit(void) { while (exit_func_list) { void (*func)(void) = exit_func_list->funcptr; _remove_exit_func(func); (*func)(); } if (system_driver) { system_driver->exit(); system_driver = NULL; } if (_scratch_mem) { _AL_FREE(_scratch_mem); _scratch_mem = NULL; _scratch_mem_size = 0; } } /* allegro_message: * Displays a message in whatever form the current platform requires. */ void allegro_message(AL_CONST char *msg, ...) { char *buf = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE); char *tmp = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE); va_list ap; ASSERT(msg); va_start(ap, msg); uvszprintf(buf, ALLEGRO_MESSAGE_SIZE, msg, ap); va_end(ap); if ((system_driver) && (system_driver->message)) system_driver->message(buf); else fputs(uconvert(buf, U_CURRENT, tmp, U_ASCII_CP, ALLEGRO_MESSAGE_SIZE), stdout); _AL_FREE(buf); _AL_FREE(tmp); } /* get_executable_name: * Finds out the name of the current executable. */ void get_executable_name(char *output, int size) { ASSERT(system_driver); ASSERT(output); if (system_driver->get_executable_name) { system_driver->get_executable_name(output, size); } else { output += usetc(output, '.'); output += usetc(output, '/'); usetc(output, 0); } } /* set_close_button_callback: * Installs a callback function to be called when the close button * of the window or any equivalent device is activated. Returns 0 on * success and -1 on failure (e.g. feature not supported). */ int set_close_button_callback(void (*proc)(void)) { ASSERT(system_driver); if (system_driver->set_close_button_callback) return system_driver->set_close_button_callback(proc); return -1; } /* debug_exit: * Closes the debugging output files. */ static void debug_exit(void) { if (assert_file) { fclose(assert_file); assert_file = NULL; } if (trace_file) { fclose(trace_file); trace_file = NULL; } debug_assert_virgin = TRUE; debug_trace_virgin = TRUE; _remove_exit_func(debug_exit); } /* al_assert: * Raises an assert (uses ASCII strings). */ void al_assert(AL_CONST char *file, int line) { static int asserted = FALSE; int olderr = errno; char buf[128]; char *s; if (asserted) return; /* todo, some day: use snprintf (C99) */ sprintf(buf, "Assert failed at line %d of %s", line, file); if (assert_handler) { if (assert_handler(buf)) return; } if (debug_assert_virgin) { s = getenv("ALLEGRO_ASSERT"); if (s) assert_file = fopen(s, "w"); else assert_file = NULL; if (debug_trace_virgin) _add_exit_func(debug_exit, "debug_exit"); debug_assert_virgin = FALSE; } if (assert_file) { fprintf(assert_file, "%s\n", buf); fflush(assert_file); } else { asserted = TRUE; if ((system_driver) && (system_driver->assert)) { system_driver->assert(buf); } else { allegro_exit(); fprintf(stderr, "%s\n", buf); abort(); } } errno = olderr; } /* al_trace: * Outputs a trace message (uses ASCII strings). */ void al_trace(AL_CONST char *msg, ...) { int olderr = errno; char buf[512]; char *s; /* todo, some day: use vsnprintf (C99) */ va_list ap; va_start(ap, msg); vsprintf(buf, msg, ap); va_end(ap); if (_al_trace_handler) { if (_al_trace_handler(buf)) return; } if (debug_trace_virgin) { s = getenv("ALLEGRO_TRACE"); if (s) trace_file = fopen(s, "w"); else trace_file = fopen(LOGFILE, "w"); if (debug_assert_virgin) _add_exit_func(debug_exit, "debug_exit"); debug_trace_virgin = FALSE; } if (trace_file) { fwrite(buf, sizeof(char), strlen(buf), trace_file); fflush(trace_file); } errno = olderr; } /* register_assert_handler: * Installs a user handler for assert failures. */ void register_assert_handler(int (*handler)(AL_CONST char *msg)) { assert_handler = handler; } /* register_trace_handler: * Installs a user handler for trace output. */ void register_trace_handler(int (*handler)(AL_CONST char *msg)) { _al_trace_handler = handler; } /* _al_malloc: * Wrapper for when a program needs to manipulate memory that has been * allocated by the Allegro DLL. */ void *_al_malloc(size_t size) { return malloc(size); } /* _al_free: * Wrapper for when a program needs to manipulate memory that has been * allocated by the Allegro DLL. */ void _al_free(void *mem) { free(mem); } /* _al_realloc: * Wrapper for when a program needs to manipulate memory that has been * allocated by the Allegro DLL. */ void *_al_realloc(void *mem, size_t size) { return realloc(mem, size); } /* _al_strdup: * Wrapper for when a program needs to duplicate a string in a way that * uses any user overloaded memory allocation system in use. * The result of this function _must_ be freed with _AL_FREE(). */ char *_al_strdup(AL_CONST char *string) { char *newstring = _AL_MALLOC(strlen(string) + 1); if (newstring) strcpy(newstring, string); return newstring; } /* a simple system driver for platform-independent code */ static int sys_none_init(void) { return 0; } static void sys_none_exit(void) { } static _DRIVER_INFO no_drivers[] = {{ 0, NULL, 0 }}; static _DRIVER_INFO *sys_no_driver(void) { return no_drivers; } SYSTEM_DRIVER system_none = { SYSTEM_NONE, empty_string, empty_string, "Agnostic", sys_none_init, sys_none_exit, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, sys_no_driver, sys_no_driver, sys_no_driver, sys_no_driver, sys_no_driver, sys_no_driver, sys_no_driver }; allegro-4.4.3.1/src/text.c0000664000175000017500000002237013437077643014223 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Text drawing routines. * * By Shawn Hargreaves. * * textout_justify() by Seymour Shlien. * * Laurence Withers added the textout_ex() function family. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* textout_ex: * Writes the null terminated string str onto bmp at position x, y, using * the specified font, foreground color and background color (-1 is trans). * If color is -1 and a proportional font is in use, it will be drawn * using the colors from the original font bitmap (the one imported into * the grabber program), which allows multicolored text output. */ void textout_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color, int bg) { ASSERT(bmp); ASSERT(f); ASSERT(str); f->vtable->render(f, str, color, bg, bmp, x, y); } /* textout_centre_ex: * Like textout_ex(), but uses the x coordinate as the centre rather than * the left of the string. */ void textout_centre_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color, int bg) { int len; ASSERT(bmp); ASSERT(f); ASSERT(str); len = text_length(f, str); f->vtable->render(f, str, color, bg, bmp, x - len/2, y); } /* textout_right_ex: * Like textout_ex(), but uses the x coordinate as the right rather than * the left of the string. */ void textout_right_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color, int bg) { int len; ASSERT(bmp); ASSERT(f); ASSERT(str); len = text_length(f, str); f->vtable->render(f, str, color, bg, bmp, x - len, y); } /* textout_justify_ex: * Like textout_ex(), but justifies the string to the specified area. */ #define MAX_TOKEN 128 void textout_justify_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x1, int x2, int y, int diff, int color, int bg) { char toks[32]; char *tok[MAX_TOKEN]; char *strbuf, *strlast; int i, minlen, last, space; float fleft, finc; ASSERT(bmp); ASSERT(f); ASSERT(str); i = usetc(toks, ' '); i += usetc(toks+i, '\t'); i += usetc(toks+i, '\n'); i += usetc(toks+i, '\r'); usetc(toks+i, 0); /* count words and measure min length (without spaces) */ strbuf = _al_ustrdup(str); if (!strbuf) { /* Can't justify ! */ f->vtable->render(f, str, color, bg, bmp, x1, y); return; } minlen = 0; last = 0; tok[last] = ustrtok_r(strbuf, toks, &strlast); while (tok[last]) { minlen += text_length(f, tok[last]); if (++last == MAX_TOKEN) break; tok[last] = ustrtok_r(NULL, toks, &strlast); } /* amount of room for space between words */ space = x2 - x1 - minlen; if ((space <= 0) || (space > diff) || (last < 2)) { /* can't justify */ _AL_FREE(strbuf); f->vtable->render(f, str, color, bg, bmp, x1, y); return; } /* distribute space left evenly between words */ fleft = (float)x1; finc = (float)space / (float)(last-1); for (i=0; ivtable->render(f, tok[i], color, bg, bmp, (int)fleft, y); fleft += (float)text_length(f, tok[i]) + finc; } _AL_FREE(strbuf); } /* textprintf_ex: * Formatted text output, using a printf() style format string. */ void textprintf_ex(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_ex(bmp, f, buf, x, y, color, bg); } /* textprintf_centre_ex: * Like textprintf_ex(), but uses the x coordinate as the centre rather than * the left of the string. */ void textprintf_centre_ex(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_centre_ex(bmp, f, buf, x, y, color, bg); } /* textprintf_right_ex: * Like textprintf_ex(), but uses the x coordinate as the right rather than * the left of the string. */ void textprintf_right_ex(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_right_ex(bmp, f, buf, x, y, color, bg); } /* textprintf_justify_ex: * Like textprintf_ex(), but right justifies the string to the specified area. */ void textprintf_justify_ex(BITMAP *bmp, AL_CONST FONT *f, int x1, int x2, int y, int diff, int color, int bg, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_justify_ex(bmp, f, buf, x1, x2, y, diff, color, bg); } /* text_length: * Calculates the length of a string in a particular font. */ int text_length(AL_CONST FONT *f, AL_CONST char *str) { ASSERT(f); ASSERT(str); return f->vtable->text_length(f, str); } /* text_height: * Returns the height of a character in the specified font. */ int text_height(AL_CONST FONT *f) { ASSERT(f); return f->vtable->font_height(f); } /* destroy_font: * Frees the memory being used by a font structure. * This is now wholly handled in the vtable. */ void destroy_font(FONT *f) { ASSERT(f); f->vtable->destroy(f); } /* The following code has been deprecated, as it relies on a global * variable. This is no good in multithreaded code, and using a bg * parameter also simplifies other code (for instance, the GUI). */ int _textmode = 0; /* text_mode: * Sets the mode in which text will be drawn. If mode is positive, text * output will be opaque and the background will be set to mode. If mode * is negative, text will be drawn transparently (ie. the background will * not be altered). The default is a mode of zero. * Returns previous mode. */ int text_mode(int mode) { int old_mode = _textmode; if (mode < 0) _textmode = -1; else _textmode = mode; return old_mode; } /* textout: (inlined) * Writes the null terminated string str onto bmp at position x, y, using * the current text mode and the specified font and foreground color. * If color is -1 and a proportional font is in use, it will be drawn * using the colors from the original font bitmap (the one imported into * the grabber program), which allows multicolored text output. */ /* textout_centre: (inlined) * Like textout(), but uses the x coordinate as the centre rather than * the left of the string. */ /* textout_right: (inlined) * Like textout(), but uses the x coordinate as the right rather than * the left of the string. */ /* textout_justify: (inlined) * Like textout(), but justifies the string to the specified area. */ /* textprintf: * Formatted text output, using a printf() style format string. */ void textprintf(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_ex(bmp, f, buf, x, y, color, _textmode); } /* textprintf_centre: * Like textprintf(), but uses the x coordinate as the centre rather than * the left of the string. */ void textprintf_centre(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_centre_ex(bmp, f, buf, x, y, color, _textmode); } /* textprintf_right: * Like textout(), but uses the x coordinate as the right rather than * the left of the string. */ void textprintf_right(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_right_ex(bmp, f, buf, x, y, color, _textmode); } /* textprintf_justify: * Like textprintf(), but right justifies the string to the specified area. */ void textprintf_justify(BITMAP *bmp, AL_CONST FONT *f, int x1, int x2, int y, int diff, int color, AL_CONST char *format, ...) { char buf[512]; va_list ap; ASSERT(bmp); ASSERT(f); ASSERT(format); va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); textout_justify_ex(bmp, f, buf, x1, x2, y, diff, color, _textmode); } allegro-4.4.3.1/src/ppc/0000775000175000017500000000000013437077643013651 5ustar siegesiegeallegro-4.4.3.1/src/ppc/pgfx8.inc0000664000175000017500000000442713437077643015407 0ustar siegesiege MACRO ;Get 4 copies of in &DSTF from &SRC MAKEDOUBLE8 &SRC,&DSTF,&TMP1 rlwinm &SRC,&SRC,0,24,31 rlwinm &TMP1,&SRC,8,16,23 or &SRC,&SRC,&TMP1 rlwinm &TMP1,&SRC,16,0,15 or &SRC,&SRC,&TMP1 stw &SRC,-8(sp) stw &SRC,-4(sp) lfd &DSTF,-8(sp) ENDM MACRO HL8SOLID8 &ADDR,&W,&SRCW,&SRCD,&TMP1,&TMP2 rlwinm. &TMP2,&ADDR,0,29,31 beq @align li &TMP1,8 sub &TMP1,&TMP1,&TMP2 cmp cr7,&TMP1,&W blt cr7,@not_too_small mr &TMP1,&W @not_too_small mtcrf 0x03,&TMP1 sub &W,&W,&TMP1 @row_loop: bc 4,31,@pre_n_b stb &SRCW,0(&ADDR) addi &ADDR,&ADDR,1 @pre_n_b: bc 4,30,@pre_n_h sth &SRCW,0(&ADDR) addi &ADDR,&ADDR,2 @pre_n_h: bc 4,29,@pre_n_w stw &SRCW,0(&ADDR) addi &ADDR,&ADDR,4 @pre_n_w: @align: srawi. &TMP1,&W,3 mtcrf 0x03,&W mtctr &TMP1 beq @pos @loop: stfd &SRCD,0(&ADDR) addi &ADDR,&ADDR,8 bdnz @loop @pos: bc 4,29,@pos_n_w stw &SRCW,0(&ADDR) addi &ADDR,&ADDR,4 @pos_n_w: bc 4,30,@pos_n_h sth &SRCW,0(&ADDR) addi &ADDR,&ADDR,2 @pos_n_h: bc 4,31,@pos_n_b stb &SRCW,0(&ADDR) addi &ADDR,&ADDR,1 @pos_n_b: ENDM MACRO HL8SOLID32 &ADDR,&W,&SRCW,&SRCD,&TMP1,&TMP2 rlwinm. &TMP2,&ADDR,0,27,31 beq @align li &TMP1,32 sub &TMP1,&TMP1,&TMP2 cmp cr7,&TMP1,&W blt cr7,@not_too_small mr &TMP1,&W @not_too_small mtcrf 0x03,&TMP1 sub &W,&W,&TMP1 @row_loop: bc 4,31,@pre_n_b stb &SRCW,0(&ADDR) addi &ADDR,&ADDR,1 @pre_n_b: bc 4,30,@pre_n_h sth &SRCW,0(&ADDR) addi &ADDR,&ADDR,2 @pre_n_h: bc 4,29,@pre_n_w stw &SRCW,0(&ADDR) addi &ADDR,&ADDR,4 @pre_n_w: bc 4,28,@pre_n_d stfd &SRCD,0(&ADDR) addi &ADDR,&ADDR,8 @pre_n_d: bc 4,27,@pre_n_q stfd &SRCD,0(&ADDR) stfd &SRCD,8(&ADDR) addi &ADDR,&ADDR,16 @pre_n_q: @align: srawi. &TMP1,&W,5 mtcrf 0x03,&W mtctr &TMP1 beq @pos @loop: dcbz 0,&ADDR stfd &SRCD,0(&ADDR) stfd &SRCD,8(&ADDR) stfd &SRCD,16(&ADDR) stfd &SRCD,24(&ADDR) addi &ADDR,&ADDR,32 bdnz @loop @pos: bc 4,27,@pos_n_q stfd &SRCD,0(&ADDR) stfd &SRCD,8(&ADDR) addi &ADDR,&ADDR,16 @pos_n_q: bc 4,28,@pos_n_d stfd &SRCD,0(&ADDR) addi &ADDR,&ADDR,8 @pos_n_d: bc 4,29,@pos_n_w stw &SRCW,0(&ADDR) addi &ADDR,&ADDR,4 @pos_n_w: bc 4,30,@pos_n_h sth &SRCW,0(&ADDR) addi &ADDR,&ADDR,2 @pos_n_h: bc 4,31,@pos_n_b stb &SRCW,0(&ADDR) addi &ADDR,&ADDR,1 @pos_n_b: ENDM allegro-4.4.3.1/src/ppc/ppcdef.inc0000664000175000017500000000610613437077643015610 0ustar siegesiege MACRO MakeFunction &fnName EXPORT &fnName[DS] EXPORT .&fnName[PR] TC &fnName[TC], &fnName[DS] CSECT &fnName[DS] DC.L .&fnName[PR] DC.L TOC[tc0] CSECT .&fnName[PR] FUNCTION .&fnName[PR] ENDM ARG1 EQU r3 ARG2 EQU r4 ARG3 EQU r5 ARG4 EQU r6 ARG5 EQU r7 ARG6 EQU r8 ARG7 EQU r9 ARG8 EQU r10 TMP1 EQU r11 TMP2 EQU r12 LOCAL1 EQU r31 LOCAL2 EQU r30 LOCAL3 EQU r29 LOCAL4 EQU r28 LOCAL5 EQU r27 LOCAL6 EQU r26 LOCAL7 EQU r25 LOCAL8 EQU r24 LOCAL10 EQU r23 LOCAL11 EQU r22 LOCAL12 EQU r21 LOCAL13 EQU r20 LOCAL14 EQU r19 LOCAL15 EQU r18 LOCAL16 EQU r17 RESULT EQU r3 ;typedef struct BITMAP /* a bitmap structure */ ;{ ; int w, h; /* width and height in pixels */ ; int clip; /* flag if clipping is turned on */ ; int cl, cr, ct, cb; /* clip left, right, top and bottom values */ ; GFX_VTABLE *vtable; /* drawing functions */ ; void *write_bank; /* C func on some machines, asm on i386 */ ; void *read_bank; /* C func on some machines, asm on i386 */ ; void *dat; /* the memory we allocated for the bitmap */ ; unsigned long id; /* for identifying sub-bitmaps */ ; void *extra; /* points to a structure with more info */ ; int x_ofs; /* horizontal offset (for sub-bitmaps) */ ; int y_ofs; /* vertical offset (for sub-bitmaps) */ ; int seg; /* bitmap segment */ ; ZERO_SIZE_ARRAY(unsigned char *,line); ;} BITMAP; BITMAP record w ds.l 1 h ds.l 1 clip ds.l 1 cl ds.l 1 cr ds.l 1 ct ds.l 1 cb ds.l 1 vtable ds.l 1 write_bank ds.l 1 read_bank ds.l 1 dat ds.l 1 id ds.l 1 extra ds.l 1 x_ofs ds.l 1 y_ofs ds.l 1 _seg ds.l 1 sizeof EQU * _line ds.l 1 _line1 ds.l 1 endr DRAW_MODE_SOLID set 0 DRAW_MODE_XOR set 1 DRAW_MODE_COPY_PATTERN set 2 DRAW_MODE_SOLID_PATTERN set 3 DRAW_MODE_MASKED_PATTERN set 4 DRAW_MODE_TRANS set 5 DRAW_MODE_MAX_SUPORTED set 5 toc tc _linear_vline8[TC],_linear_vline8[DS] import ._linear_vline8[PR] import _linear_vline8[DS] toc tc _linear_hline8[TC],_linear_hline8[DS] import ._linear_hline8[PR] import _linear_hline8[DS] toc tc _normal_rectfill[TC],_normal_rectfill[DS] import ._normal_rectfill[PR] import _normal_rectfill[DS] toc tc _linear_putpixel8[TC],_linear_putpixel8[DS] import ._linear_putpixel8[PR] import _linear_putpixel8[DS] toc tc _drawing_mode[TC],_drawing_mode[RW] toc tc color_map[TC],color_map[RW] toc tc _drawing_x_mask[TC],_drawing_x_mask[RW] toc tc _drawing_x_anchor[TC],_drawing_x_anchor[RW] toc tc _drawing_y_mask[TC],_drawing_y_mask[RW] toc tc _drawing_y_anchor[TC],_drawing_y_anchor[RW] toc tc _drawing_pattern[TC],_drawing_pattern[RW] import _drawing_mode[RW] import color_map[RW] import _drawing_x_mask[RW] import _drawing_x_anchor[RW] import _drawing_y_mask[RW] import _drawing_y_anchor[RW] import _drawing_pattern[RW] allegro-4.4.3.1/src/ppc/ppchl8.inc0000664000175000017500000001553013437077643015546 0ustar siegesiege MakeFunction _ppc_linear_hline8 ._ppc_linear_hline8: ;BITMAP * r3 ;x1 r4 ;y r5 ;x2 r6 ;color r7 lwz r9, _drawing_mode[TC](rtoc) lwz r11, 0(r9) cmpli cr0, r11, DRAW_MODE_MAX_SUPORTED ble cr0, @ok b ._linear_hline8[PR] @ok cmp cr0, r4, r6 bng cr0,@n_swap_x1_x2 mr r9, r6 mr r6, r4 mr r4, r9 @n_swap_x1_x2 lwz r8, BITMAP.clip(r3) cmpi cr1, r8, 0 beq cr1,@n_clip lwz r8, BITMAP.ct(r3) lwz r9, BITMAP.cb(r3) cmp cr6, r5, r8 cmp cr7, r5, r9 bltlr cr6 bgelr cr7 lwz r9, BITMAP.cl(r3) lwz r8, BITMAP.cr(r3) cmp cr0, r4, r9 cmp cr1, r6, r8 bnl cr0,@n_clip_x1 addi r4, r9, 0 @n_clip_x1: blt cr1,@n_clip_x2 addi r6, r8,-1 @n_clip_x2: cmp cr6, r6, r4 bltlr cr6 @n_clip: sub r12,r6,r4 addi r12,r12,1 rlwinm r7, r7, 0, 24, 31 ._ppc_linear_n_cache: rlwinm r8, r5, 2, 0, 29 add r8, r3, r8 lwz r10, 64(r8) add r9, r10, r4 cmpli cr7, r11,DRAW_MODE_COPY_PATTERN bge cr7,@pat_transfer cmpli cr0, r11,DRAW_MODE_SOLID MAKEDOUBLE8 r7,f0,r11 bne cr0,@xor HL8SOLID8 r9,r12,r7,f0,r3,r11 blr @xor: rlwinm. r11, r9, 0, 30, 31 beq @xor_pre_end li r4,4 sub r3,r4,r11 sub. r12,r12,r3 rlwinm r10, r9, 0, 0, 29 bge @xor_n_too_small addi r4,r12,4 rlwinm r4,r4,3,0,28 slw r7,r7,r4 li r12,0 @xor_n_too_small: lwz r4,0(r10) rlwinm r3,r11,3,0,28 srw r5,r7,r3 xor r6,r4,r5 stw r6,0(r10) addi r9,r10,4 @xor_pre_end: srawi. r3,r12,2 rlwinm r11, r12, 0, 30, 31 addi r9,r9,-4 beq @xor_pos mtctr r3 @xor_loop: lwzu r3, 4(r9) xor r4, r3,r7 stw r4, 0(r9) bdnz @xor_loop @xor_pos: cmpi cr6, r11, 0 li r5,4 beqlr cr6 lwzu r4,4(r9) sub r3,r5,r11 rlwinm r3,r3,3,0,28 slw r5,r7,r3 xor r6,r4,r5 stw r6,0(r9) @xor_end: blr @trans: lwz r11, color_map[TC](rtoc) lwz r10, 0(r11) rlwinm r3, r7, 8, 16, 23 add r8, r10, r3 rlwinm. r11, r9, 0, 30, 31 beq @trans_pre_end li r3,4 addi r9,r9,-1 sub r3,r3,r11 cmp cr6,r3,r12 blt cr6,@trans_pre_loop0 mr r3,r12 @trans_pre_loop0: mtctr r3 sub r12,r12,r3 @trans_pre_loop: lbzu r4, 1(r9) lbzx r5, r8, r4 stb r5, 0(r9) bdnz @trans_pre_loop addi r9,r9,1 @trans_pre_end: srawi. r3,r12,2 rlwinm r11, r12, 0, 30, 31 beq @trans_pos addi r9,r9,-4 mtctr r3 @trans_loop: lwzu r7, 4(r9) rlwinm r3,r7,0,24,31 rlwinm r4,r7,8,24,31 rlwinm r5,r7,16,24,31 rlwinm r6,r7,24,24,31 lbzx r3,r8,r3 lbzx r4,r8,r4 lbzx r5,r8,r5 lbzx r6,r8,r6 rlwinm r4,r4,24,0,31 rlwinm r5,r5,16,0,31 rlwinm r6,r6, 8,0,31 add r7,r3,r4 add r5,r5,r6 add r3,r7,r5 stw r3, 0(r9) bdnz @trans_loop addi r9,r9,4 @trans_pos: cmpi cr6,r11, 0 beq cr6,@trans_end addi r9,r9,-1 mtctr r11 @trans_pos_loop: lbzu r4, 1(r9) lbzx r5, r8, r4 stb r5, 0(r9) bdnz @trans_pos_loop @trans_end: blr @pat_transfer: cmpli cr7, r11,DRAW_MODE_TRANS beq cr7,@trans cmpli cr6, r11,DRAW_MODE_SOLID_PATTERN lwz r11, _drawing_y_anchor[TC](rtoc) lwz r3, _drawing_y_mask[TC](rtoc) lwz r10,0(r11) lwz r11,0(r3) add r8,r10,r5 and r8,r8,r11 lwz r5, _drawing_pattern[TC](rtoc) lwz r11, _drawing_x_anchor[TC](rtoc) lwz r3, _drawing_x_mask[TC](rtoc) rlwinm r8,r8,2,0,29 lwz r5,0(r5) add r5,r5,r8 lwz r8,64(r5) lwz r10,0(r11) lwz r6,0(r3) add r10,r10,r4 beq cr6,@solid_pat bgt cr6,@mask_pat @copy_pat: rlwinm. r11, r9, 0, 30, 31 beq @copy_pat_pre_end li r3,4 addi r9,r9,-1 sub r3,r3,r11 cmp cr6,r3,r12 blt cr6,@copy_pat_pre_loop0 mr r3,r12 @copy_pat_pre_loop0 mtctr r3 sub r12,r12,r3 @copy_pat_pre_loop: and r10,r10,r6 lbzx r3,r10,r8 addi r10,r10,1 stbu r3,1(r9) bdnz @copy_pat_pre_loop addi r9,r9,1 @copy_pat_pre_end: srawi. r3,r12,2 rlwinm r11, r12, 0, 30, 31 beq @copy_pat_pos addi r9,r9,-4 mtctr r3 @copy_pat_loop: and r10,r10,r6 lbzx r3,r10,r8 addi r10,r10,1 and r10,r10,r6 rlwinm r3, r3, 24, 0, 31 lbzx r4,r10,r8 addi r10,r10,1 and r10,r10,r6 rlwinm r4, r4, 16, 0, 31 lbzx r5,r10,r8 addi r10,r10,1 and r10,r10,r6 add r3,r3,r4 rlwinm r5, r5, 8, 0, 31 lbzx r7,r10,r8 addi r10,r10,1 add r3,r3,r5 add r3,r3,r7 stwu r3,4(r9) bdnz @copy_pat_loop addi r9,r9,4 @copy_pat_pos: cmpi cr6,r11, 0 beqlr cr6 addi r9,r9,-1 mtctr r11 @copy_pat_pos_loop: and r10,r10,r6 lbzx r3,r10,r8 addi r10,r10,1 stbu r3,1(r9) bdnz @copy_pat_pos_loop @copy_pat_end: blr @solid_pat: rlwinm. r11, r9, 0, 30, 31 beq @solid_pat_pre_end li r3,4 addi r9,r9,-1 sub r3,r3,r11 cmp cr6,r3,r12 blt cr6,@solid_pat_pre_loop0 mr r3,r12 @solid_pat_pre_loop0 mtctr r3 sub r12,r12,r3 @solid_pat_pre_loop: and r10,r10,r6 lbzx r3,r10,r8 cmpi cr7,r3,0 addi r10,r10,1 beq cr7,@solid_pat_pre_1 mr r3,r7 @solid_pat_pre_1 stbu r3,1(r9) bdnz @solid_pat_pre_loop addi r9,r9,1 @solid_pat_pre_end: srawi. r3,r12,2 rlwinm r11, r12, 0, 30, 31 beq @solid_pat_pos addi r9,r9,-4 mtctr r3 @solid_pat_loop: and r10,r10,r6 lbzx r3,r10,r8 addi r10,r10,1 cmpi cr7, r3,0 and r10,r10,r6 lbzx r4,r10,r8 beq cr7,@solid_pat_1 rlwinm r3, r7, 24, 0, 31 @solid_pat_1 addi r10,r10,1 cmpi cr7, r4,0 and r10,r10,r6 lbzx r5,r10,r8 beq cr7,@solid_pat_2 rlwinm r4, r7, 16, 0, 31 or r3,r3,r4 @solid_pat_2 addi r10,r10,1 cmpi cr7, r5,0 and r10,r10,r6 lbzx r4,r10,r8 beq cr7,@solid_pat_3 rlwinm r5, r7, 8, 0, 31 or r3,r3,r5 @solid_pat_3 cmpi cr7, r4,0 addi r10,r10,1 beq cr7,@solid_pat_4 or r3,r3,r7 @solid_pat_4 stwu r3,4(r9) bdnz @solid_pat_loop addi r9,r9,4 @solid_pat_pos: cmpi cr6,r11, 0 beqlr cr6 addi r9,r9,-1 mtctr r11 @solid_pat_pos_loop: and r10,r10,r6 lbzx r3,r10,r8 cmpi cr7,r3,0 addi r10,r10,1 beq cr7,@solid_pat_pos_1 mr r3,r7 @solid_pat_pos_1 stbu r3,1(r9) bdnz @solid_pat_pos_loop @solid_pat_end: blr @mask_pat mtctr r12 @mask_pat_loop: and r10,r10,r6 lbzx r3,r10,r8 cmpi cr7,r3,0 addi r10,r10,1 beq cr7,@mask_pat_1 stb r7,0(r9) @mask_pat_1 addi r9,r9,1 bdnz @mask_pat_loop blr ._ppc_linear_hline8_end: MakeFunction _ppc_linear_hline8_32 ._ppc_linear_hline8_32: ;BITMAP * r3 ;x1 r4 ;y r5 ;x2 r6 ;color r7 ;cache optimised only solid mode on memory cacheble lwz r9, _drawing_mode[TC](rtoc) lwz r11, 0(r9) cmpli cr0, r11, DRAW_MODE_SOLID beq cr0, @ok b ._ppc_linear_hline8 @ok cmp cr0, r4, r6 bng cr0,@n_swap_x1_x2 mr r9, r6 mr r6, r4 mr r4, r9 @n_swap_x1_x2 lwz r8, BITMAP.clip(r3) cmpi cr1, r8, 0 beq cr1,@n_clip lwz r8, BITMAP.ct(r3) lwz r9, BITMAP.cb(r3) cmp cr6, r5, r8 cmp cr7, r5, r9 bltlr cr6 bgelr cr7 lwz r9, BITMAP.cl(r3) lwz r8, BITMAP.cr(r3) cmp cr0, r4, r9 cmp cr1, r6, r8 bnl cr0,@n_clip_x1 addi r4, r9, 0 @n_clip_x1: blt cr1,@n_clip_x2 addi r6, r8,-1 @n_clip_x2: cmp cr6, r6, r4 bltlr cr6 @n_clip: sub r12,r6,r4 addi r12,r12,1 cmpli cr0,r12,64 rlwinm r7, r7, 0, 24, 31 blt cr0,._ppc_linear_n_cache rlwinm r8, r5, 2, 0, 29 add r8, r3, r8 lwz r10, 64(r8) add r9, r10, r4 MAKEDOUBLE8 r7,f0,r11 HL8SOLID32 r9,r12,r7,f0,r3,r11 blr ._ppc_linear_hline8_32_end:allegro-4.4.3.1/src/ppc/ppcvl8.inc0000664000175000017500000000646313437077643015571 0ustar siegesiege MakeFunction _ppc_linear_vline8 ._ppc_linear_vline8: ;BITMAP * r3 ;x r4 ;y1 r5 ;y2 r6 ;color r7 lwz r9, _drawing_mode[TC](rtoc) lwz r9, 0(r9) cmpli cr0, r9, DRAW_MODE_MAX_SUPORTED ble cr0, ._ppc_linear_vline8_ok b ._linear_vline8[PR] ._ppc_linear_vline8_ok: cmp cr0, r5, r6 mr r10, r6 bng cr0,.vl8_5 mr r6, r5 mr r5, r10 .vl8_5: lwz r8, BITMAP.clip(r3) cmpi cr0, r8, 0 beq cr0,.vl8_no_clip lwz r8, BITMAP.cl(r3) cmp cr0, r4, r8 bltlr cr0 .vl8_10: lwz r8, BITMAP.cr(r3) cmp cr0, r4, r8 bgelr cr0 .vl8_13: lwz r10, BITMAP.ct(r3) lwz r8, BITMAP.cb(r3) cmp cr0, r5, r10 cmp cr1, r6, r8 bnl cr0,.vl8_15 mr r5, r10 .vl8_15: blt cr1,.vl8_17 addi r6, r8, -1 .vl8_17: cmp cr0, r6, r5 bltlr cr0 .vl8_no_clip: stmw r27, -20(sp) rlwinm r7,r7,0,24,31 stwu sp, -96(sp) rlwinm r12, r5, 2, 0, 29 add r12, r3, r12 lwz r31, 68(r3) subf r11, r5, r6 lwz r30, 64(r12) cmpi cr0, r9, DRAW_MODE_SOLID lwz r12, 64(r3) addi r10, r11, 1 subf r31, r12, r31 add r8, r30, r4 bne cr0,.vl8_30 subf r9, r31, r8 mtctr r10 .vl8_solid_loop: stbux r7, r9, r31 bdnz .vl8_solid_loop addi sp, sp, 96 lmw r27, -20(sp) blr .vl8_30: cmpi cr0, r9, DRAW_MODE_XOR bne cr0,.vl8_38 subf r8, r31, r8 mtctr r10 .vl8_xor_loop: lbzux r3, r8, r31 xor r4, r3, r7 stb r4, 0(r8) bdnz .vl8_xor_loop addi sp, sp, 96 lmw r27, -20(sp) blr .vl8_38: cmpi cr0, r9, 5 bne cr0,.vl8_patern_mode lwz r3, color_map[TC](rtoc) subf r9, r31, r8 lwz r4, 0(r3) rlwinm r5, r7, 8, 16, 23 add r8, r4, r5 mtctr r10 .vl8_trans_loop: lbzux r3, r9, r31 lbzx r4, r3, r8 stb r4, 0(r9) bdnz .vl8_trans_loop addi sp, sp, 96 lmw r27, -20(sp) blr .vl8_patern_mode: lwz r12, _drawing_pattern[TC](rtoc) lwz r12, 0(r12) rlwinm r11, r6, 2, 0, 29 add r11, r3, r11 lwz r30, 64(r11) add r6, r4, r30 lwz r10, _drawing_y_anchor[TC](rtoc) lwz r30, 0(r10) lwz r11, _drawing_x_mask[TC](rtoc) lwz r11, 0(r11) lwz r3, _drawing_y_mask[TC](rtoc) lwz r10, 0(r3) subf r30, r30, r5 rlwinm r28, r10, 2, 0, 29 lwz r3, _drawing_x_anchor[TC](rtoc) lwz r3, 0(r3) and r30, r10, r30 lwz r27, 64(r12) rlwinm r30, r30, 2, 0, 29 lwz r10, 68(r12) addi r12, r12, 64 subf r10, r27, r10 lwzx r29, r12, r28 subf r3, r3, r4 lwzx r30, r12, r30 and r12, r3, r11 add r27, r12, r27 add r29, r12, r29 add r28, r12, r30 cmpi cr0, r9, DRAW_MODE_COPY_PATTERN bne cr0,.vl8_63 subf r9, r31, r8 subf r8, r10, r28 subf r29, r10, r29 .vl8_copy_pat_loop: lbzux r3, r8, r10 stbux r3, r9, r31 cmpl cr0, r8, r29 cmpl cr1, r9, r6 bng cr0,.vl8_copy_pat_1 subf r8, r10, r27 .vl8_copy_pat_1: bng cr1,.vl8_copy_pat_loop b .vl8_end .vl8_63: cmpi cr0, r9, DRAW_MODE_SOLID_PATTERN bne cr0,.vl8_80 subf r9, r31, r8 subf r8, r10, r28 subf r29, r10, r29 .vl8_solid_pat_loop: lbzux r3, r8, r10 cmpi cr0, r3, 0 beq cr0,.L64 mr r3,r7 .L64: stbux r3, r9, r31 cmpl cr0, r8, r29 cmpl cr1, r9, r6 bng cr0,.vl8_solid_pat_1 subf r8, r10, r27 .vl8_solid_pat_1: bng cr1,.vl8_solid_pat_loop b .vl8_end .vl8_80: mr r9,r8 subf r8, r10, r28 subf r29, r10, r29 .vl8_mask_pat_loop: lbzux r3, r8, r10 cmpi cr0, r3, 0 beq cr0,.vl8_mask_pat_no_write stb r7, 0(r9) .vl8_mask_pat_no_write cmpl cr0, r8, r29 cmpl cr1, r9, r6 add r9, r9, r31 bng cr0,.vl8_mask_pat_no_reinit subf r8, r10, r27 .vl8_mask_pat_no_reinit: bng cr1,.vl8_mask_pat_loop .vl8_end: addi sp, sp, 96 lmw r27, -20(sp) blrallegro-4.4.3.1/src/ppc/ppcpp8.inc0000664000175000017500000000305513437077643015561 0ustar siegesiegeDMOD SET r7 MakeFunction _ppc_linear_putpixel8 ._ppc_linear_putpixel8: ;BITMAP * r3 ;x r4 ;y r5 ;color r6 lwz DMOD,_drawing_mode[TC](rtoc) lwz DMOD,0(DMOD) cmpli cr0,DMOD,DRAW_MODE_TRANS ble cr0,@OK b ._linear_putpixel8[PR] @OK: lwz r8,BITMAP.clip(r3) cmpi cr0,r8,0 beq cr0,@no_clip lwz r9,BITMAP.ct(r3) lwz r10,BITMAP.cb(r3) cmp cr1,r5,r9 cmp cr6,r5,r10 bltlr cr1 bgelr cr6 lwz r11,BITMAP.cl(r3) lwz r12,BITMAP.cr(r3) cmp cr0,r4,r12 cmp cr7,r4,r11 bgelr cr0 bltlr cr7 @no_clip: rlwinm r10,r5,2,0,29 add r10,r3,r10 lwz r8,64(r10) cmpli cr1,DMOD,DRAW_MODE_XOR add r9,r8,r4 bge cr1,@n_solid stb r6,0(r9) blr @n_solid: bne cr1,@n_xor lbz r3,0(r9) xor r4,r6,r3 stb r4,0(r9) blr @n_xor: cmpli cr7,DMOD,DRAW_MODE_TRANS bne cr7,@n_trans lwz r12,color_map[TC](rtoc) lwz r10,0(r12) lbz r11,0(r9) add r10,r10,r11 rlwinm r8,r6,8,16,23 lbzx r3,r10,r8 stb r3,0(r9) blr @n_trans: lwz r12,_drawing_y_anchor[TC](rtoc) lwz r11,0(r12) subf r11,r11,r5 lwz r10,_drawing_y_mask[TC](rtoc) lwz r12,0(r10) and r11,r11,r12 rlwinm r11,r11,2,0,29 lwz r10,_drawing_pattern[TC](rtoc) lwz r12,0(r10) add r11,r12,r11 lwz r10,64(r11) lwz r12,_drawing_x_anchor[TC](rtoc) lwz r11,0(r12) subf r11,r11,r4 lwz r12,_drawing_x_mask[TC](rtoc) lwz r4,0(r12) and r11,r11,r4 lbzx r8,r10,r11 cmpi cr0,DMOD,DRAW_MODE_COPY_PATTERN bne cr0,@n_cpy_pat stb r8,0(r9) blr @n_cpy_pat: cmpi cr1,DMOD,DRAW_MODE_MASKED_PATTERN cmpi cr6,r8,0 bne cr1,@40 bne cr6,@37 addi r6,r0,0 @37: stb r6,0(r9) blr @40: beqlr cr6 stb r6,0(r9) blr ._ppc_linear_putpixel8_end: allegro-4.4.3.1/src/ppc/ppccc8.inc0000664000175000017500000000151313437077643015524 0ustar siegesiege MACRO CLEARBEGIN lwz r10, 4(r3) lwz r8, 0(r3) lwz r9, 64(r3) lwz r6, 68(r3) subf r6, r9, r6 subf. r6, r8, r6 cmpi cr0, r10, 0 beqlr cr0 bne @_cont mullw r7,r7,r10 addi r10,0,1 @_cont MAKEDOUBLE8 r4,f0,r11 ENDM MakeFunction _ppc_linear_clear_to_color8 ._ppc_linear_clear_to_color8: ;BITMAP * r3 ;color r4 CLEARBEGIN @_r_loop: addi r7,r8,0 HL8SOLID8 r9,r7,r4,f0,r3,r11 add r9,r9,r6 addi r10,r10,-1 cmpi cr2,r10,0 bne cr2,@_r_loop blr ._ppc_linear_clear_to_color8end: MakeFunction _ppc_linear_clear_to_color8_32 ._ppc_linear_clear_to_color8_32: ;BITMAP * r3 ;color r4 ;Cache optimized code should be used only with memory cacheble CLEARBEGIN @_r_loop: addi r7,r8,0 HL8SOLID32 r9,r7,r4,f0,r3,r11 add r9,r9,r6 addi r10,r10,-1 cmpi cr2,r10,0 bne cr2,@_r_loop blr ._ppc_linear_clear_to_color8_32_end:allegro-4.4.3.1/src/ppc/ppcfr8.inc0000664000175000017500000000305313437077643015547 0ustar siegesiege MACRO RECTFILL8BEGIN lwz r12,_drawing_mode[TC](rtoc) lwz r9,0(r12) cmpli cr0,r9,0 beq cr0,@ok b ._normal_rectfill[PR] @ok mr r9,r6 cmp cr0,r4,r9 bng cr0,@5 mr r6,r4 mr r4,r9 @5: mr r9,r7 cmp cr1,r5,r9 bng cr1,@9 mr r7,r5 mr r5,r9 @9: lwz r10,BITMAP.clip(r3) cmpi cr6,r10,0 beq cr6,@n_clip lwz r9,12(r3) cmp cr7,r4,r9 bnl cr7,@13 mr r4,r9 @13: lwz r9,16(r3) cmp cr0,r6,r9 blt cr0,@15 addi r6,r9,-1 @15: cmp cr1,r6,r4 bltlr cr1 @18: lwz r9,20(r3) cmp cr6,r5,r9 bnl cr6,@20 mr r5,r9 @20: lwz r9,24(r3) cmp cr7,r7,r9 blt cr7,@22 addi r7,r9,-1 @22: cmp cr0,r7,r5 bltlr cr0 @n_clip: subf r11,r5,r7 addi r10,r11,1 rlwinm r11,r5,2,0,29 add r11,r3,r11 lwz r9,64(r11) add r9,r4,r9 subf r4,r4,r6 addi r4,r4,1 lwz r6,68(r3) lwz r11,64(r3) subf r6,r11,r6 subf. r6,r4,r6 bne @solid_cont mullw r4,r4,r10 addi r10,r0,1 @solid_cont MAKEDOUBLE8 r8,f0,r11 ENDM MakeFunction _ppc_linear_rectfill8 ._ppc_linear_rectfill8: ;r3 BITMAP* ;r4 x1 ;r5 y1 ;r6 x2 ;r7 y2 ;r8 color RECTFILL8BEGIN ._ppc_linear_rectfill8_n_cache @solid_r_loop: addi r7,r4,0 HL8SOLID8 r9,r7,r8,f0,r3,r11 add r9,r9,r6 addi r10,r10,-1 cmpi cr2,r10,0 bne cr2,@solid_r_loop blr ._ppc_linear_rectfill8_end: MakeFunction _ppc_linear_rectfill8_32 ._ppc_linear_rectfill8_32: ;r3 BITMAP* ;r4 x1 ;r5 y1 ;r6 x2 ;r7 y2 ;r8 color RECTFILL8BEGIN cmpli cr0,r4,64 blt cr0,._ppc_linear_rectfill8_n_cache @solid_r_loop: addi r7,r4,0 HL8SOLID32 r9,r7,r8,f0,r3,r11 add r9,r9,r6 addi r10,r10,-1 cmpi cr2,r10,0 bne cr2,@solid_r_loop blr ._ppc_linear_rectfill8_32_end:allegro-4.4.3.1/src/ppc/ppcgfx.s0000664000175000017500000000031213437077643015320 0ustar siegesiege INCLUDE 'ppcdef.inc' INCLUDE 'pgfx8.inc' INCLUDE 'ppchl8.inc' INCLUDE 'ppcvl8.inc' INCLUDE 'ppcpp8.inc' INCLUDE 'ppcfr8.inc' INCLUDE 'ppccc8.inc' INCLUDE 'ppccc15.inc'allegro-4.4.3.1/src/ppc/ppccc15.inc0000664000175000017500000000357613437077643015615 0ustar siegesiegeDST SET ARG1 COR SET ARG2 MACRO PRECLEAR15 lwz r10, BITMAP.h(DST) rlwinm COR, COR, 0, 17, 31 lwz r11, BITMAP.w(DST) rlwinm r5, COR, 16, 0, 15 lwz r9, BITMAP._line(DST) add COR, r5, COR lwz r8, BITMAP._line1(DST) subf r8, r9, r8 rlwinm r6, r11, 1, 0, 30 subf r8, r6, r8 cmpi cr0, r10, 0 beqlr cr0 cmpi cr1, r11, 0 beqlr cr1 stw COR,-8(sp) stw COR,-4(sp) lfd f0,-8(sp) ENDM MakeFunction _ppc_linear_clear_to_color15 ._ppc_linear_clear_to_color15: PRECLEAR15 @r_loop: rlwinm. DST,r9,0,30,30 beq @pre_n_h sth COR,0(r9) addi r9,r9,2 @pre_n_h: rlwinm. DST,r9,0,29,29 beq @pre_n_w stw COR,0(r9) addi r9,r9,4 @pre_n_w: mtcrf 0x01,r11 srawi. DST,r11,2 mtctr DST @loop: stfd f0,0(r9) addi r9,r9,8 bdnz @loop bc 4,30,@pos_n_w stw COR,0(r9) addi r9,r9,4 @pos_n_w: bc 4,31,@pos_n_h sth COR,0(r9) addi r9,r9,2 @pos_n_h: add r9,r9,r8 addi r10,r10,-1 cmpi cr2,r10,0 bne cr2,@r_loop @end: blr ._ppc_linear_clear_to_color15_end: MakeFunction _ppc_linear_clear_to_color15_32 ._ppc_linear_clear_to_color15_32: PRECLEAR15 @r_loop: rlwinm. DST,r9,0,30,30 beq @pre_n_h sth COR,0(r9) addi r9,r9,2 @pre_n_h: rlwinm. DST,r9,0,29,29 beq @pre_n_w stw COR,0(r9) addi r9,r9,4 @pre_n_w: rlwinm. DST,r9,0,28,28 beq @pre_n_d stfd f0,0(r9) addi r9,r9,8 @pre_n_d: rlwinm. DST,r9,0,27,27 beq @pre_n_q stfd f0,0(r9) stfd f0,8(r9) addi r9,r9,16 @pre_n_q: mtcrf 0x01,r11 srawi. DST,r11,4 mtctr DST @loop: dcbz 0,r9 stfd f0,0(r9) stfd f0,8(r9) stfd f0,16(r9) stfd f0,24(r9) addi r9,r9,32 bdnz @loop bc 4,28,@pos_n_q stfd f0,0(r9) stfd f0,8(r9) addi r9,r9,16 @pos_n_q: bc 4,29,@pos_n_d stfd f0,0(r9) addi r9,r9,8 @pos_n_d: bc 4,30,@pos_n_w stw COR,0(r9) addi r9,r9,4 @pos_n_w: bc 4,31,@pos_n_h sth COR,0(r9) addi r9,r9,2 @pos_n_h: add r9,r9,r8 addi r10,r10,-1 cmpi cr2,r10,0 bne cr2,@r_loop @end: blr ._ppc_linear_clear_to_color15_32_end: allegro-4.4.3.1/src/mouse.c0000664000175000017500000007560413437077643014377 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mouse input routines. * * By Shawn Hargreaves. * * Mark Wodrich added double-buffered drawing of the mouse pointer and * the set_mouse_sprite_focus() function. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" /* dummy driver for systems without a mouse */ static int nomouse_init(void) { return 0; } static void nomouse_exit(void) { } MOUSE_DRIVER mousedrv_none = { MOUSEDRV_NONE, empty_string, empty_string, "No mouse", nomouse_init, nomouse_exit, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; MOUSE_DRIVER *mouse_driver = NULL; /* the active driver */ int _mouse_type = MOUSEDRV_AUTODETECT; /* driver ID */ int _mouse_installed = FALSE; volatile int mouse_x = 0; /* user-visible position */ volatile int mouse_y = 0; volatile int mouse_z = 0; volatile int mouse_w = 0; volatile int mouse_b = 0; volatile int mouse_pos = 0; int _mouse_x = 0; /* internal position */ int _mouse_y = 0; int _mouse_z = 0; int _mouse_w = 0; int _mouse_b = 0; int _mouse_on = TRUE; static int mon = TRUE; static int emulate_three = FALSE; volatile int freeze_mouse_flag = FALSE; void (*mouse_callback)(int flags) = NULL; int mouse_x_focus = 1; /* focus point in mouse sprite */ int mouse_y_focus = 1; #define MOUSE_OFFSCREEN -4096 /* somewhere to put unwanted cursors */ /* default mouse cursor sizes */ #define DEFAULT_SPRITE_W 16 #define DEFAULT_SPRITE_H 16 /* Default cursor shapes */ /* TODO: add other shapes! */ static char mouse_arrow_data[DEFAULT_SPRITE_H * DEFAULT_SPRITE_W] = { 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }; static char mouse_busy_data[DEFAULT_SPRITE_H * DEFAULT_SPRITE_W] = { 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 2, 0, 0, 2, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 2, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 2, 0, 2, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 2, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 2, 1, 1, 1, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0 }; BITMAP *_mouse_pointer = NULL; /* default mouse pointer */ BITMAP *mouse_sprite = NULL; /* current mouse pointer */ BITMAP *_mouse_screen = NULL; /* where to draw the pointer */ static BITMAP *default_cursors[AL_NUM_MOUSE_CURSORS]; static BITMAP *cursors[AL_NUM_MOUSE_CURSORS]; static int allow_system_cursor; /* Allow native OS cursor? */ static int use_system_cursor = FALSE; /* Use native OS cursor? */ static int got_hw_cursor = FALSE; /* hardware pointer available? */ static int hw_cursor_dirty = FALSE; /* need to set a new pointer? */ static int current_cursor = MOUSE_CURSOR_ALLEGRO; static int mx, my; /* previous mouse pointer position */ static BITMAP *ms = NULL; /* previous screen data */ static BITMAP *mtemp = NULL; /* double-buffer drawing area */ #define SCARED_SIZE 16 /* for unscare_mouse() */ static BITMAP *scared_screen[SCARED_SIZE]; static int scared_freeze[SCARED_SIZE]; static int scared_size = 0; static int mouse_polled = FALSE; /* are we in polling mode? */ static int mouse_semaphore = FALSE; /* reentrant interrupt? */ /* draw_mouse_doublebuffer: * Eliminates mouse-cursor flicker by using an off-screen buffer for * updating the cursor, and blitting only the final screen image. * newx and newy contain the new cursor position, and mx and my are * assumed to contain previous cursor pos. This routine is called if * mouse cursor is to be erased and redrawn, and the two position overlap. */ static void draw_mouse_doublebuffer(int newx, int newy) { int x1, y1, w, h; /* grab bit of screen containing where we are and where we'll be */ x1 = MIN(mx, newx) - mouse_x_focus; y1 = MIN(my, newy) - mouse_y_focus; /* get width of area */ w = MAX(mx, newx) - MIN(mx, newx) + mouse_sprite->w+1; h = MAX(my, newy) - MIN(my, newy) + mouse_sprite->h+1; /* make new co-ords relative to 'mtemp' bitmap co-ords */ newx -= mouse_x_focus+x1; newy -= mouse_y_focus+y1; /* save screen image in 'mtemp' */ blit(_mouse_screen, mtemp, x1, y1, 0, 0, w, h); /* blit saved image in 'ms' to corect place in this buffer */ blit(ms, mtemp, 0, 0, mx-mouse_x_focus-x1, my-mouse_y_focus-y1, mouse_sprite->w, mouse_sprite->h); /* draw mouse at correct place in 'mtemp' */ blit(mtemp, ms, newx, newy, 0, 0, mouse_sprite->w, mouse_sprite->h); draw_sprite(mtemp, mouse_sprite, newx, newy); /* blit 'mtemp' to screen */ blit(mtemp, _mouse_screen, 0, 0, x1, y1, w, h); } END_OF_STATIC_FUNCTION(draw_mouse_doublebuffer); /* draw_mouse: * Mouse pointer drawing routine. If remove is set, deletes the old mouse * pointer. If add is set, draws a new one. */ static void draw_mouse(int remove, int add) { int normal_draw = (remove ^ add); int newmx = _mouse_x; int newmy = _mouse_y; int cf = _mouse_screen->clip; int cl = _mouse_screen->cl; int cr = _mouse_screen->cr; int ct = _mouse_screen->ct; int cb = _mouse_screen->cb; _mouse_screen->clip = TRUE; _mouse_screen->cl = _mouse_screen->ct = 0; _mouse_screen->cr = _mouse_screen->w; _mouse_screen->cb = _mouse_screen->h; if (!_mouse_on) { newmx = MOUSE_OFFSCREEN; newmy = MOUSE_OFFSCREEN; mon = FALSE; } else mon = TRUE; if (!normal_draw) { if ((newmx <= mx-mouse_sprite->w) || (newmx >= mx+mouse_sprite->w) || (newmy <= my-mouse_sprite->h) || (newmy >= my+mouse_sprite->h)) normal_draw = 1; } if (normal_draw) { if (remove) blit(ms, _mouse_screen, 0, 0, mx-mouse_x_focus, my-mouse_y_focus, mouse_sprite->w, mouse_sprite->h); if (add) { blit(_mouse_screen, ms, newmx-mouse_x_focus, newmy-mouse_y_focus, 0, 0, mouse_sprite->w, mouse_sprite->h); draw_sprite(_mouse_screen, cursors[current_cursor], newmx-mouse_x_focus, newmy-mouse_y_focus); } } else draw_mouse_doublebuffer(newmx, newmy); mx = newmx; my = newmy; _mouse_screen->clip = cf; _mouse_screen->cl = cl; _mouse_screen->cr = cr; _mouse_screen->ct = ct; _mouse_screen->cb = cb; } END_OF_STATIC_FUNCTION(draw_mouse); /* update_mouse: * Worker function to update the mouse position variables with new values. */ static void update_mouse(void) { int x, y, z, w, b, flags = 0; if (freeze_mouse_flag) { x = mx; y = my; } else { x = _mouse_x; y = _mouse_y; } z = _mouse_z; w = _mouse_w; b = _mouse_b; if (emulate_three) { if ((b & 3) == 3) b = 4; } if ((mouse_x != x) || (mouse_y != y) || (mouse_z != z) || (mouse_w != w) || (mouse_b != b)) { if (mouse_callback) { if ((mouse_x != x) || (mouse_y != y)) flags |= MOUSE_FLAG_MOVE; if (mouse_z != z) flags |= MOUSE_FLAG_MOVE_Z; if (mouse_w != w) flags |= MOUSE_FLAG_MOVE_W; if ((b & 1) && !(mouse_b & 1)) flags |= MOUSE_FLAG_LEFT_DOWN; else if (!(b & 1) && (mouse_b & 1)) flags |= MOUSE_FLAG_LEFT_UP; if ((b & 2) && !(mouse_b & 2)) flags |= MOUSE_FLAG_RIGHT_DOWN; else if (!(b & 2) && (mouse_b & 2)) flags |= MOUSE_FLAG_RIGHT_UP; if ((b & 4) && !(mouse_b & 4)) flags |= MOUSE_FLAG_MIDDLE_DOWN; else if (!(b & 4) && (mouse_b & 4)) flags |= MOUSE_FLAG_MIDDLE_UP; mouse_x = x; mouse_y = y; mouse_z = z; mouse_w = w; mouse_b = b; mouse_pos = ((x & 0xFFFF) << 16) | (y & 0xFFFF); mouse_callback(flags); } else { mouse_x = x; mouse_y = y; mouse_z = z; mouse_w = w; mouse_b = b; mouse_pos = ((x & 0xFFFF) << 16) | (y & 0xFFFF); } } } END_OF_STATIC_FUNCTION(update_mouse); /* mouse_move: * Timer interrupt handler for redrawing the mouse pointer. */ static void mouse_move(void) { if (mouse_semaphore) return; mouse_semaphore = TRUE; /* periodic poll */ if (mouse_driver->timer_poll) { mouse_driver->timer_poll(); if (!mouse_polled) update_mouse(); } /* redraw pointer */ if ((!freeze_mouse_flag) && (_mouse_screen) && ((mx != _mouse_x) || (my != _mouse_y) || (mon != _mouse_on))) { acquire_bitmap(_mouse_screen); if (gfx_capabilities & GFX_HW_CURSOR) { if (_mouse_on) { gfx_driver->move_mouse(mx=_mouse_x, my=_mouse_y); mon = TRUE; } else { gfx_driver->move_mouse(mx=MOUSE_OFFSCREEN, my=MOUSE_OFFSCREEN); mon = FALSE; } } else { #ifdef ALLEGRO_DOS /* bodge to avoid using non legacy 386 asm code inside a timer handler */ int old_capabilities = cpu_capabilities; cpu_capabilities = 0; #endif draw_mouse(TRUE, TRUE); #ifdef ALLEGRO_DOS cpu_capabilities = old_capabilities; #endif } release_bitmap(_mouse_screen); } mouse_semaphore = FALSE; } END_OF_STATIC_FUNCTION(mouse_move); /* _handle_mouse_input: * Callback for an asynchronous driver to tell us when it has changed the * position. */ void _handle_mouse_input(void) { if (!mouse_polled) update_mouse(); } END_OF_FUNCTION(_handle_mouse_input); /* create_mouse_pointer: * Creates the default arrow mouse sprite using the current color depth * and palette. */ static BITMAP *create_mouse_pointer(char *data) { BITMAP *bmp; int x, y; int col; bmp = create_bitmap(DEFAULT_SPRITE_W, DEFAULT_SPRITE_H); for (y=0; yvtable->mask_color; break; } putpixel(bmp, x, y, col); } } return bmp; } /* set_mouse_sprite: * Sets the sprite to be used for the mouse pointer. If the sprite is * NULL, restores the default arrow. */ void set_mouse_sprite(struct BITMAP *sprite) { BITMAP *old_mouse_screen = _mouse_screen; int am_using_sys_cursor = use_system_cursor; if (!mouse_driver) return; if (_mouse_screen && !am_using_sys_cursor) show_mouse(NULL); if (sprite) mouse_sprite = sprite; else { if (_mouse_pointer) destroy_bitmap(_mouse_pointer); _mouse_pointer = create_mouse_pointer(mouse_arrow_data); mouse_sprite = _mouse_pointer; } cursors[MOUSE_CURSOR_ALLEGRO] = mouse_sprite; lock_bitmap((struct BITMAP*)mouse_sprite); /* make sure the ms bitmap is big enough */ if ((!ms) || (ms->w < mouse_sprite->w) || (ms->h < mouse_sprite->h) || (bitmap_color_depth(mouse_sprite) != bitmap_color_depth(ms))) { if (ms) { destroy_bitmap(ms); destroy_bitmap(mtemp); } ms = create_bitmap(mouse_sprite->w, mouse_sprite->h); lock_bitmap(ms); mtemp = create_bitmap(mouse_sprite->w*2, mouse_sprite->h*2); lock_bitmap(mtemp); } mouse_x_focus = 1; mouse_y_focus = 1; if (!am_using_sys_cursor) hw_cursor_dirty = TRUE; if (old_mouse_screen && !am_using_sys_cursor) show_mouse(old_mouse_screen); } /* select_mouse_cursor: * Selects the shape of the mouse cursor. */ void select_mouse_cursor(int cursor) { ASSERT(cursor >= 0); ASSERT(cursor < AL_NUM_MOUSE_CURSORS); current_cursor = cursor; } /* set_mouse_cursor_bitmap: * Changes the default Allegro cursor for a mouse cursor */ void set_mouse_cursor_bitmap(int cursor, struct BITMAP *bmp) { ASSERT(cursor >= 0); ASSERT(cursor != MOUSE_CURSOR_NONE); ASSERT(cursor < AL_NUM_MOUSE_CURSORS); cursors[cursor] = bmp?bmp:default_cursors[cursor]; } /* set_mouse_sprite_focus: * Sets co-ordinate (x, y) in the sprite to be the mouse location. * Call after set_mouse_sprite(). Doesn't redraw the sprite. */ void set_mouse_sprite_focus(int x, int y) { if (!mouse_driver) return; mouse_x_focus = x; mouse_y_focus = y; hw_cursor_dirty = TRUE; } /* show_os_cursor: * Tries to display the OS cursor. Returns 0 if a cursor is displayed after the * function returns, else -1. This is similar to calling show_mouse(screen) * after calling enable_hardware_cursor and checking gfx_capabilities for * GFX_HW_CURSOR, but is easier to use in cases where you don't need Allegro's * software cursor even if no os cursor is available. */ int show_os_cursor(int cursor) { int r = -1; if (!mouse_driver) return r; remove_int(mouse_move); gfx_capabilities &= ~(GFX_HW_CURSOR|GFX_SYSTEM_CURSOR); if (cursor != MOUSE_CURSOR_NONE) { if (mouse_driver->enable_hardware_cursor) { mouse_driver->enable_hardware_cursor(TRUE); } /* default system cursor? */ if (cursor != MOUSE_CURSOR_ALLEGRO) { if (mouse_driver->select_system_cursor) { if (mouse_driver->select_system_cursor(cursor) != 0) { gfx_capabilities |= (GFX_HW_CURSOR|GFX_SYSTEM_CURSOR); r = 0; goto done; } } goto done; } else { /* set custom hardware cursor */ if (gfx_driver) { if (gfx_driver->set_mouse_sprite) { if (gfx_driver->set_mouse_sprite(mouse_sprite, mouse_x_focus, mouse_y_focus)) goto done; } if (gfx_driver->show_mouse) { if (gfx_driver->show_mouse(screen, mouse_x, mouse_y)) goto done; } gfx_capabilities |= GFX_HW_CURSOR; r = 0; goto done; } } } else { if (gfx_driver && gfx_driver->hide_mouse) gfx_driver->hide_mouse(); } done: if (mouse_driver->timer_poll) install_int(mouse_move, 10); return r; } /* show_mouse: * Tells Allegro to display a mouse pointer. This only works when the timer * module is active. The mouse pointer will be drawn onto the bitmap bmp, * which should normally be the hardware screen. To turn off the mouse * pointer, which you must do before you draw anything onto the screen, call * show_mouse(NULL). If you forget to turn off the mouse pointer when * drawing something, the SVGA bank switching code will become confused and * will produce garbage all over the screen. */ void show_mouse(BITMAP *bmp) { if (!mouse_driver) return; remove_int(mouse_move); /* Remove the mouse cursor */ if (_mouse_screen) { acquire_bitmap(_mouse_screen); if (gfx_capabilities & GFX_HW_CURSOR) { gfx_driver->hide_mouse(); gfx_capabilities &= ~(GFX_HW_CURSOR|GFX_SYSTEM_CURSOR); hw_cursor_dirty = TRUE; } else draw_mouse(TRUE, FALSE); release_bitmap(_mouse_screen); } _mouse_screen = bmp; if (bmp && (current_cursor != MOUSE_CURSOR_NONE)) { acquire_bitmap(_mouse_screen); /* Default system cursor? */ if ((current_cursor != MOUSE_CURSOR_ALLEGRO) && allow_system_cursor) { if (mouse_driver && mouse_driver->select_system_cursor) { use_system_cursor = mouse_driver->select_system_cursor(current_cursor); if (use_system_cursor) { gfx_capabilities |= GFX_HW_CURSOR|GFX_SYSTEM_CURSOR; hw_cursor_dirty = FALSE; got_hw_cursor = TRUE; } } } else { use_system_cursor = FALSE; } /* Custom hardware cursor? */ if (hw_cursor_dirty) { got_hw_cursor = FALSE; if ((gfx_driver) && (gfx_driver->set_mouse_sprite) && (!_dispsw_status)) if (gfx_driver->set_mouse_sprite(mouse_sprite, mouse_x_focus, mouse_y_focus) == 0) got_hw_cursor = TRUE; hw_cursor_dirty = FALSE; } /* Try to display hardware (custom or system) cursor */ if ((got_hw_cursor) && (is_same_bitmap(bmp, screen))) if (gfx_driver->show_mouse(bmp, mx=mouse_x, my=mouse_y) == 0) gfx_capabilities |= GFX_HW_CURSOR; /* Draw cursor manually if we can't do that */ if (!(gfx_capabilities & GFX_HW_CURSOR)) { draw_mouse(FALSE, TRUE); use_system_cursor = FALSE; } release_bitmap(_mouse_screen); install_int(mouse_move, 10); } else { if (mouse_driver->timer_poll) install_int(mouse_move, 10); } } /* scare_mouse: * Removes the mouse pointer prior to a drawing operation, if that is * required (ie. noop if the mouse is on a memory bitmap, or a hardware * cursor is in use). This operation can later be reversed by calling * unscare_mouse(). */ void scare_mouse(void) { if (!mouse_driver) return; if ((is_same_bitmap(screen, _mouse_screen)) && (!(gfx_capabilities & GFX_HW_CURSOR))) { if (scared_size < SCARED_SIZE) { scared_screen[scared_size] = _mouse_screen; scared_freeze[scared_size] = FALSE; } show_mouse(NULL); } else { if (scared_size < SCARED_SIZE) { scared_screen[scared_size] = NULL; scared_freeze[scared_size] = FALSE; } } scared_size++; } /* scare_mouse_area: * Removes the mouse pointer prior to a drawing operation, if that is * required (ie. noop if the mouse is on a memory bitmap, or a hardware * cursor is in use, or the mouse lies outside of the specified bounds * (in this last case, the mouse is frozen)). This operation can later * be reversed by calling unscare_mouse(). */ void scare_mouse_area(int x, int y, int w, int h) { int was_frozen; if (!mouse_driver) return; if ((is_same_bitmap(screen, _mouse_screen)) && (!(gfx_capabilities & GFX_HW_CURSOR))) { was_frozen = freeze_mouse_flag; freeze_mouse_flag = TRUE; if ((mx - mouse_x_focus < x + w) && (my - mouse_y_focus < y + h) && (mx - mouse_x_focus + mouse_sprite->w >= x) && (my - mouse_y_focus + mouse_sprite->h >= y)) { if (scared_size < SCARED_SIZE) { scared_screen[scared_size] = _mouse_screen; scared_freeze[scared_size] = FALSE; } freeze_mouse_flag = was_frozen; show_mouse(NULL); } else { if (scared_size < SCARED_SIZE) { scared_screen[scared_size] = NULL; if (was_frozen) { scared_freeze[scared_size] = FALSE; freeze_mouse_flag = was_frozen; } else scared_freeze[scared_size] = TRUE; } } } else { if (scared_size < SCARED_SIZE) { scared_screen[scared_size] = NULL; scared_freeze[scared_size] = FALSE; } } scared_size++; } /* unscare_mouse: * Restores the original mouse state, after a call to scare_mouse() or * scare_mouse_area. */ void unscare_mouse(void) { if (!mouse_driver) return; if (scared_size > 0) scared_size--; if (scared_size < SCARED_SIZE) { if (scared_screen[scared_size]) show_mouse(scared_screen[scared_size]); if (scared_freeze[scared_size]) freeze_mouse_flag = FALSE; scared_screen[scared_size] = NULL; scared_freeze[scared_size] = FALSE; } } /* position_mouse: * Moves the mouse to screen position x, y. This is safe to call even * when a mouse pointer is being displayed. */ void position_mouse(int x, int y) { BITMAP *old_mouse_screen = _mouse_screen; if (!mouse_driver) return; if (_mouse_screen) show_mouse(NULL); if (mouse_driver->position) { mouse_driver->position(x, y); } else { _mouse_x = x; _mouse_y = y; } update_mouse(); if (old_mouse_screen) show_mouse(old_mouse_screen); } /* position_mouse_z: * Sets the mouse third axis to position z. */ void position_mouse_z(int z) { if (!mouse_driver) return; _mouse_z = z; update_mouse(); } /* position_mouse_w: * Sets the mouse fourth axis to position w. */ void position_mouse_w(int w) { if (!mouse_driver) return; _mouse_w = w; update_mouse(); } /* set_mouse_range: * Sets the screen area within which the mouse can move. Pass the top left * corner and the bottom right corner (inclusive). If you don't call this * function the range defaults to (0, 0, SCREEN_W-1, SCREEN_H-1). */ void set_mouse_range(int x1, int y1, int x2, int y2) { BITMAP *old_mouse_screen = _mouse_screen; ASSERT(x1 >= 0); ASSERT(y1 >= 0); ASSERT(x2 >= x1); ASSERT(y2 >= y2); if (!mouse_driver) return; if (_mouse_screen) show_mouse(NULL); if (mouse_driver->set_range) mouse_driver->set_range(x1, y1, x2, y2); update_mouse(); if (old_mouse_screen) show_mouse(old_mouse_screen); } /* set_mouse_speed: * Sets the mouse speed. Larger values of xspeed and yspeed represent * slower mouse movement: the default for both is 2. */ void set_mouse_speed(int xspeed, int yspeed) { if ((mouse_driver) && (mouse_driver->set_speed)) mouse_driver->set_speed(xspeed, yspeed); } /* get_mouse_mickeys: * Measures the mickey count (how far the mouse has moved since the last * call to this function). */ void get_mouse_mickeys(int *mickeyx, int *mickeyy) { if ((mouse_driver) && (mouse_driver->get_mickeys)) { mouse_driver->get_mickeys(mickeyx, mickeyy); } else { *mickeyx = 0; *mickeyy = 0; } } /* mouse_on_screen: * Tells whether the mouse pointer position is currently on the screen. * Returns 0 when offscreen, and non-zero otherwise. */ int mouse_on_screen() { return _mouse_on; } /* enable_hardware_cursor: * enabels the hardware cursor on platforms where this needs to be done * explicitly and allows system cursors to be used. */ void enable_hardware_cursor(void) { if ((mouse_driver) && (mouse_driver->enable_hardware_cursor)) { mouse_driver->enable_hardware_cursor(TRUE); allow_system_cursor = TRUE; if (is_same_bitmap(_mouse_screen, screen)) { BITMAP *bmp = _mouse_screen; show_mouse(NULL); show_mouse(bmp); } } } /* disable_hardware_cursor: * disables the hardware cursor on platforms where this interferes with * mickeys and disables system cursors. */ void disable_hardware_cursor(void) { if ((mouse_driver) && (mouse_driver->enable_hardware_cursor)) { mouse_driver->enable_hardware_cursor(FALSE); allow_system_cursor = FALSE; if (is_same_bitmap(_mouse_screen, screen)) { BITMAP *bmp = _mouse_screen; show_mouse(NULL); show_mouse(bmp); } } } /* poll_mouse: * Polls the current mouse state, and updates the user-visible information * accordingly. On some drivers this is actually required to get the * input, while on others it is only present to keep compatibility with * systems that do need it. So that people can test their polling code * even on platforms that don't strictly require it, after this function * has been called once, the entire system will switch into polling mode * and will no longer operate asynchronously even if the driver actually * does support that. */ int poll_mouse(void) { if (!mouse_driver) return -1; if (mouse_driver->poll) mouse_driver->poll(); update_mouse(); mouse_polled = TRUE; return 0; } END_OF_FUNCTION(poll_mouse); /* mouse_needs_poll: * Checks whether the current driver uses polling. */ int mouse_needs_poll(void) { return mouse_polled; } END_OF_FUNCTION(mouse_needs_poll); /* set_mouse_etc: * Hook for setting up the motion range, cursor graphic, etc, called by * the mouse init and whenever we change the graphics mode. */ static void set_mouse_etc(void) { if ((!mouse_driver) || (!gfx_driver)) return; if ((!_mouse_pointer) || ((screen) && (_mouse_pointer) && (bitmap_color_depth(_mouse_pointer) != bitmap_color_depth(screen)))) set_mouse_sprite(NULL); else hw_cursor_dirty = TRUE; set_mouse_range(0, 0, SCREEN_W-1, SCREEN_H-1); set_mouse_speed(2, 2); position_mouse(SCREEN_W/2, SCREEN_H/2); } /* install_mouse: * Installs the Allegro mouse handler. You must do this before using any * other mouse functions. Return -1 if it can't find a mouse driver, * otherwise the number of buttons on the mouse. */ int install_mouse(void) { _DRIVER_INFO *driver_list; int num_buttons = -1; int config_num_buttons; AL_CONST char *emulate; char tmp1[64], tmp2[64]; int i; if (mouse_driver) return 0; LOCK_VARIABLE(mouse_driver); LOCK_VARIABLE(mousedrv_none); LOCK_VARIABLE(mouse_x); LOCK_VARIABLE(mouse_y); LOCK_VARIABLE(mouse_z); LOCK_VARIABLE(mouse_w); LOCK_VARIABLE(mouse_b); LOCK_VARIABLE(mouse_pos); LOCK_VARIABLE(_mouse_x); LOCK_VARIABLE(_mouse_y); LOCK_VARIABLE(_mouse_z); LOCK_VARIABLE(_mouse_w); LOCK_VARIABLE(_mouse_b); LOCK_VARIABLE(_mouse_on); LOCK_VARIABLE(mon); LOCK_VARIABLE(emulate_three); LOCK_VARIABLE(freeze_mouse_flag); LOCK_VARIABLE(mouse_callback); LOCK_VARIABLE(mouse_x_focus); LOCK_VARIABLE(mouse_y_focus); LOCK_VARIABLE(mouse_sprite); LOCK_VARIABLE(_mouse_pointer); LOCK_VARIABLE(_mouse_screen); LOCK_VARIABLE(mx); LOCK_VARIABLE(my); LOCK_VARIABLE(ms); LOCK_VARIABLE(mtemp); LOCK_VARIABLE(mouse_polled); LOCK_VARIABLE(mouse_semaphore); LOCK_VARIABLE(cursors); LOCK_FUNCTION(draw_mouse_doublebuffer); LOCK_FUNCTION(draw_mouse); LOCK_FUNCTION(update_mouse); LOCK_FUNCTION(mouse_move); LOCK_FUNCTION(poll_mouse); LOCK_FUNCTION(mouse_needs_poll); LOCK_FUNCTION(_handle_mouse_input); /* Construct mouse pointers */ if (!default_cursors[MOUSE_CURSOR_ARROW]) default_cursors[MOUSE_CURSOR_ARROW] = create_mouse_pointer(mouse_arrow_data); if (!default_cursors[MOUSE_CURSOR_BUSY]) default_cursors[MOUSE_CURSOR_BUSY] = create_mouse_pointer(mouse_busy_data); if (!default_cursors[MOUSE_CURSOR_QUESTION]) default_cursors[MOUSE_CURSOR_QUESTION] = create_mouse_pointer(mouse_arrow_data); if (!default_cursors[MOUSE_CURSOR_EDIT]) default_cursors[MOUSE_CURSOR_EDIT] = create_mouse_pointer(mouse_arrow_data); cursors[MOUSE_CURSOR_ARROW] = default_cursors[MOUSE_CURSOR_ARROW]; cursors[MOUSE_CURSOR_BUSY] = default_cursors[MOUSE_CURSOR_BUSY]; cursors[MOUSE_CURSOR_QUESTION] = default_cursors[MOUSE_CURSOR_QUESTION]; cursors[MOUSE_CURSOR_EDIT] = default_cursors[MOUSE_CURSOR_EDIT]; if (system_driver->mouse_drivers) driver_list = system_driver->mouse_drivers(); else driver_list = _mouse_driver_list; if (_mouse_type == MOUSEDRV_AUTODETECT) _mouse_type = get_config_id(uconvert_ascii("mouse", tmp1), uconvert_ascii("mouse", tmp2), MOUSEDRV_AUTODETECT); if (_mouse_type != MOUSEDRV_AUTODETECT) { for (i=0; driver_list[i].driver; i++) { if (driver_list[i].id == _mouse_type) { mouse_driver = driver_list[i].driver; break; } } } if (mouse_driver) { mouse_driver->name = mouse_driver->desc = get_config_text(mouse_driver->ascii_name); num_buttons = mouse_driver->init(); } else { for (i=0; num_buttons<0; i++) { if (!driver_list[i].driver) break; mouse_driver = driver_list[i].driver; mouse_driver->name = mouse_driver->desc = get_config_text(mouse_driver->ascii_name); num_buttons = mouse_driver->init(); } } if (num_buttons < 0) { mouse_driver = NULL; return -1; } config_num_buttons = get_config_int(uconvert_ascii("mouse", tmp1), uconvert_ascii("num_buttons", tmp2), -1); emulate = get_config_string(uconvert_ascii("mouse", tmp1), uconvert_ascii("emulate_three", tmp2), NULL); /* clamp config_num_buttons to zero/positive values */ if (config_num_buttons >= 0) num_buttons = config_num_buttons; if ((emulate) && ((i = ugetc(emulate)) != 0)) { if ((i == 'y') || (i == 'Y') || (i == '1')) emulate_three = TRUE; else emulate_three = FALSE; } else { emulate_three = FALSE; } mouse_polled = (mouse_driver->poll) ? TRUE : FALSE; _mouse_installed = TRUE; disable_hardware_cursor(); set_mouse_etc(); _add_exit_func(remove_mouse, "remove_mouse"); if (mouse_driver->timer_poll) install_int(mouse_move, 10); return num_buttons; } /* remove_mouse: * Removes the mouse handler. You don't normally need to call this, because * allegro_exit() will do it for you. */ void remove_mouse(void) { if (!mouse_driver) return; show_mouse(NULL); remove_int(mouse_move); mouse_driver->exit(); mouse_driver = NULL; _mouse_installed = FALSE; mouse_x = mouse_y = _mouse_x = _mouse_y = 0; mouse_z = _mouse_z = 0; mouse_w = _mouse_w = 0; mouse_b = _mouse_b = 0; mouse_pos = 0; mouse_polled = FALSE; destroy_bitmap(default_cursors[MOUSE_CURSOR_ARROW]); destroy_bitmap(default_cursors[MOUSE_CURSOR_BUSY]); destroy_bitmap(default_cursors[MOUSE_CURSOR_QUESTION]); destroy_bitmap(default_cursors[MOUSE_CURSOR_EDIT]); cursors[MOUSE_CURSOR_ARROW] = default_cursors[MOUSE_CURSOR_ARROW] = NULL; cursors[MOUSE_CURSOR_BUSY] = default_cursors[MOUSE_CURSOR_BUSY] = NULL; cursors[MOUSE_CURSOR_QUESTION] = default_cursors[MOUSE_CURSOR_QUESTION] = NULL; cursors[MOUSE_CURSOR_EDIT] = default_cursors[MOUSE_CURSOR_EDIT] = NULL; if (_mouse_pointer) { destroy_bitmap(_mouse_pointer); _mouse_pointer = NULL; } if (ms) { destroy_bitmap(ms); ms = NULL; destroy_bitmap(mtemp); mtemp = NULL; } _remove_exit_func(remove_mouse); } /* _mouse_constructor: * Register mouse functions if this object file is linked in. */ #ifdef ALLEGRO_USE_CONSTRUCTOR CONSTRUCTOR_FUNCTION(void _mouse_constructor(void)); #endif static struct _AL_LINKER_MOUSE mouse_linker = { set_mouse_etc, show_mouse, &_mouse_screen }; void _mouse_constructor(void) { _al_linker_mouse = &mouse_linker; } allegro-4.4.3.1/src/vtable16.c0000664000175000017500000000462213437077643014663 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Table of functions for drawing onto 16 bit linear bitmaps. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_COLOR16 void _linear_draw_sprite16_end(void); void _linear_blit16_end(void); GFX_VTABLE __linear_vtable16 = { 16, MASK_COLOR_16, _stub_unbank_switch, NULL, NULL, NULL, NULL, NULL, _linear_getpixel16, _linear_putpixel16, _linear_vline16, _linear_hline16, _linear_hline16, _normal_line, _fast_line, _normal_rectfill, _soft_triangle, _linear_draw_sprite16, _linear_draw_256_sprite16, _linear_draw_sprite_v_flip16, _linear_draw_sprite_h_flip16, _linear_draw_sprite_vh_flip16, _linear_draw_trans_sprite16, _linear_draw_trans_rgba_sprite16, _linear_draw_lit_sprite16, _linear_draw_rle_sprite16, _linear_draw_trans_rle_sprite16, _linear_draw_trans_rgba_rle_sprite16, _linear_draw_lit_rle_sprite16, _linear_draw_character16, _linear_draw_glyph16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit16, _linear_blit_backward16, _blit_between_formats, _linear_masked_blit16, _linear_clear_to_color16, _pivot_scaled_sprite_flip, NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) _soft_draw_gouraud_sprite, _linear_draw_sprite16_end, _linear_blit16_end, _soft_polygon, _soft_rect, _soft_circle, _soft_circlefill, _soft_ellipse, _soft_ellipsefill, _soft_arc, _soft_spline, _soft_floodfill, _soft_polygon3d, _soft_polygon3d_f, _soft_triangle3d, _soft_triangle3d_f, _soft_quad3d, _soft_quad3d_f, _linear_draw_sprite_ex16 }; #endif allegro-4.4.3.1/src/linux/0000775000175000017500000000000013437077643014226 5ustar siegesiegeallegro-4.4.3.1/src/linux/vtswitch.c0000664000175000017500000001436313437077643016254 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Virtual console handling routines for Linux console Allegro. * * By George Foot, based on Marek Habersack's code. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #ifdef ALLEGRO_HAVE_MMAP #include #endif #if !defined(_POSIX_MAPPED_FILES) || !defined(ALLEGRO_HAVE_MMAP) #error "Sorry, mapped files are required for Allegro/Linux to work!" #endif static int switch_mode = SWITCH_PAUSE; static int vtswitch_initialised = 0; static struct vt_mode startup_vtmode; volatile int __al_linux_switching_blocked = 0; static volatile int console_active = 1; /* are we active? */ static volatile int console_should_be_active = 1; /* should we be? */ int __al_linux_set_display_switch_mode (int mode) { /* Clean up after the previous mode, if necessary */ if (switch_mode == SWITCH_NONE) __al_linux_switching_blocked--; switch_mode = mode; /* Initialise the new mode */ if (switch_mode == SWITCH_NONE) __al_linux_switching_blocked++; return 0; } /* go_away: * Performs a switch away. */ static void go_away(void) { _switch_out(); _unix_bg_man->disable_interrupts(); if ((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA)) if (timer_driver) timer_driver->exit(); /* Disable input devices while we're away */ __al_linux_suspend_standard_drivers(); _save_switch_state(switch_mode); if (gfx_driver && gfx_driver->save_video_state) gfx_driver->save_video_state(); ioctl (__al_linux_console_fd, VT_RELDISP, 1); console_active = 0; __al_linux_switching_blocked--; if ((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA)) { __al_linux_wait_for_display(); if (timer_driver) timer_driver->init(); } _unix_bg_man->enable_interrupts(); } /* come_back: * Performs a switch back. */ static void come_back(void) { _unix_bg_man->disable_interrupts(); if (gfx_driver && gfx_driver->restore_video_state) gfx_driver->restore_video_state(); _restore_switch_state(); ioctl(__al_linux_console_fd, VT_RELDISP, VT_ACKACQ); console_active = 1; __al_linux_resume_standard_drivers(); _unix_bg_man->enable_interrupts(); _switch_in(); __al_linux_switching_blocked--; } /* poll_console_switch: * Checks whether a switch is needed and not blocked; if so, * makes the switch. */ static void poll_console_switch (void) { if (console_active == console_should_be_active) return; if (__al_linux_switching_blocked) return; __al_linux_switching_blocked++; if (console_should_be_active) come_back(); else go_away(); } /* vt_switch_requested: * This is our signal handler; it gets called whenever a switch is * requested, because either SIGRELVT or SIGACQVT is raised. */ static RETSIGTYPE vt_switch_requested(int signo) { switch (signo) { case SIGRELVT: console_should_be_active = 0; break; case SIGACQVT: console_should_be_active = 1; break; default: return; } poll_console_switch(); } /* __al_linux_acquire_bitmap: * Increases the switching_blocked counter to block switches during * critical code (e.g. code accessing unsaved graphics controller * registers; or in background mode, code that does anything at all * connected with the screen bitmap). */ void __al_linux_acquire_bitmap(BITMAP *bmp) { ASSERT(bmp); __al_linux_switching_blocked++; } /* __al_linux_release_bitmap: * Decreases the blocking count and polls for switching. */ void __al_linux_release_bitmap(BITMAP *bmp) { ASSERT(bmp); __al_linux_switching_blocked--; poll_console_switch(); } /* __al_linux_display_switch_lock: * System driver routine for locking the display around crucial bits of * code, for example when changing video modes. */ void __al_linux_display_switch_lock(int lock, int foreground) { if (__al_linux_console_fd == -1) { return; } if (foreground) { __al_linux_wait_for_display(); } if (lock) { __al_linux_switching_blocked++; } else { __al_linux_switching_blocked--; poll_console_switch(); } } /* __al_linux_init_vtswitch: * Takes control over our console. It means we'll be notified when user * switches to and from the graphics console. */ int __al_linux_init_vtswitch(void) { struct sigaction sa; struct vt_mode vtm; if (vtswitch_initialised) return 0; /* shouldn't happen */ __al_linux_switching_blocked = (switch_mode == SWITCH_NONE) ? 1 : 0; console_active = console_should_be_active = 1; /* Hook the signals */ sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGIO); /* block async IO during the VT switch */ sa.sa_flags = 0; sa.sa_handler = vt_switch_requested; if ((sigaction(SIGRELVT, &sa, NULL) < 0) || (sigaction(SIGACQVT, &sa, NULL) < 0)) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to control VT switching")); return 1; } /* Save old mode, take control, and arrange for the signals * to be raised. */ ioctl(__al_linux_console_fd, VT_GETMODE, &startup_vtmode); vtm = startup_vtmode; vtm.mode = VT_PROCESS; vtm.relsig = SIGRELVT; vtm.acqsig = SIGACQVT; ioctl(__al_linux_console_fd, VT_SETMODE, &vtm); vtswitch_initialised = 1; return 0; } /* __al_linux_done_vtswitch: * Undoes the effect of `init_vtswitch'. */ int __al_linux_done_vtswitch(void) { struct sigaction sa; if (!vtswitch_initialised) return 0; /* shouldn't really happen either */ /* !trout gfoot. Must turn off the signals before unhooking them... */ ioctl(__al_linux_console_fd, VT_SETMODE, &startup_vtmode); sigemptyset (&sa.sa_mask); sa.sa_handler = SIG_DFL; sa.sa_flags = SA_RESTART; sigaction (SIGRELVT, &sa, NULL); sigaction (SIGACQVT, &sa, NULL); vtswitch_initialised = 0; return 0; } allegro-4.4.3.1/src/linux/lmsegpmd.c0000664000175000017500000000750013437077643016204 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console internal mouse driver for `gpmdata' repeater. * * By George Foot. * * See readme.txt for copyright information. */ #include #include #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #define ASCII_NAME "GPM repeater" #define DEVICE_FILENAME "/dev/gpmdata" /* processor: * Processes the first packet in the buffer, if any, returning the number * of bytes eaten. * * The GPM repeater uses Mouse Systems protocol. Packets contain five * bytes. The low bits of the first byte represent the button state. * The following bytes represent motion left, up, right and down * respectively. I think. * * We recognise the start of a packet by looking for a byte with the top * bit set and the next four bits not set -- while this can occur in the * data bytes, it's pretty unlikely. */ static int processor (unsigned char *buf, int buf_size) { int r, m, l, x, y, z; if (buf_size < 5) return 0; /* not enough data, spit it out for now */ if ((buf[0] & 0xf8) != 0x80) return 1; /* invalid byte, eat it */ /* packet is valid, process the data */ r = !(buf[0] & 1); m = !(buf[0] & 2); l = !(buf[0] & 4); x = (signed char)buf[1] + (signed char)buf[3]; y = (signed char)buf[2] + (signed char)buf[4]; z = 0; __al_linux_mouse_handler(x, y, z, l+(r<<1)+(m<<2)); return 5; /* yum */ } static INTERNAL_MOUSE_DRIVER intdrv = { -1, processor, 3 }; /* sync_mouse: * To find the start of a packet, we just read all the data that's * waiting. This isn't a particularly good way, obviously. :) */ static void sync_mouse (int fd) { fd_set set; int result; struct timeval tv; char bitbucket; do { FD_ZERO (&set); FD_SET (fd, &set); tv.tv_sec = tv.tv_usec = 0; result = select (FD_SETSIZE, &set, NULL, NULL, &tv); if (result > 0) read (fd, &bitbucket, 1); } while (result > 0); } /* mouse_init: * Here we open the mouse device, initialise anything that needs it, * and chain to the framework init routine. */ static int mouse_init (void) { char tmp1[128], tmp2[128], tmp3[128]; AL_CONST char *udevice; /* Find the device filename */ udevice = get_config_string (uconvert_ascii ("mouse", tmp1), uconvert_ascii ("mouse_device", tmp2), uconvert_ascii (DEVICE_FILENAME, tmp3)); /* Open mouse device. Devices are cool. */ intdrv.device = open (uconvert_toascii (udevice, tmp1), O_RDONLY | O_NONBLOCK); if (intdrv.device < 0) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to open %s: %s"), udevice, ustrerror (errno)); return -1; } /* Discard any garbage, so the next thing we read is a packet header */ sync_mouse (intdrv.device); return __al_linux_mouse_init (&intdrv); } /* mouse_exit: * Chain to the framework, then uninitialise things. */ static void mouse_exit (void) { __al_linux_mouse_exit(); close (intdrv.device); } MOUSE_DRIVER mousedrv_linux_gpmdata = { MOUSEDRV_LINUX_GPMDATA, empty_string, empty_string, ASCII_NAME, mouse_init, mouse_exit, NULL, /* poll() */ NULL, /* timer_poll() */ __al_linux_mouse_position, __al_linux_mouse_set_range, __al_linux_mouse_set_speed, __al_linux_mouse_get_mickeys, NULL, /* analyse_data */ NULL, NULL }; allegro-4.4.3.1/src/linux/svgalib.c0000664000175000017500000004006313437077643016024 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video driver using SVGAlib. * * By Stefan T. Boettner. * * Modified extensively by Peter Wang. * * Horizontal scrolling fixed by Attila Szilagyi. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #if (defined ALLEGRO_LINUX_SVGALIB) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include #include #include #include #include #include static BITMAP *svga_init(int w, int h, int v_w, int v_h, int color_depth); static void svga_exit(BITMAP *b); static int svga_scroll(int x, int y); static void svga_vsync(void); static void svga_set_palette(AL_CONST RGB *p, int from, int to, int vsync); static void svga_save(void); static void svga_restore(void); /* static GFX_MODE_LIST *svga_fetch_mode_list(void); */ #ifndef ALLEGRO_NO_ASM unsigned long _svgalib_read_line_asm(BITMAP *bmp, int line); unsigned long _svgalib_write_line_asm(BITMAP *bmp, int line); void _svgalib_unwrite_line_asm(BITMAP *bmp); #endif GFX_DRIVER gfx_svgalib = { GFX_SVGALIB, empty_string, empty_string, "SVGAlib", svga_init, svga_exit, svga_scroll, svga_vsync, svga_set_palette, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ svga_save, svga_restore, NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ NULL, /* svga_fetch_mode_list disabled */ 0, 0, TRUE, 0, 0, 0, 0, FALSE }; static char svga_desc[256] = EMPTY_STRING; static int svga_mode; static unsigned int bytes_per_line; static unsigned int display_start_mask; static unsigned char *screen_buffer; static int last_line; static int saved_palette[PAL_SIZE * 3]; #ifdef ALLEGRO_MODULE int _module_has_registered_via_atexit = 0; #endif /* _svgalib_read_line: * Return linear offset for reading line. */ unsigned long _svgalib_read_line(BITMAP *bmp, int line) { ASSERT(bmp); ASSERT(line>=0 && lineh); return (unsigned long) (bmp->line[line]); } /* _svgalib_write_line: * Update last selected line and select new line. */ unsigned long _svgalib_write_line(BITMAP *bmp, int line) { int new_line; ASSERT(bmp); ASSERT(line>=0 && lineh); new_line = line + bmp->y_ofs; if ((new_line != last_line) && (last_line >= 0)) vga_drawscansegment(screen_buffer + last_line * bytes_per_line, 0, last_line, bytes_per_line); last_line = new_line; return (unsigned long) (bmp->line[line]); } /* _svgalib_unwrite_line: * Update last selected line. */ void _svgalib_unwrite_line(BITMAP *bmp) { ASSERT(bmp); if (last_line >= 0) { vga_drawscanline(last_line, screen_buffer + last_line * bytes_per_line); last_line = -1; } } /* save_signals, restore_signals: * Helpers to save and restore signals captured by SVGAlib. */ static const int signals[] = { SIGUSR1, SIGUSR2, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPWR }; #define NUM_SIGNALS (sizeof (signals) / sizeof (int)) static struct sigaction old_signals[NUM_SIGNALS]; static void save_signals(void) { int i; for (i = 0; i < (int)NUM_SIGNALS; i++) sigaction(signals[i], NULL, old_signals+i); } static void restore_signals(void) { int i; for (i = 0; i < (int)NUM_SIGNALS; i++) sigaction(signals[i], old_signals+i, NULL); } /* safe_vga_setmode: * We don't want SVGAlib messing with our keyboard driver or taking * over control of VT switching. Note that doing all this every * time is possibly a little excessive. */ static int safe_vga_setmode(int num, int tio) { struct termios termio; struct vt_mode vtm; int ret; save_signals(); if (tio) ioctl(__al_linux_console_fd, VT_GETMODE, &vtm); tcgetattr(__al_linux_console_fd, &termio); ret = vga_setmode(num); #ifdef ALLEGRO_MODULE /* A side-effect of vga_setmode() is that it will register an * atexit handler. See umodules.c for this problem. */ _module_has_registered_via_atexit = 1; #endif tcsetattr(__al_linux_console_fd, TCSANOW, &termio); if (tio) ioctl(__al_linux_console_fd, VT_SETMODE, &vtm); restore_signals(); return ret; } /* get_depth: * SVGAlib speaks in number of colors and bytes per pixel. * Allegro speaks in color depths. */ static int get_depth(int ncolors, int bytesperpixel) { if (ncolors == 256) return 8; if (ncolors == 32768) return 15; if (ncolors == 65536) return 16; if (bytesperpixel == 3) return 24; if (bytesperpixel == 4) return 32; return -1; } /* mode_ok: * Check if the mode passed matches the size and color depth requirements. */ static int mode_ok(vga_modeinfo *info, int w, int h, int v_w, int v_h, int color_depth) { ASSERT(info); return ((color_depth == get_depth(info->colors, info->bytesperpixel)) && (((info->width == w) && (info->height == h)) || ((w == 0) && (h == 0))) && (info->maxlogicalwidth >= (MAX(w, v_w) * info->bytesperpixel)) && (info->maxpixels >= (MAX(w, v_w) * MAX(h, v_h)))); } /* find_and_set_mode: * Helper to find a suitable video mode and then set it. */ static vga_modeinfo *find_and_set_mode(int w, int h, int v_w, int v_h, int color_depth, int flags) { vga_modeinfo *info; int i; for (i = 0; i <= vga_lastmodenumber(); i++) { if (!vga_hasmode(i)) continue; info = vga_getmodeinfo(i); if ((info->flags & IS_MODEX) || ((flags) && !(info->flags & flags)) || (!mode_ok(info, w, h, v_w, v_h, color_depth))) continue; if (safe_vga_setmode(i, 1) == 0) { svga_mode = i; gfx_svgalib.w = vga_getxdim(); gfx_svgalib.h = vga_getydim(); return info; } } return NULL; } /* set_color_shifts: * Set the color shift values for truecolor modes. */ static void set_color_shifts(int color_depth, int bgr) { switch (color_depth) { #ifdef ALLEGRO_COLOR16 case 15: _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; break; case 16: _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; break; #endif #ifdef ALLEGRO_COLOR24 case 24: if (bgr) { _rgb_r_shift_24 = 0; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 16; } else { _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; } break; #endif #ifdef ALLEGRO_COLOR32 case 32: if (bgr) { _rgb_a_shift_32 = 0; _rgb_r_shift_32 = 8; _rgb_g_shift_32 = 16; _rgb_b_shift_32 = 24; } else { _rgb_a_shift_32 = 24; _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; } break; #endif } } /* do_set_mode: * Do the hard work of setting a video mode, then return a screen bitmap. */ static BITMAP *do_set_mode(int w, int h, int v_w, int v_h, int color_depth) { int vid_mem, width, height; vga_modeinfo *info; BITMAP *bmp; char tmp[128]; /* Try get a linear frame buffer. */ info = find_and_set_mode(w, h, v_w, v_h, color_depth, CAPABLE_LINEAR); if (info) { vid_mem = vga_setlinearaddressing(); if (vid_mem < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot enable linear addressing")); return NULL; } if ((v_w != 0) && (w != v_w)) { if ((v_w < w) || ((v_w * info->bytesperpixel) % ((info->flags & EXT_INFO_AVAILABLE) ? info->linewidth_unit : 8))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid virtual resolution requested")); return NULL; } bytes_per_line = v_w * info->bytesperpixel; vga_setlogicalwidth(bytes_per_line); } else { bytes_per_line = info->linewidth; } width = bytes_per_line / info->bytesperpixel; height = info->maxpixels / width; /* Set entries in gfx_svgalib. */ gfx_svgalib.vid_mem = vid_mem; gfx_svgalib.scroll = svga_scroll; ustrzcpy(svga_desc, sizeof(svga_desc), uconvert_ascii("SVGAlib (linear)", tmp)); gfx_svgalib.desc = svga_desc; /* For hardware scrolling. */ display_start_mask = info->startaddressrange; /* Set truecolor format. */ set_color_shifts(color_depth, (info->flags & RGB_MISORDERED)); /* Make the screen bitmap. */ return _make_bitmap(width, height, (unsigned long)vga_getgraphmem(), &gfx_svgalib, color_depth, bytes_per_line); } /* Try get a banked frame buffer. */ /* We don't support virtual screens larger than the screen itself * in banked mode. */ if ((v_w > w) || (v_h > h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } info = find_and_set_mode(w, h, v_w, v_h, color_depth, 0); if (info) { width = gfx_svgalib.w; height = gfx_svgalib.h; bytes_per_line = width * info->bytesperpixel; vid_mem = bytes_per_line * height; /* Allocate memory buffer for screen. */ screen_buffer = _AL_MALLOC_ATOMIC(vid_mem); if (!screen_buffer) return NULL; last_line = -1; /* Set entries in gfx_svgalib. */ gfx_svgalib.vid_mem = vid_mem; gfx_svgalib.scroll = NULL; ustrzcpy(svga_desc, sizeof(svga_desc), uconvert_ascii("SVGAlib (banked)", tmp)); gfx_svgalib.desc = svga_desc; /* Set truecolor format. */ set_color_shifts(color_depth, 0); /* Make the screen bitmap. */ bmp = _make_bitmap(width, height, (unsigned long)screen_buffer, &gfx_svgalib, color_depth, bytes_per_line); if (bmp) { /* Set bank switching routines. */ #ifndef ALLEGRO_NO_ASM bmp->read_bank = _svgalib_read_line_asm; bmp->write_bank = _svgalib_write_line_asm; bmp->vtable->unwrite_bank = _svgalib_unwrite_line_asm; #else bmp->read_bank = _svgalib_read_line; bmp->write_bank = _svgalib_write_line; bmp->vtable->unwrite_bank = _svgalib_unwrite_line; #endif } return bmp; } ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } /* svga_version2: * Returns non-zero if we have SVGAlib version 2 (or the prereleases). */ static int svga_version2(void) { #ifdef ALLEGRO_LINUX_SVGALIB_HAVE_VGA_VERSION return vga_version >= 0x1900; #else return 0; #endif } /* svga_init: * Entry point to set a video mode. */ static BITMAP *svga_init(int w, int h, int v_w, int v_h, int color_depth) { static int virgin = 1; #ifndef ALLEGRO_HAVE_LIBPTHREAD /* SVGAlib and the SIGALRM code don't like each other, so only support * pthreads event processing. */ if (_unix_bg_man == &_bg_man_sigalrm) return NULL; #endif if ((!svga_version2()) && (!__al_linux_have_ioperms)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("This driver needs root privileges")); return NULL; } __al_linux_use_console(); /* Initialise SVGAlib. */ if (virgin) { if (!svga_version2()) seteuid(0); else { /* I don't remember why I put this code in eight years ago (!) and the * log message wasn't very good :-P My guess is that a previous * version of SVGAlib 1.9.x would call exit() if the /dev/svga device * wasn't present. However, as far as I know, the svgalib_helper * doesn't compile with recent kernels so the device won't exist. --pw */ #if 0 /* Avoid having SVGAlib calling exit() on us. */ int fd = open("/dev/svga", O_RDWR); if (fd < 0) return NULL; close(fd); #endif } vga_disabledriverreport(); if (vga_init() != 0) return NULL; if (!svga_version2()) seteuid(getuid()); virgin = 0; } /* Ask for a video mode. */ return do_set_mode(w, h, v_w, v_h, color_depth); } /* svga_exit: * Unsets the video mode. */ static void svga_exit(BITMAP *b) { if (screen_buffer) { _AL_FREE(screen_buffer); screen_buffer = NULL; } safe_vga_setmode(TEXT, 1); __al_linux_leave_console(); } /* svga_scroll: * Hardware scrolling routine. */ static int svga_scroll(int x, int y) { vga_setdisplaystart((x + y * bytes_per_line) /* & display_start_mask */); /* The bitmask seems to mess things up on my machine, even though * the documentation says it should be there. -- PW */ /* wait for a retrace */ if (_wait_for_vsync) vga_waitretrace(); return 0; } /* svga_vsync: * Waits for a retrace. */ static void svga_vsync(void) { vga_waitretrace(); } /* svga_set_palette: * Sets the palette. */ static void svga_set_palette(AL_CONST RGB *p, int from, int to, int vsync) { int i; ASSERT(p); ASSERT(from>=0 && from<=255); ASSERT(to>=0 && to<=255); ASSERT(from<=to); if (vsync) vga_waitretrace(); for (i = from; i <= to; i++) vga_setpalette(i, p[i].r, p[i].g, p[i].b); } /* svga_save: * Saves the graphics state. */ static void svga_save(void) { vga_getpalvec(0, PAL_SIZE, saved_palette); safe_vga_setmode(TEXT, 0); } /* svga_restore: * Restores the graphics state. */ static void svga_restore(void) { safe_vga_setmode(svga_mode, 0); vga_setpage(0); vga_setpalvec(0, PAL_SIZE, saved_palette); } /* svga_fetch_mode_list: * Generates a list of valid video modes. * Returns the mode list on success or NULL on failure. * * Disabled because it causes problems if called when other graphics * drivers are being used. (It starts up SVGAlib, which then does * stuff with the console.) */ #if 0 static GFX_MODE_LIST *svga_fetch_mode_list(void) { GFX_MODE_LIST *mode_list; vga_modeinfo *info; int i, count, bpp; if ((!svga_version2()) && (!__al_linux_have_ioperms)) return NULL; for (i = 0, count = 0; i <= vga_lastmodenumber(); i++) { if (vga_hasmode(i)) { info = vga_getmodeinfo(i); if (!(info->flags & IS_MODEX)) count++; } } mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) return NULL; mode_list->mode = _AL_MALLOC(sizeof(GFX_MODE) * (count + 1)); if (!mode_list->mode) { _AL_FREE(mode_list); return NULL; } for (i = 0, count = 0; i <= vga_lastmodenumber(); i++) { if (!vga_hasmode(i)) continue; info = vga_getmodeinfo(i); if (info->flags & IS_MODEX) continue; bpp = get_depth(info->colors, info->bytesperpixel); if (bpp < 0) continue; mode_list->mode[count].width = info->width; mode_list->mode[count].height = info->height; mode_list->mode[count].bpp = bpp; count++; } mode_list->mode[count].width = 0; mode_list->mode[count].height = 0; mode_list->mode[count].bpp = 0; mode_list->num_modes = count; return mode_list; } #endif #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { if (system_driver == SYSTEM_LINUX) _unix_register_gfx_driver(GFX_SVGALIB, &gfx_svgalib, TRUE, FALSE); } #endif /* ifdef ALLEGRO_MODULE */ #endif /* if (defined ALLEGRO_LINUX_SVGALIB) ... */ allegro-4.4.3.1/src/linux/svgalibs.s0000664000175000017500000000300613437077643016223 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * SVGAlib bank switching code. These routines will be called * with a line number in %eax and a pointer to the bitmap in %edx. * The bank switcher should select the appropriate bank for the * line, and replace %eax with a pointer to the start of the line. * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro/platform/alunixac.h" #include "../i386/asmdefs.inc" .text #if (!defined ALLEGRO_NO_ASM) && (defined ALLEGRO_LINUX_SVGALIB) #if (!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE) FUNC(_svgalib_read_line_asm) pushl %ecx pushl %eax pushl %edx call GLOBL(_svgalib_read_line) popl %edx popl %ecx /* preserve %eax */ popl %ecx ret FUNC(_svgalib_write_line_asm) pushl %ecx pushl %eax pushl %edx call GLOBL(_svgalib_write_line) popl %edx popl %ecx /* preserve %eax */ popl %ecx ret FUNC(_svgalib_unwrite_line_asm) pushl %ecx pushl %eax pushl %edx call GLOBL(_svgalib_unwrite_line) popl %edx popl %eax popl %ecx ret #endif #endif allegro-4.4.3.1/src/linux/lmemory.c0000664000175000017500000000457313437077643016067 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Memory mapping helpers for Linux Allegro. * * By George Foot, heavily based upon Marek Habersack's code. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #if !defined(_POSIX_MAPPED_FILES) || !defined(ALLEGRO_HAVE_MMAP) #error "Sorry, mapped files are required for Linux console Allegro to work!" #endif #include #include static int mem_fd = -1; /* fd of /dev/mem */ /* __al_linux_init_memory: * Prepares to be able to map memory; returns 0 on success. */ int __al_linux_init_memory (void) { mem_fd = open ("/dev/mem", O_RDWR); if (mem_fd < 0) return 1; mprotect ((void *)&mem_fd, sizeof mem_fd, PROT_READ); return 0; } /* __al_linux_shutdown_memory: * Turns off memory mapping, returning 0 on success. */ int __al_linux_shutdown_memory (void) { if (mem_fd < 0) return 1; mprotect ((void *)&mem_fd, sizeof mem_fd, PROT_READ | PROT_WRITE); close (mem_fd); mem_fd = -1; return 0; } /* __al_linux_map_memory: * Given a MAPPED_MEMORY struct with physical address, size and * permissions filled in, this function maps the memory and fills * in the pointer in the struct. Returns 0 on success; errno will * be set on error. */ int __al_linux_map_memory (struct MAPPED_MEMORY *info) { ASSERT(info); info->data = mmap (0, info->size, info->perms, MAP_SHARED, mem_fd, info->base); if (info->data == MAP_FAILED) { info->data = NULL; return 1; } return 0; } /* __al_linux_unmap_memory: * Given a MAPPED_MEMORY struct, this function unmaps * the block. Returns 0 on success, errno set on error. */ int __al_linux_unmap_memory (struct MAPPED_MEMORY *info) { ASSERT(info); if (info->data == NULL) return 0; if (!munmap (info->data, info->size)) { info->data = NULL; return 0; } return 1; } allegro-4.4.3.1/src/linux/lvgahelp.c0000664000175000017500000001624613437077643016205 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * VGA helper functions for Linux Allegro. * * Originally by Marek Habersack, mangled by George Foot. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "allegro.h" #ifdef ALLEGRO_LINUX_VGA #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "allegro/internal/aintvga.h" #include "linalleg.h" #include #include #include #include #include #include #include #include /* Used by the text font routines, to access the video memory */ static struct MAPPED_MEMORY vram = { VGA_MEMORY_BASE, VGA_MEMORY_SIZE, PROT_READ | PROT_WRITE, NULL }; int __al_linux_init_vga_helpers (void) { __al_linux_map_memory (&vram); _vga_regs_init(); return 0; } int __al_linux_shutdown_vga_helpers (void) { __al_linux_unmap_memory (&vram); return 0; } /* __al_linux_set_vga_regs: * Write the standard VGA registers using values from the passed structure. */ void __al_linux_set_vga_regs(MODE_REGISTERS *regs) { int i = 0; if (!regs) return; outportb(MISC_REG_W, regs->misc); outportw(SEQ_REG_I, 0x0100); for (i = 1; i < N_SEQ_REGS; i++) outportw(SEQ_REG_I, (regs->seq[i] << 8) | i); outportw(SEQ_REG_I, 0x0300); outportw(_crtc, ((_read_vga_register(_crtc, 0x11) & 0x7F) << 8) | 0x11); for (i = 0; i < N_CRTC_REGS; i++) outportw(_crtc, (regs->crt[i] << 8) | i); for (i = 0; i < N_GC_REGS; i++) outportw(GC_REG_I, (regs->gc[i] << 8) | i); for (i = 0; i < N_ATC_REGS; i++) { inportb(_is1); outportb(ATC_REG_IW, i); outportb(ATC_REG_IW, regs->atc[i]); __just_a_moment(); } } /* __al_linux_get_vga_regs: * Read and save in the passed array all standard VGA regs for the current * video mode. */ void __al_linux_get_vga_regs(MODE_REGISTERS *regs) { int i = 0; if (!regs) return; regs->misc = inportb(MISC_REG_R); for (i = 0; i < N_CRTC_REGS; i++) { outportb(_crtc, i); regs->crt[i] = inportb(_crtc+1); } for (i = 0; i < N_GC_REGS; i++) { outportb(GC_REG_I, i); regs->gc[i] = inportb(GC_REG_RW); } for (i = 0; i < N_SEQ_REGS; i++) { outportb(SEQ_REG_I, i); regs->seq[i] = inportb(SEQ_REG_RW); } for (i = 0; i < N_ATC_REGS; i++) { inportb(_is1); outportb(ATC_REG_IW, i); regs->atc[i] = inportb(ATC_REG_R); __just_a_moment(); } } static void __al_linux_save_palette (MODE_REGISTERS *regs) { int c; unsigned char *ptr; ASSERT(regs); ptr = regs->palette.vga; for (c = 0; c < 256; c++) { outportb (0x3c7, c); *ptr++ = inportb (0x3c9); *ptr++ = inportb (0x3c9); *ptr++ = inportb (0x3c9); } } static void __al_linux_restore_palette (MODE_REGISTERS *regs) { int c; unsigned char *ptr; ASSERT(regs); ptr = regs->palette.vga; for (c = 0; c < 256; c++) { outportb (0x3c8, c); outportb (0x3c9, *ptr++); outportb (0x3c9, *ptr++); outportb (0x3c9, *ptr++); } } static inline void slow_byte_copy(char *from, char *to, unsigned count) { unsigned int i; ASSERT(from && to); for (i = 0; i < count; i++) { *to++ = *from++; outportb(0x80, 0x00); /* 1ms delay */ } } /* __al_linux_save_text_font: * Copy the text font data from the video memory. Since some cards won't work * properly unless we save/restore fonts from both 2nd and 3rd plane, we save * them both. */ static void __al_linux_save_text_font (MODE_REGISTERS *regs) { ASSERT(regs); if (!regs->text_font1) regs->text_font1 = (unsigned char*) _AL_MALLOC (VGA_FONT_SIZE); if (!regs->text_font2) regs->text_font2 = (unsigned char*) _AL_MALLOC (VGA_FONT_SIZE); /* First switch to a 4bpp video mode, so that we have selective * access to video memory planes. Do it with host palette * access disabled. */ inportb(_is1); outportb(ATC_REG_IW, 0x30); outportb(ATC_REG_IW, 0x01); /* Put ATC into graphics mode */ outportw(SEQ_REG_I, 0x0604); /* Planar mode */ outportw(GC_REG_I, 0x0005); /* Write Mode == Read Mode == 0 */ outportw(GC_REG_I, 0x0506); /* Switch GC to graphics mode and start VGA * memory at 0xA0000 (64KB) */ /* Now we're ready to read the first font. We'll do it using the slowest * copy routine possible. It is to account for the old VGA boards which may * lose data during too fast reads/writes. */ outportw(GC_REG_I, 0x0204); /* Reading from plane 2 */ slow_byte_copy ((char*)vram.data, (char*)regs->text_font1, VGA_FONT_SIZE); outportw(GC_REG_I, 0x0304); /* Reading from plane 3 */ slow_byte_copy ((char*)vram.data, (char*)regs->text_font2, VGA_FONT_SIZE); } /* __al_linux_restore_text_font: * Copy the saved font data back to video memory. */ static void __al_linux_restore_text_font(MODE_REGISTERS *regs) { ASSERT(regs); /* Same as in the previous routing. We're restoring the font in a * 4bpp mode to have access to separate memory planes. */ inportb(_is1); outportb(ATC_REG_IW, 0x30); outportb(ATC_REG_IW, 0x01); /* Put ATC into graphics mode */ outportw(SEQ_REG_I, 0x0604); /* Planar mode */ outportw(GC_REG_I, 0x0005); /* Write Mode == Read Mode == 0 */ outportw(GC_REG_I, 0x0506); /* Switch GC to graphics mode and start VGA * memory at 0xA0000 (64KB) */ outportw(GC_REG_I, 0x0001); if (regs->text_font1) { outportw(SEQ_REG_I, 0x0402); slow_byte_copy((char*)regs->text_font1, (char*)vram.data, VGA_FONT_SIZE); } if (regs->text_font2) { outportw(SEQ_REG_I, 0x0802); slow_byte_copy((char*)regs->text_font2, (char*)vram.data, VGA_FONT_SIZE); } } void __al_linux_screen_off(void) { _write_vga_register(SEQ_REG_I, 0x01, _read_vga_register(SEQ_REG_I, 0x01) | 0x20); inportb(_is1); __just_a_moment(); outportb(ATC_REG_IW, 0x00); __just_a_moment(); } void __al_linux_screen_on(void) { _write_vga_register(SEQ_REG_I, 0x01, _read_vga_register(SEQ_REG_I, 0x01) & 0xDF); inportb(_is1); __just_a_moment(); outportb(ATC_REG_IW, 0x20); __just_a_moment(); } void __al_linux_clear_vram (void) { memset (vram.data, 0, vram.size); } static MODE_REGISTERS txt_regs; void __al_linux_save_text_mode (void) { __al_linux_get_vga_regs (&txt_regs); __al_linux_save_palette (&txt_regs); __al_linux_save_text_font (&txt_regs); } void __al_linux_restore_text_mode (void) { __al_linux_restore_text_font (&txt_regs); __al_linux_restore_palette (&txt_regs); __al_linux_set_vga_regs (&txt_regs); } #endif /* ALLEGRO_LINUX_VGA */ allegro-4.4.3.1/src/linux/lgfxdrv.c0000664000175000017500000000233313437077643016047 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console video driver list. * * By George Foot. * * See readme.txt for copyright information. */ #include "allegro.h" /* list the available drivers */ _DRIVER_INFO _linux_gfx_driver_list[] = { #if (defined ALLEGRO_LINUX_FBCON) && (!defined ALLEGRO_WITH_MODULES) { GFX_FBCON, &gfx_fbcon, TRUE }, #endif #ifdef ALLEGRO_LINUX_VBEAF { GFX_VBEAF, &gfx_vbeaf, TRUE }, #endif #if (defined ALLEGRO_LINUX_VGA) && (!defined ALLEGRO_WITH_MODULES) { GFX_VGA, &gfx_vga, TRUE }, /* { GFX_MODEX, &gfx_modex, TRUE }, */ #endif #if (defined ALLEGRO_LINUX_SVGALIB) && (!defined ALLEGRO_WITH_MODULES) { GFX_SVGALIB, &gfx_svgalib, FALSE }, #endif { 0, NULL, 0 } }; allegro-4.4.3.1/src/linux/lsystem.c0000664000175000017500000001520413437077643016074 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console system driver. * * By George Foot. * * See readme.txt for copyright information. */ #include #include #include #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "allegro/platform/aintlnx.h" #ifdef ALLEGRO_LINUX_VGA #ifdef ALLEGRO_HAVE_SYS_IO_H /* iopl() exists in here instead of unistd.h in glibc */ #include #endif #endif #include "linalleg.h" #ifndef ALLEGRO_LINUX #error Something is wrong with the makefile #endif static int sys_linux_init(void); static void sys_linux_exit(void); static void sys_linux_message (AL_CONST char *msg); /* driver list getters */ #define make_getter(x,y) static _DRIVER_INFO *get_##y##_driver_list (void) { return x##_##y##_driver_list; } make_getter (_unix, gfx) make_getter (_unix, digi) make_getter (_unix, midi) make_getter (_linux, keyboard) make_getter (_linux, mouse) make_getter (_linux, timer) make_getter (_linux, joystick) #undef make_getter /* the main system driver for running on the Linux console */ SYSTEM_DRIVER system_linux = { SYSTEM_LINUX, empty_string, empty_string, "Linux console", sys_linux_init, sys_linux_exit, _unix_get_executable_name, _unix_find_resource, NULL, /* set_window_title */ NULL, /* set_close_button_callback */ sys_linux_message, NULL, /* assert */ NULL, NULL, NULL, /* create_bitmap */ NULL, /* created_bitmap */ NULL, /* create_sub_bitmap */ NULL, /* created_sub_bitmap */ NULL, /* destroy_bitmap */ NULL, /* read_hardware_palette */ NULL, /* set_palette_range */ NULL, /* get_vtable */ __al_linux_set_display_switch_mode, __al_linux_display_switch_lock, #if (defined ALLEGRO_LINUX_FBCON) && (!defined ALLEGRO_WITH_MODULES) __al_linux_get_fb_color_depth, __al_linux_get_fb_resolution, #else NULL, /* desktop_color_depth */ NULL, /* get_desktop_resolution */ #endif NULL, /* get_gfx_safe_mode */ _unix_yield_timeslice, #ifdef ALLEGRO_HAVE_LIBPTHREAD _unix_create_mutex, _unix_destroy_mutex, _unix_lock_mutex, _unix_unlock_mutex, #else NULL, /* create_mutex */ NULL, /* destroy_mutex */ NULL, /* lock_mutex */ NULL, /* unlock_mutex */ #endif get_gfx_driver_list, get_digi_driver_list, get_midi_driver_list, get_keyboard_driver_list, get_mouse_driver_list, get_joystick_driver_list, get_timer_driver_list }; int __al_linux_have_ioperms = 0; typedef RETSIGTYPE (*temp_sighandler_t)(int); static temp_sighandler_t old_sig_abrt, old_sig_fpe, old_sig_ill, old_sig_segv, old_sig_term, old_sig_int, old_sig_quit; /* signal_handler: * Used to trap various signals, to make sure things get shut down cleanly. */ static RETSIGTYPE signal_handler (int num) { allegro_exit(); fprintf (stderr, "Shutting down Allegro due to signal #%d\n", num); raise (num); } /* __al_linux_bgman_init: * Starts asynchronous processing. */ static int __al_linux_bgman_init (void) { #ifdef ALLEGRO_HAVE_LIBPTHREAD _unix_bg_man = &_bg_man_pthreads; #else _unix_bg_man = &_bg_man_sigalrm; #endif if (_unix_bg_man->init() || _unix_bg_man->register_func (__al_linux_update_standard_drivers)) return -1; return 0; } /* __al_linux_bgman_exit: * Stops asynchronous processing. */ static void __al_linux_bgman_exit (void) { _unix_bg_man->exit(); } /* sys_linux_init: * Top level system driver wakeup call. */ static int sys_linux_init (void) { /* Get OS type */ _unix_read_os_type(); if (os_type != OSTYPE_LINUX) return -1; /* FWIW */ /* This is the only bit that needs root privileges. First * we attempt to set our euid to 0, in case this is the * second time we've been called. */ __al_linux_have_ioperms = !seteuid (0); #ifdef ALLEGRO_LINUX_VGA __al_linux_have_ioperms &= !iopl (3); #endif __al_linux_have_ioperms &= !__al_linux_init_memory(); /* At this stage we can drop the root privileges. */ seteuid (getuid()); /* Initialise dynamic driver lists */ _unix_driver_lists_init(); if (_unix_gfx_driver_list) _driver_list_append_list(&_unix_gfx_driver_list, _linux_gfx_driver_list); /* Load dynamic modules */ _unix_load_modules(SYSTEM_LINUX); /* Initialise VGA helpers */ #ifdef ALLEGRO_LINUX_VGA if (__al_linux_have_ioperms) if (__al_linux_init_vga_helpers()) return -1; #endif /* Install emergency-exit signal handlers */ old_sig_abrt = signal(SIGABRT, signal_handler); old_sig_fpe = signal(SIGFPE, signal_handler); old_sig_ill = signal(SIGILL, signal_handler); old_sig_segv = signal(SIGSEGV, signal_handler); old_sig_term = signal(SIGTERM, signal_handler); old_sig_int = signal(SIGINT, signal_handler); #ifdef SIGQUIT old_sig_quit = signal(SIGQUIT, signal_handler); #endif /* Initialise async event processing */ if (__al_linux_bgman_init()) { /* shutdown everything. */ sys_linux_exit(); return -1; } return 0; } /* sys_linux_exit: * The end of the world... */ static void sys_linux_exit (void) { /* shut down asynchronous event processing */ __al_linux_bgman_exit(); /* remove emergency exit signal handlers */ signal(SIGABRT, old_sig_abrt); signal(SIGFPE, old_sig_fpe); signal(SIGILL, old_sig_ill); signal(SIGSEGV, old_sig_segv); signal(SIGTERM, old_sig_term); signal(SIGINT, old_sig_int); #ifdef SIGQUIT signal(SIGQUIT, old_sig_quit); #endif /* shut down VGA helpers */ #ifdef ALLEGRO_LINUX_VGA if (__al_linux_have_ioperms) __al_linux_shutdown_vga_helpers(); #endif /* unload dynamic modules */ _unix_unload_modules(); /* free dynamic driver lists */ _unix_driver_lists_shutdown(); __al_linux_shutdown_memory(); #ifdef ALLEGRO_LINUX_VGA iopl (0); #endif } /* sys_linux_message: * Display a message on our original console. */ static void sys_linux_message (AL_CONST char *msg) { char *tmp; int ret; ASSERT(msg); tmp = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE); msg = uconvert(msg, U_CURRENT, tmp, U_ASCII, ALLEGRO_MESSAGE_SIZE); do { ret = write(STDERR_FILENO, msg, strlen(msg)); if ((ret < 0) && (errno != EINTR)) break; } while (ret < (int)strlen(msg)); __al_linux_got_text_message = TRUE; _AL_FREE(tmp); } allegro-4.4.3.1/src/linux/tslib.c0000664000175000017500000001045613437077643015515 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console mouse driver for tslib (touch screens). * * By Tobi Vollebregt. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_LINUX_TSLIB #include #include #define PREFIX_I "al-tslib INFO: " #define PREFIX_W "al-tslib WARNING: " #define PREFIX_E "al-tslib ERROR: " #define ARRAY_SIZE(a) ((int)sizeof((a)) / (int)sizeof((a)[0])) static struct tsdev *ts; static int mouse_minx = 0; /* mouse range */ static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int al_tslib_error_callback(const char *fmt, va_list ap) { char tmp[ALLEGRO_ERROR_SIZE]; int ret; ret = vsnprintf(tmp, sizeof(tmp), fmt, ap); TRACE(PREFIX_E "%s\n", tmp); uconvert(tmp, U_ASCII, allegro_error, U_CURRENT, ALLEGRO_ERROR_SIZE); return ret; } static int mouse_init(void) { char tmp1[128], tmp2[128]; AL_CONST char *udevice; /* Set custom error handling function */ ts_error_fn = al_tslib_error_callback; /* Find the device filename */ udevice = get_config_string(uconvert_ascii("mouse", tmp1), uconvert_ascii("mouse_device", tmp2), NULL); /* Open mouse device. Devices are cool. */ if (udevice) { TRACE(PREFIX_I "Trying %s device\n", udevice); ts = ts_open(uconvert_toascii(udevice, tmp1), TRUE); if (ts == NULL) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to open %s: %s"), udevice, ustrerror(errno)); return -1; } } else { /* If not specified in the config file, try several /dev/input/event * devices. */ const char *device_name[] = { "/dev/input/event0", "/dev/input/event1", "/dev/input/event2", "/dev/input/event3", NULL }; int i; TRACE(PREFIX_I "Trying /dev/input/event[0-3] devices\n"); for (i=0; device_name[i]; i++) { ts = ts_open(device_name[i], TRUE); if (ts != NULL) break; } if (!device_name[i]) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to open a touch screen device: %s"), ustrerror(errno)); return -1; } } if (ts_config(ts)) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to configure touch screen device: %s"), ustrerror(errno)); ts_close(ts); return -1; } return 0; } static void mouse_exit(void) { if (ts) { ts_close(ts); ts = NULL; } } static void mouse_position(int x, int y) { _mouse_x = CLAMP(mouse_minx, x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, y, mouse_maxy); } static void mouse_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; mouse_position(_mouse_x, _mouse_y); } static void mouse_timer_poll(void) { struct ts_sample samp[16]; int n; n = ts_read(ts, samp, ARRAY_SIZE(samp)); if (n > 0) { --n; mouse_position(samp[n].x, samp[n].y); _mouse_b = samp[n].pressure > 0; /*TRACE(PREFIX_I "Read %d samples. x:%3d y:%3d pressure:%3d\n", n + 1, samp[n].x, samp[n].y, samp[n].pressure);*/ } } MOUSE_DRIVER mousedrv_linux_tslib = { MOUSEDRV_LINUX_TSLIB, empty_string, empty_string, "Linux tslib touch screen", mouse_init, mouse_exit, NULL, /* poll */ mouse_timer_poll, mouse_position, mouse_set_range, NULL, /* set_speed */ NULL, /* get_mickeys */ NULL, /* analyse_data */ NULL, /* enable_hardware_cursor */ NULL, /* select_system_cursor */ }; #endif allegro-4.4.3.1/src/linux/fbcon.c0000664000175000017500000007216613437077643015475 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video driver for the Linux framebuffer device. * * By Shawn Hargreaves. * * Proper mode setting support added by George Foot. * * Modified by Grzegorz Adam Hankiewicz. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #if (defined ALLEGRO_LINUX_FBCON) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #if !defined(_POSIX_MAPPED_FILES) || !defined(ALLEGRO_HAVE_MMAP) #error "Sorry, mapped files are required for Linux console Allegro to work!" #endif #include #include #include #include #include /* 2.4 kernel doesn't seem to have these, so assume that they don't * "have sticky," heheh. */ #ifndef FB_VBLANK_HAVE_STICKY #define FB_VBLANK_HAVE_STICKY 0 #endif #ifndef FB_VBLANK_STICKY #define FB_VBLANK_STICKY 0 #endif #define PREFIX_I "al-fbcon INFO: " #define PREFIX_W "al-fbcon WARNING: " #define PREFIX_E "al-fbcon ERROR: " static BITMAP *fb_init(int w, int h, int v_w, int v_h, int color_depth); static int fb_open_device(void); static void fb_exit(BITMAP *b); static void fb_save(void); static void fb_restore(void); static int fb_scroll(int x, int y); static void fb_vsync(void); static void fb_set_palette(AL_CONST RGB *p, int from, int to, int vsync); static void fb_save_cmap(void); static void fb_restore_cmap(void); GFX_DRIVER gfx_fbcon = { GFX_FBCON, empty_string, empty_string, "fbcon", fb_init, fb_exit, fb_scroll, fb_vsync, fb_set_palette, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ fb_save, fb_restore, NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, /* no fetch mode hook */ 0, 0, TRUE, 0, 0, 0, 0, FALSE }; static char fb_desc[256] = EMPTY_STRING; /* description string */ static int fb_mode_read = FALSE; /* has orig_mode been read? */ static struct fb_fix_screeninfo fix_info; /* read-only video mode info */ static struct fb_var_screeninfo orig_mode; /* original video mode info */ static struct fb_var_screeninfo my_mode; /* my video mode info */ static void *fbaddr; /* frame buffer address */ static int fbfd; /* file descriptor */ static int fb_approx; /* emulate small resolution */ #ifdef FBIOGET_VBLANK static int vblank_flags; /* supports retrace detection? */ #endif static int in_fb_restore; static int update_timings(struct fb_var_screeninfo *mode); static void set_ramp_cmap(AL_CONST struct fb_fix_screeninfo *fix, AL_CONST struct fb_var_screeninfo *var) { struct fb_cmap cmap; static unsigned short r[256], g[256], b[256]; /* 1.5 KB, so in .bss */ int rlen, glen, blen, rdiv, gdiv, bdiv; unsigned int c; ASSERT(fix); ASSERT(var); ASSERT(fix->visual == FB_VISUAL_DIRECTCOLOR); /* initialize what is common */ cmap.start = 0; cmap.red = r; cmap.green = g; cmap.blue = b; cmap.transp = NULL; /* from the mode's color depth information */ rlen = 1<red.length; glen = 1<green.length; blen = 1<blue.length; cmap.len = MAX(rlen, MAX(glen, blen)); ASSERT(cmap.len <= 256); if (cmap.len > 256) cmap.len = 256; /* are there cards with more than 8 bits per color ? */ rdiv = rlen<=1 ? 1 : rlen-1; gdiv = glen<=1 ? 1 : glen-1; bdiv = blen<=1 ? 1 : blen-1; /* the easy case (should not happen) */ if (cmap.len == 0) return; /* build the colormap */ for (c=0; cleft_margin+mode->xres+mode->left_margin+mode->hsync_len; v = mode->upper_margin+mode->yres+mode->lower_margin+mode->vsync_len; hz = (int)(0.5f+1.0e12f/((float)mode->pixclock*h*v)); _set_current_refresh_rate(hz); } /* __al_linux_get_fb_color_depth: * Get the colour depth of the framebuffer */ int __al_linux_get_fb_color_depth(void) { if ((!fb_mode_read) && (fb_open_device() != 0)) return 0; return orig_mode.bits_per_pixel; } /* __al_linux_get_fb_resolution: * Get the resolution of the framebuffer */ int __al_linux_get_fb_resolution(int *width, int *height) { if ((!fb_mode_read) && (fb_open_device() != 0)) return -1; *width = orig_mode.xres; *height = orig_mode.yres; return 0; } /* fb_init: * Sets a graphics mode. */ static BITMAP *fb_init(int w, int h, int v_w, int v_h, int color_depth) { AL_CONST char *p; int stride, tries, original_color_depth = _color_depth; BITMAP *b; char tmp[16]; /* open framebuffer and store info in global variables */ if ((!fb_mode_read) && (fb_open_device() != 0)) return NULL; /* look for a nice graphics mode in several passes */ fb_approx = FALSE; ASSERT (w >= 0); ASSERT (h >= 0); /* preset a resolution if the user didn't ask for one */ if (((!w) && (!h)) || _safe_gfx_mode_change) { w = orig_mode.xres; h = orig_mode.yres; TRACE(PREFIX_I "User didn't ask for a resolution, and we are trying " "to set a safe mode, so I will try resolution %dx%d\n", w, h); } if (_safe_gfx_mode_change) tries = -1; else tries = 0; if (__al_linux_console_graphics() != 0) { ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); close(fbfd); return NULL; } for (; tries<3; tries++) { TRACE(PREFIX_I "...try number %d...\n", tries); my_mode = orig_mode; switch (tries) { case -1: /* let's see if we can get the actual screen mode */ /* shouldn't we be keeping the previous color depth setting? */ switch (orig_mode.bits_per_pixel) { case 8: case 16: case 24: case 32: color_depth = orig_mode.bits_per_pixel; set_color_depth(color_depth); } break; case 0: /* try for largest possible virtual screen size */ my_mode.xres = w; my_mode.yres = h; my_mode.xres_virtual = MAX(w, v_w); my_mode.yres_virtual = MAX(MAX(h, v_h), (int)(fix_info.smem_len / (my_mode.xres_virtual * BYTES_PER_PIXEL(color_depth)))); break; case 1: /* try setting the exact size that was requested */ my_mode.xres = w; my_mode.yres = h; my_mode.xres_virtual = MAX(w, v_w); my_mode.yres_virtual = MAX(h, v_h); break; case 2: /* see if we can fake a smaller mode (better than nothing) */ if (((int)my_mode.xres < w) || ((int)my_mode.yres < h) || (v_w > w) || (v_h > h)) continue; fb_approx = TRUE; break; } my_mode.bits_per_pixel = color_depth; my_mode.grayscale = 0; my_mode.activate = FB_ACTIVATE_NOW; my_mode.xoffset = 0; my_mode.yoffset = 0; switch (color_depth) { #ifdef ALLEGRO_COLOR16 case 15: my_mode.red.offset = 10; my_mode.red.length = 5; my_mode.green.offset = 5; my_mode.green.length = 5; my_mode.blue.offset = 0; my_mode.blue.length = 5; break; case 16: my_mode.red.offset = 11; my_mode.red.length = 5; my_mode.green.offset = 5; my_mode.green.length = 6; my_mode.blue.offset = 0; my_mode.blue.length = 5; break; #endif #if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) case 24: case 32: my_mode.red.offset = 16; my_mode.red.length = 8; my_mode.green.offset = 8; my_mode.green.length = 8; my_mode.blue.offset = 0; my_mode.blue.length = 8; break; #endif case 8: default: my_mode.red.offset = 0; my_mode.red.length = 0; my_mode.green.offset = 0; my_mode.green.length = 0; my_mode.blue.offset = 0; my_mode.blue.length = 0; break; } my_mode.red.msb_right = 0; my_mode.green.msb_right = 0; my_mode.blue.msb_right = 0; /* fill in the timings */ if (update_timings(&my_mode) != 0) continue; /* try to set the mode */ if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &my_mode) == 0) { if (my_mode.bits_per_pixel == (unsigned)color_depth) goto got_a_nice_mode; } } /* oops! */ if (_safe_gfx_mode_change) { set_color_depth(original_color_depth); TRACE(PREFIX_I "Restoring color depth %d\n", original_color_depth); } ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); __al_linux_console_text(); close(fbfd); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Framebuffer resolution not available")); TRACE(PREFIX_E "Resolution %dx%d not available...\n", w, h); return NULL; got_a_nice_mode: /* get the fb_fix_screeninfo again, as it may have changed */ if (ioctl(fbfd, FBIOGET_FSCREENINFO, &fix_info) != 0) { ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); __al_linux_console_text(); close(fbfd); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Framebuffer ioctl() failed")); return NULL; } /* map the framebuffer */ fbaddr = mmap(NULL, fix_info.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if (fbaddr == MAP_FAILED) { ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); __al_linux_console_text(); close(fbfd); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't map framebuffer")); TRACE(PREFIX_E "Couldn't map framebuffer for %dx%d. Restored old " "resolution.\n", w, h); return NULL; } /* set up the screen bitmap */ gfx_fbcon.w = w; gfx_fbcon.h = h; gfx_fbcon.vid_mem = fix_info.smem_len; stride = fix_info.line_length; v_w = my_mode.xres_virtual; v_h = my_mode.yres_virtual; p = fbaddr; if (fb_approx) { v_w = w; v_h = h; p += (my_mode.xres-w)/2 * BYTES_PER_PIXEL(color_depth) + (my_mode.yres-h)/2 * stride; } b = _make_bitmap(v_w, v_h, (unsigned long)p, &gfx_fbcon, color_depth, stride); if (!b) { ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); munmap(fbaddr, fix_info.smem_len); __al_linux_console_text(); close(fbfd); TRACE(PREFIX_E "Couldn't make bitmap `b', sorry.\n"); return NULL; } b->vtable->acquire = __al_linux_acquire_bitmap; b->vtable->release = __al_linux_release_bitmap; do_uconvert(fix_info.id, U_ASCII, fb_desc, U_CURRENT, sizeof(fb_desc)); if (fb_approx) { ustrzcat(fb_desc, sizeof(fb_desc), uconvert_ascii(", ", tmp)); ustrzcat(fb_desc, sizeof(fb_desc), get_config_text("approx.")); } gfx_fbcon.desc = fb_desc; /* set up the truecolor pixel format */ switch (color_depth) { #ifdef ALLEGRO_COLOR16 case 15: _rgb_r_shift_15 = my_mode.red.offset; _rgb_g_shift_15 = my_mode.green.offset; _rgb_b_shift_15 = my_mode.blue.offset; break; case 16: _rgb_r_shift_16 = my_mode.red.offset; _rgb_g_shift_16 = my_mode.green.offset; _rgb_b_shift_16 = my_mode.blue.offset; break; #endif #ifdef ALLEGRO_COLOR24 case 24: _rgb_r_shift_24 = my_mode.red.offset; _rgb_g_shift_24 = my_mode.green.offset; _rgb_b_shift_24 = my_mode.blue.offset; break; #endif #ifdef ALLEGRO_COLOR32 case 32: _rgb_r_shift_32 = my_mode.red.offset; _rgb_g_shift_32 = my_mode.green.offset; _rgb_b_shift_32 = my_mode.blue.offset; break; #endif } /* is retrace detection available? */ #ifdef FBIOGET_VBLANK { struct fb_vblank vblank; if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) == 0) vblank_flags = vblank.flags; else vblank_flags = 0; } if (!(vblank_flags & (FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_STICKY | FB_VBLANK_HAVE_VCOUNT))) #endif { ustrzcat(fb_desc, sizeof(fb_desc), uconvert_ascii(", ", tmp)); ustrzcat(fb_desc, sizeof(fb_desc), get_config_text("no vsync")); } /* is scrolling available? */ if ((my_mode.xres_virtual > my_mode.xres) || (my_mode.yres_virtual > my_mode.yres)) { fb_scroll(0, 0); if ((fb_approx) || ((my_mode.xres_virtual > my_mode.xres) && (!fix_info.xpanstep)) || ((my_mode.yres_virtual > my_mode.yres) && (!fix_info.ypanstep))) gfx_fbcon.scroll = NULL; else gfx_fbcon.scroll = fb_scroll; } else gfx_fbcon.scroll = NULL; if (fb_approx) memset(fbaddr, 0, gfx_fbcon.vid_mem); fb_save_cmap(); /* Maybe we should fill in our default palette too... */ /* for directcolor modes, set up a ramp colormap, so colors are mapped onto themselves, so to speak */ if (fix_info.visual == FB_VISUAL_DIRECTCOLOR) set_ramp_cmap(&fix_info, &my_mode); calculate_refresh_rate(&my_mode); /* Note: Locked in __al_linux_console_graphics(). */ __al_linux_display_switch_lock(FALSE, FALSE); TRACE(PREFIX_I "Got a bitmap %dx%dx%d\n", b->w, b->h, bitmap_color_depth(b)); return b; } /* fb_open_device: * Opens the framebuffer device, first checking config values or * environment variables. Returns 0 on success. */ static int fb_open_device(void) { char fname[1024], tmp1[256], tmp2[256]; AL_CONST char *p; /* find the device filename */ p = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("framebuffer", tmp2), NULL); if (p && ugetc(p)) do_uconvert(p, U_CURRENT, fname, U_ASCII, sizeof(fname)); else { p = getenv("FRAMEBUFFER"); if ((p) && (p[0])) { _al_sane_strncpy(fname, p, sizeof(fname)); } else _al_sane_strncpy(fname, "/dev/fb0", 1024); } /* open the framebuffer device */ if ((fbfd = open(fname, O_RDWR)) < 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't open framebuffer %s"), uconvert_ascii(fname, tmp1)); TRACE(PREFIX_E "Couldn't open %s\n", fname); return 1; } /* read video mode information */ if ((ioctl(fbfd, FBIOGET_FSCREENINFO, &fix_info) != 0) || (ioctl(fbfd, FBIOGET_VSCREENINFO, &orig_mode) != 0)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Framebuffer ioctl() failed")); TRACE(PREFIX_E "ioctl() failed\n"); return 2; } TRACE(PREFIX_I "fb device %s opened successfully.\n", fname); fb_mode_read = TRUE; return 0; } /* fb_exit: * Unsets the video mode. */ static void fb_exit(BITMAP *b) { TRACE(PREFIX_I "Unsetting video mode.\n"); /* Note: Unlocked in __al_linux_console_text(). */ __al_linux_display_switch_lock(TRUE, TRUE); ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); fb_restore_cmap(); munmap(fbaddr, fix_info.smem_len); close(fbfd); __al_linux_console_text(); fb_mode_read = FALSE; } /* fb_save: * Saves the graphics state. */ static void fb_save(void) { ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_mode); } /* fb_restore: * Restores the graphics state. */ static void fb_restore(void) { ASSERT(!in_fb_restore); in_fb_restore = TRUE; ioctl(fbfd, FBIOPUT_VSCREENINFO, &my_mode); if (fb_approx) memset(fbaddr, 0, gfx_fbcon.vid_mem); if (fix_info.visual == FB_VISUAL_DIRECTCOLOR) set_ramp_cmap(&fix_info, &my_mode); in_fb_restore = FALSE; } /* fb_scroll: * Hardware scrolling routine. */ static int fb_scroll(int x, int y) { int ret; my_mode.xoffset = x; my_mode.yoffset = y; ret = ioctl(fbfd, FBIOPAN_DISPLAY, &my_mode); if (_wait_for_vsync) { /* On a lot of graphics hardware the scroll registers don't * take effect until the start of the next frame, so when you do a * scroll you want to make sure you've waited at least until then. * If you have reliable vsyncing, one call to vysnc is enough, * but if you don't then the first call waits some time between 0 * and 1/60th of a second, and since it's not really synced to the * retrace, this may or may not include an actual retrace. However, * by making a second call, we then wait for a full 1/60th of a second * after the first call, and this is sure to include a retrace, * assuming the refresh rate is at least 60Hz. Sometimes overall * we'll have waited past two retraces, or even more if the refresh * rate is much higher than the fake vblank timer frequency, but * it's still better than sometimes missing the retrace completely. */ fb_vsync(); #ifdef FBIOGET_VBLANK if (!vblank_flags) #endif fb_vsync(); } return (ret) ? -1 : 0; } /* fb_vsync: * Waits for a retrace. */ static void fb_vsync(void) { unsigned int prev; #ifdef FBIOGET_VBLANK struct fb_vblank vblank; if (vblank_flags & FB_VBLANK_HAVE_STICKY) { /* it's really good if sticky bits are available */ if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) != 0) return; do { if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) != 0) break; } while (!(vblank.flags & FB_VBLANK_STICKY)); } else if (vblank_flags & FB_VBLANK_HAVE_VCOUNT) { /* we can read the exact scanline position, which avoids skipping */ if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) != 0) return; do { prev = vblank.vcount; if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) != 0) break; } while (vblank.vcount >= prev); } else if (vblank_flags & FB_VBLANK_HAVE_VBLANK) { /* boring, normal style poll operation */ do { if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) != 0) break; } while (vblank.flags & FB_VBLANK_VBLANKING); do { if (ioctl(fbfd, FBIOGET_VBLANK, &vblank) != 0) break; } while (!(vblank.flags & FB_VBLANK_VBLANKING)); } else #endif /* bodged implementation for when the framebuffer doesn't support it */ /* We must not to run this loop while returning from a VT switch as timer * "interrupts" will not be running at that time so retrace_count will * remain constant. */ if (_timer_installed && !in_fb_restore) { prev = retrace_count; do { } while (retrace_count == (int)prev); } } /* fb_set_palette: * Sets the palette. */ static void fb_set_palette(AL_CONST RGB *p, int from, int to, int vsync) { unsigned short r[256], g[256], b[256]; struct fb_cmap cmap; int i; ASSERT(p); cmap.start = from; cmap.len = to-from+1; cmap.red = r; cmap.green = g; cmap.blue = b; cmap.transp = NULL; for (i=0; i < (int)cmap.len; i++) { r[i] = p[from+i].r << 10; g[i] = p[from+i].g << 10; b[i] = p[from+i].b << 10; } fb_vsync(); ioctl(fbfd, FBIOPUTCMAP, &cmap); } static unsigned short *orig_cmap_data; /* original palette data */ /* fb_do_cmap: * Helper for fb_{save|restore}_cmap. */ static void fb_do_cmap (int ioctlno) { struct fb_cmap cmap; cmap.start = 0; cmap.len = 256; cmap.red = orig_cmap_data; cmap.green = orig_cmap_data+256; cmap.blue = orig_cmap_data+512; cmap.transp = NULL; ioctl(fbfd, ioctlno, &cmap); } /* fb_{save|restore}_cmap: * Routines to save and restore the whole palette. */ static void fb_save_cmap (void) { if (orig_cmap_data) _AL_FREE (orig_cmap_data); /* can't happen */ orig_cmap_data = _AL_MALLOC_ATOMIC (sizeof *orig_cmap_data* 768); if (orig_cmap_data) fb_do_cmap (FBIOGETCMAP); } static void fb_restore_cmap (void) { if (orig_cmap_data) { fb_do_cmap (FBIOPUTCMAP); _AL_FREE (orig_cmap_data); orig_cmap_data = NULL; } } static struct timings { char config_item[1024]; int pixclock; int left_margin; int right_margin; int upper_margin; int lower_margin; int hsync_len; int vsync_len; int vmode; int sync; int xres; int yres; } _fb_current_timings; static struct timings temp_timings; static int read_config_file (int w, int h); static int read_fbmodes_file (int w, int h); static int tweak_timings (int w, int h); /* _fb_get_timings: * Returns a pointer to a struct as above containing timings for the given * resolution, or NULL on error. */ static struct timings *_fb_get_timings (int w, int h) { /* First try the config file */ if (read_config_file (w, h)) return &temp_timings; /* Failing that, try fb.modes */ if (read_fbmodes_file (w, h)) return &temp_timings; /* Still no luck, so tweak the current mode instead */ if (tweak_timings (w, h)) return &temp_timings; return NULL; } /* read_config_file: * Assigns timing settings from the config file or returns 0. */ static int read_config_file (int w, int h) { char tmp[128]; char **argv; int argc; /* Let the setup program know what config string we read for this mode */ uszprintf(temp_timings.config_item, sizeof(temp_timings.config_item), uconvert_ascii("fb_mode_%dx%d", tmp), w, h); /* First try the config file */ argv = get_config_argv (NULL, temp_timings.config_item, &argc); if (argv) { #define get_info(info) if (*argv) temp_timings.info = ustrtol (*argv++, NULL, 10) get_info(pixclock); get_info(left_margin); get_info(right_margin); get_info(upper_margin); get_info(lower_margin); get_info(hsync_len); get_info(vsync_len); if (*argv) { if (!ustrcmp (*argv, uconvert_ascii("none", tmp))) temp_timings.vmode = FB_VMODE_NONINTERLACED; else if (!ustrcmp (*argv, uconvert_ascii("interlaced", tmp))) temp_timings.vmode = FB_VMODE_INTERLACED; else if (!ustrcmp (*argv, uconvert_ascii("doublescan", tmp))) temp_timings.vmode = FB_VMODE_DOUBLE; argv++; } else temp_timings.vmode = FB_VMODE_NONINTERLACED; get_info(sync); #undef get_info temp_timings.xres = w; temp_timings.yres = h; return 1; } return 0; } /* helper to read the relevant parts of a line from fb.modes */ static char *get_line (FILE *file) { static char buffer[1024]; char *ch; ASSERT (file); if (!fgets (buffer, sizeof (buffer), file)) return 0; /* if there's no eol, get one before continuing */ if (!strchr (buffer, '\n') && strlen (buffer) == 1 + sizeof (buffer)) { char waste[128], *ret; do { ret = fgets (waste, sizeof (waste), file); } while (ret && !strchr (waste, '\n')); /* this doesn't actually exit because we still have buffer */ } if ((ch = strpbrk (buffer, "#\n"))) *ch = 0; ch = buffer; while (uisspace(*ch)) ch++; return ch; } /* read_fbmodes_file: * Assigns timing settings from the fbmodes file or returns 0. */ static int read_fbmodes_file (int w, int h) { char *mode_id = NULL; char *geometry = NULL; char *timings = NULL; int sync = 0, vmode = 0; char *s, *t; FILE *fbmodes; int ret = 0; fbmodes = fopen ("/etc/fb.modes", "r"); if (!fbmodes) return 0; do { s = get_line (fbmodes); if (!s) break; t = strchr (s, ' '); if (t) { *t++ = '\0'; while (uisspace(*t)) t++; } else { t = strchr (s, '\0'); } if (!strcmp (s, "mode")) { _AL_FREE (mode_id); _AL_FREE (geometry); _AL_FREE (timings); mode_id = strdup (t); geometry = timings = NULL; sync = 0; vmode = FB_VMODE_NONINTERLACED; } else if (!strcmp (s, "endmode")) { if (geometry && timings) { int mw, mh; sscanf (geometry, "%d %d", &mw, &mh); if ((mw == w) && (mh == h)) { sscanf (timings, "%d %d %d %d %d %d %d", &temp_timings.pixclock, &temp_timings.left_margin, &temp_timings.right_margin, &temp_timings.upper_margin, &temp_timings.lower_margin, &temp_timings.hsync_len, &temp_timings.vsync_len ); temp_timings.sync = sync; temp_timings.vmode = vmode; temp_timings.xres = w; temp_timings.yres = h; ret = 1; s = NULL; } } _AL_FREE (mode_id); _AL_FREE (geometry); _AL_FREE (timings); mode_id = geometry = timings = NULL; } else if (!strcmp (s, "geometry")) { _AL_FREE (geometry); geometry = strdup (t); } else if (!strcmp (s, "timings")) { _AL_FREE (timings); timings = strdup (t); } else if (!strcmp (s, "hsync")) { #define set_bit(var,bit,on) var = ((var) &~ (bit)) | ((on) ? bit : 0) set_bit (sync, FB_SYNC_HOR_HIGH_ACT, t[0] == 'h'); } else if (!strcmp (s, "vsync")) { set_bit (sync, FB_SYNC_VERT_HIGH_ACT, t[0] == 'h'); } else if (!strcmp (s, "csync")) { set_bit (sync, FB_SYNC_COMP_HIGH_ACT, t[0] == 'h'); } else if (!strcmp (s, "gsync")) { set_bit (sync, FB_SYNC_ON_GREEN, t[0] == 'h'); } else if (!strcmp (s, "extsync")) { set_bit (sync, FB_SYNC_EXT, t[0] == 't'); } else if (!strcmp (s, "bcast")) { set_bit (sync, FB_SYNC_BROADCAST, t[0] == 't'); } else if (!strcmp (s, "laced")) { if (t[0] == 't') vmode = FB_VMODE_INTERLACED; } else if (!strcmp (s, "double")) { if (t[0] == 't') vmode = FB_VMODE_DOUBLE; } } while (s); _AL_FREE (mode_id); _AL_FREE (geometry); _AL_FREE (timings); fclose (fbmodes); return ret; } /* tweak_timings: * Tweak the timings to match the mode we want to set. Only works if * the parent is a higher resolution. */ static int tweak_timings (int w, int h) { if ((w <= temp_timings.xres) && (h <= temp_timings.yres)) { int diff = temp_timings.xres - w; temp_timings.left_margin += diff/2; temp_timings.right_margin += diff/2 + diff%2; temp_timings.xres = w; diff = temp_timings.yres - h; temp_timings.upper_margin += diff/2; temp_timings.lower_margin += diff/2 + diff%2; temp_timings.yres = h; return 1; } return 0; } static void set_default_timings (void) { char tmp[128]; #define cp(x) temp_timings.x = orig_mode.x cp(pixclock); cp(left_margin); cp(right_margin); cp(upper_margin); cp(lower_margin); cp(hsync_len); cp(vsync_len); cp(vmode); cp(sync); cp(xres); cp(yres); #undef cp uszprintf(temp_timings.config_item, sizeof(temp_timings.config_item), uconvert_ascii("fb_mode_%dx%d", tmp), orig_mode.xres, orig_mode.yres); } /* update_timings: * Updates the timing section of the mode info. Maybe we can make * this algorithmic, as a backup, at some point. For now it searches * the config file or /etc/fb.modes for the data. * * We could make the init routine give up if the data isn't there, or * use an algorithmic guesser. * * If we go right ahead with this system, I think the setup program * should offer quite a few options -- dotclock probing might be useful, * along with the functionality of xvidtune. */ static int update_timings(struct fb_var_screeninfo *mode) { struct timings *t; ASSERT(mode); set_default_timings(); t = _fb_get_timings (mode->xres, mode->yres); if (!t) return -1; /* for debugging, maybe for the setup program too */ memcpy (&_fb_current_timings, t, sizeof(struct timings)); /* update the mode struct */ mode->pixclock = t->pixclock; mode->left_margin = t->left_margin; mode->right_margin = t->right_margin; mode->upper_margin = t->upper_margin; mode->lower_margin = t->lower_margin; mode->hsync_len = t->hsync_len; mode->vsync_len = t->vsync_len; mode->vmode = t->vmode; mode->sync = t->sync; return 0; } /* I'm not sure whether these work or not -- my Matrox seems capable * of setting whatever you ask it to. */ #if 0 static int _fb_get_pixclock(void) { struct fb_var_screeninfo mode; if (ioctl (fbfd, FBIOGET_VSCREENINFO, &mode)) return -1; return mode.pixclock; } static void _fb_set_pixclock(int new_val) { struct fb_var_screeninfo mode; if (ioctl (fbfd, FBIOGET_VSCREENINFO, &mode)) return; mode.pixclock = new_val; if (ioctl (fbfd, FBIOPUT_VSCREENINFO, &mode)) return; } #endif #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { if (system_driver == SYSTEM_LINUX) { _unix_register_gfx_driver(GFX_FBCON, &gfx_fbcon, TRUE, TRUE); /* Register resolution and colour depth getters. * This is a bit ugly because these are actually part of the * system driver rather than the graphics driver... */ system_linux.desktop_color_depth = __al_linux_get_fb_color_depth; system_linux.get_desktop_resolution = __al_linux_get_fb_resolution; } } #endif /* ifdef ALLEGRO_MODULE */ #endif /* if (defined ALLEGRO_LINUX_FBCON) ... */ allegro-4.4.3.1/src/linux/lvga.c0000664000175000017500000001306113437077643015324 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helpers for setting VGA modes in Linux. * * By George Foot, based on code by Marek Habersack. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include "allegro.h" #if ((defined ALLEGRO_LINUX_VGA) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))) #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "allegro/internal/aintvga.h" static MODE_REGISTERS mode13h = /* 320x200x8bpp NI */ { /* CRTC registers (24: 0-23) */ { 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3 }, /* Sequencer registers (5: 54-58) */ { 0x03, 0x01, 0x0F, 0x00, 0x0E }, /* ATC registers (21: 24-44) */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00 }, /* GC registers (9: 45-53) */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF }, /* misc (1: 59-59) */ 0x63, /* null pointer to extra register block; extra reg count */ NULL, 0, /* text font data */ NULL, NULL, /* flags */ 0L, /* palette (unused) */ { { 0 } } }; static MODE_REGISTERS mode10h = /* 640x350x4bpp NI */ { /* CRTC registers (24: 0-23) */ { 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3 }, /* Sequencer registers (5: 54-58) */ { 0x03, 0x01, 0x0F, 0x00, 0x06 }, /* ATC registers (21: 24-44) */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00 }, /* GC registers (9: 45-53) */ { 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF }, /* misc (1: 59-59) */ 0xA3, /* null pointer to extra register block; extra reg count */ NULL, 0, /* text font data */ NULL, NULL, /* flags */ 0L, /* palette (unused) */ { { 0 } } }; static MODE_REGISTERS mode0Dh = /* 320x200x4bpp NI */ { /* CRTC registers (24: 0-23) */ { 0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3 }, /* Sequencer registers (5: 54-58) */ { 0x03, 0x09, 0x0F, 0x00, 0x06 }, /* ATC registers (21: 24-44) */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x00, 0x0F, 0x00, 0x00 }, /* GC registers (9: 45-53) */ { 0x00, 0x0F, 0x00, 0x20, 0x00, 0x00, 0x05, 0x0F, 0xFF }, /* misc (1: 59-59) */ 0x63, /* null pointer to extra register block; extra reg count */ NULL, 0, /* text font data */ NULL, NULL, /* flags */ 0L, /* palette (unused) */ { { 0 } } }; static struct MAPPED_MEMORY vram = { 0xa0000, 0x10000, PROT_READ | PROT_WRITE, NULL }; /* _set_vga_mode: * Helper for the VGA and mode-X drivers to set a video mode. */ uintptr_t _set_vga_mode (int modenum) { MODE_REGISTERS *regs; if (!__al_linux_have_ioperms) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("This driver needs root privileges")); return 0; } switch (modenum) { case 0x13: regs = &mode13h; break; case 0x10: regs = &mode10h; break; case 0x0D: regs = &mode0Dh; break; default: ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Required VGA mode not supported")); return 0; } if (__al_linux_map_memory (&vram)) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to map video memory")); return 0; } __al_linux_screen_off(); if (__al_linux_console_graphics()) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Error setting VGA video mode")); __al_linux_screen_on(); __al_linux_unmap_memory (&vram); return 0; } __al_linux_save_text_mode(); __al_linux_set_vga_regs (regs); __al_linux_clear_vram(); __al_linux_screen_on(); return (unsigned long)vram.data; } /* _unset_vga_mode: * Helper for the VGA and mode-X drivers to unset the video mode. */ void _unset_vga_mode (void) { __al_linux_unmap_memory (&vram); __al_linux_screen_off(); __al_linux_restore_text_mode(); __al_linux_console_text(); __al_linux_screen_on(); } static MODE_REGISTERS gfx_regs; void _save_vga_mode (void) { __al_linux_screen_off(); get_palette (gfx_regs.palette.allegro); __al_linux_get_vga_regs (&gfx_regs); __al_linux_restore_text_mode(); __al_linux_console_text(); __al_linux_screen_on(); } void _restore_vga_mode (void) { __al_linux_screen_off(); __al_linux_save_text_mode(); __al_linux_console_graphics(); __al_linux_set_vga_regs (&gfx_regs); set_palette (gfx_regs.palette.allegro); __al_linux_screen_on(); } #endif /* if ((defined ALLEGRO_LINUX_VGA) && ... */ allegro-4.4.3.1/src/linux/lmsedrv.c0000664000175000017500000000266413437077643016056 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console mouse driver list. * * By George Foot. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" /* list the available drivers */ _DRIVER_INFO _linux_mouse_driver_list[] = { { MOUSEDRV_LINUX_IPS2, &mousedrv_linux_ips2, TRUE }, { MOUSEDRV_LINUX_PS2, &mousedrv_linux_ps2, TRUE }, { MOUSEDRV_LINUX_MS, &mousedrv_linux_ms, TRUE }, { MOUSEDRV_LINUX_IMS, &mousedrv_linux_ims, TRUE }, { MOUSEDRV_LINUX_GPMDATA, &mousedrv_linux_gpmdata, TRUE }, #ifdef ALLEGRO_HAVE_LINUX_INPUT_H { MOUSEDRV_LINUX_EVDEV, &mousedrv_linux_evdev, TRUE }, #endif #ifdef ALLEGRO_LINUX_TSLIB { MOUSEDRV_LINUX_TSLIB, &mousedrv_linux_tslib, TRUE }, #endif { MOUSEDRV_NONE, &mousedrv_none, TRUE }, { 0, NULL, 0 } }; allegro-4.4.3.1/src/linux/lstddrv.c0000664000175000017500000000500313437077643016052 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Standard driver helpers for Linux Allegro. * * By Marek Habersack, mangled by George Foot. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #include /* List of standard drivers */ STD_DRIVER *__al_linux_std_drivers[N_STD_DRIVERS]; static int std_drivers_suspended = FALSE; /* __al_linux_add_standard_driver: * Adds a standard driver; returns 0 on success, non-zero if the sanity * checks fail. */ int __al_linux_add_standard_driver (STD_DRIVER *spec) { if (!spec) return 1; if (spec->type >= N_STD_DRIVERS) return 2; if (!spec->update) return 3; if (spec->fd < 0) return 4; __al_linux_std_drivers[spec->type] = spec; spec->resume(); return 0; } /* __al_linux_remove_standard_driver: * Removes a standard driver, returning 0 on success or non-zero on * failure. */ int __al_linux_remove_standard_driver (STD_DRIVER *spec) { if (!spec) return 1; if (spec->type >= N_STD_DRIVERS) return 3; if (!__al_linux_std_drivers[spec->type]) return 4; if (__al_linux_std_drivers[spec->type] != spec) return 5; spec->suspend(); __al_linux_std_drivers[spec->type] = NULL; return 0; } /* __al_linux_update_standard_drivers: * Updates all drivers. */ void __al_linux_update_standard_drivers (int threaded) { int i; if (!std_drivers_suspended) { for (i = 0; i < N_STD_DRIVERS; i++) if (__al_linux_std_drivers[i]) __al_linux_std_drivers[i]->update(); } } /* __al_linux_suspend_standard_drivers: * Temporary disable standard drivers during a VT switch. */ void __al_linux_suspend_standard_drivers (void) { ASSERT(!std_drivers_suspended); std_drivers_suspended = TRUE; } /* __al_linux_resume_standard_drivers: * Re-enable standard drivers after a VT switch. */ void __al_linux_resume_standard_drivers (void) { ASSERT(std_drivers_suspended); std_drivers_suspended = FALSE; } allegro-4.4.3.1/src/linux/ltimer.c0000664000175000017500000000173513437077643015674 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux timer driver list. * * By George Foot. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/platform/aintunix.h" /* list the available drivers */ _DRIVER_INFO _linux_timer_driver_list[] = { #ifdef ALLEGRO_HAVE_LIBPTHREAD { TIMERDRV_UNIX_PTHREADS, &timerdrv_unix_pthreads, TRUE }, #else { TIMERDRV_UNIX_SIGALRM, &timerdrv_unix_sigalrm, TRUE }, #endif { 0, NULL, 0 } }; allegro-4.4.3.1/src/linux/lmsems.c0000664000175000017500000001343513437077643015700 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console internal mouse driver for Microsoft mouse. * * By George Foot. * * See readme.txt for copyright information. */ #include #include #include #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" static int intellimouse; static int packet_size; /* processor: * Processes the first packet in the buffer, if any, returning the number * of bytes eaten. * * Microsoft protocol has only seven data bits. The top bit is set in * the first byte of the packet, clear in the other two. The next two * bits in the header are the button state. The next two are the top * bits of the Y offset (second data byte), and the last two are the * top bits of the X offset (first data byte). */ static int processor (unsigned char *buf, int buf_size) { int r, l, m, x, y, z; if (buf_size < packet_size) return 0; /* not enough data, spit it out for now */ /* if packet is invalid, just eat it */ if (!(buf[0] & 0x40)) return 1; /* invalid byte */ if (buf[1] & 0x40) return 1; /* first data byte is actually a header */ if (buf[2] & 0x40) return 2; /* second data byte is actually a header */ /* packet is valid, decode the data */ l = !!(buf[0] & 0x20); r = !!(buf[0] & 0x10); if (intellimouse) { m = !!(buf[3] & 0x10); z = (buf[3] & 0x0f); if (z) z = (z-7) >> 3; } else { m = 0; z = 0; } x = (signed char) (((buf[0] & 0x03) << 6) | (buf[1] & 0x3F)); y = -(signed char) (((buf[0] & 0x0C) << 4) | (buf[2] & 0x3F)); __al_linux_mouse_handler(x, y, z, l+(r<<1)+(m<<2)); return packet_size; /* yum */ } /* analyse_data: * Analyses the given data, returning 0 if it is unparsable, nonzero * if there's a reasonable chance that this driver can work with that * data. */ static int analyse_data (AL_CONST char *buffer, int size) { int pos = 0; int packets = 0, errors = 0; int step = 0; for (pos = 0; pos < size; pos++) switch (step) { case 3: packets++; step = 0; case 0: if (!(buffer[pos] & 0x40)) { errors++; } else { step++; } break; case 1: case 2: if (buffer[pos] & 0x40) { errors++; step = 0; pos--; } else { step++; } break; } return (errors <= 5) || (errors < size / 20); /* 5% error allowance */ } static INTERNAL_MOUSE_DRIVER intdrv = { -1, processor, 2 }; /* sync_mouse: * To find the start of a packet, we just read all the data that's * waiting. This isn't a particularly good way, obviously. :) */ static void sync_mouse (int fd) { fd_set set; int result; struct timeval tv; char bitbucket; do { FD_ZERO (&set); FD_SET (fd, &set); tv.tv_sec = tv.tv_usec = 0; result = select (FD_SETSIZE, &set, NULL, NULL, &tv); if (result > 0) read (fd, &bitbucket, 1); } while (result > 0); } /* mouse_init: * Here we open the mouse device, initialise anything that needs it, * and chain to the framework init routine. */ static int mouse_init (void) { char tmp1[128], tmp2[128], tmp3[128]; AL_CONST char *udevice; struct termios t; /* Find the device filename */ udevice = get_config_string (uconvert_ascii ("mouse", tmp1), uconvert_ascii ("mouse_device", tmp2), uconvert_ascii ("/dev/mouse", tmp3)); /* Open mouse device. Devices are cool. */ intdrv.device = open (uconvert_toascii (udevice, tmp1), O_RDONLY | O_NONBLOCK); if (intdrv.device < 0) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to open %s: %s"), udevice, ustrerror (errno)); return -1; } /* Set parameters */ tcgetattr (intdrv.device, &t); t.c_iflag = IGNBRK | IGNPAR; t.c_oflag = t.c_lflag = t.c_line = 0; t.c_cflag = CS7 | CREAD | CLOCAL | HUPCL | B1200; tcsetattr (intdrv.device, TCSAFLUSH, &t); /* Discard any garbage, so the next thing we read is a packet header */ sync_mouse (intdrv.device); return __al_linux_mouse_init (&intdrv); } /* ms_mouse_init: * Initialisation for vanilla MS mouse. */ static int ms_mouse_init (void) { intellimouse = FALSE; packet_size = 3; intdrv.num_buttons = 2; return mouse_init (); } /* msi_mouse_init: * Initialisation for MS mouse with Intellimouse extension. */ static int ims_mouse_init (void) { intellimouse = TRUE; packet_size = 4; intdrv.num_buttons = 3; return mouse_init (); } /* mouse_exit: * Chain to the framework, then uninitialise things. */ static void mouse_exit (void) { __al_linux_mouse_exit(); close (intdrv.device); } MOUSE_DRIVER mousedrv_linux_ms = { MOUSEDRV_LINUX_MS, empty_string, empty_string, "Linux MS mouse", ms_mouse_init, mouse_exit, NULL, /* poll() */ NULL, /* timer_poll() */ __al_linux_mouse_position, __al_linux_mouse_set_range, __al_linux_mouse_set_speed, __al_linux_mouse_get_mickeys, analyse_data, NULL, /* enable_hardware_cursor */ NULL }; MOUSE_DRIVER mousedrv_linux_ims = { MOUSEDRV_LINUX_IMS, empty_string, empty_string, "Linux MS Intellimouse", ims_mouse_init, mouse_exit, NULL, /* poll() */ NULL, /* timer_poll() */ __al_linux_mouse_position, __al_linux_mouse_set_range, __al_linux_mouse_set_speed, __al_linux_mouse_get_mickeys, analyse_data, NULL, /* enable_hardware_cursor */ NULL }; allegro-4.4.3.1/src/linux/lmouse.c0000664000175000017500000001355113437077643015703 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console mouse module. * * By George Foot. * * This file contains a generic framework for different mouse * types to hook into. See lmseps2.c for an example. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" static int mouse_mx = 0; /* internal position, in mickeys */ static int mouse_my = 0; static int mouse_sx = 128; /* mickey -> pixel scaling factor */ static int mouse_sy = 128; static int mouse_minx = 0; /* mouse range */ static int mouse_miny = 0; static int mouse_maxx = 319; static int mouse_maxy = 199; static int mymickey_x = 0; /* for get_mouse_mickeys() */ static int mymickey_y = 0; #define MICKEY_TO_COORD_X(n) ((n) * mouse_sx / 256) #define MICKEY_TO_COORD_Y(n) ((n) * mouse_sy / 256) #define COORD_TO_MICKEY_X(n) ((n) * 256 / mouse_sx) #define COORD_TO_MICKEY_Y(n) ((n) * 256 / mouse_sy) /* __al_linux_mouse_position: * Sets the position of the mickey-mode mouse. */ void __al_linux_mouse_position(int x, int y) { DISABLE(); _mouse_x = x; _mouse_y = y; mouse_mx = COORD_TO_MICKEY_X(x); mouse_my = COORD_TO_MICKEY_Y(y); mymickey_x = mymickey_y = 0; ENABLE(); } /* __al_linux_mouse_set_range: * Sets the range of the mickey-mode mouse. */ void __al_linux_mouse_set_range(int x1, int y1, int x2, int y2) { mouse_minx = x1; mouse_miny = y1; mouse_maxx = x2; mouse_maxy = y2; DISABLE(); _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); ENABLE(); } /* __al_linux_mouse_set_speed: * Sets the speed of the mickey-mode mouse. */ void __al_linux_mouse_set_speed(int xspeed, int yspeed) { int scale; if (gfx_driver) scale = 256*gfx_driver->w/320; else scale = 256; DISABLE(); mouse_sx = scale / MAX(1, xspeed); mouse_sy = scale / MAX(1, yspeed); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); ENABLE(); } /* __al_linux_mouse_get_mickeys: * Reads the mickey-mode count. */ void __al_linux_mouse_get_mickeys(int *mickeyx, int *mickeyy) { int temp_x = mymickey_x; int temp_y = mymickey_y; mymickey_x -= temp_x; mymickey_y -= temp_y; *mickeyx = temp_x; *mickeyy = temp_y; } /* __al_linux_mouse_handler: * Movement callback for mickey-mode driver. */ void __al_linux_mouse_handler (int x, int y, int z, int b) { _mouse_b = b; mymickey_x += x; mymickey_y -= y; mouse_mx += x; mouse_my -= y; _mouse_x = MICKEY_TO_COORD_X(mouse_mx); _mouse_y = MICKEY_TO_COORD_Y(mouse_my); _mouse_z += z; if ((_mouse_x < mouse_minx) || (_mouse_x > mouse_maxx) || (_mouse_y < mouse_miny) || (_mouse_y > mouse_maxy)) { _mouse_x = CLAMP(mouse_minx, _mouse_x, mouse_maxx); _mouse_y = CLAMP(mouse_miny, _mouse_y, mouse_maxy); mouse_mx = COORD_TO_MICKEY_X(_mouse_x); mouse_my = COORD_TO_MICKEY_Y(_mouse_y); } _handle_mouse_input(); } static int update_mouse (void); static void resume_mouse (void); static void suspend_mouse (void); static STD_DRIVER std_mouse = { STD_MOUSE, update_mouse, resume_mouse, suspend_mouse, -1 /* fd -- filled in later */ }; #include #include #include #include #include #include static int resume_count; static INTERNAL_MOUSE_DRIVER *internal_driver; /* update_mouse: * Reads data from the mouse, attempting to process it. */ static int update_mouse (void) { static unsigned char buf[1024]; static int bytes_in_buffer = 0; int bytes_read; fd_set set; struct timeval tv = { 0, 0 }; if (resume_count <= 0) return 0; FD_ZERO(&set); FD_SET(std_mouse.fd, &set); if (select (FD_SETSIZE, &set, NULL, NULL, &tv) <= 0) return 0; bytes_read = read(std_mouse.fd, &buf[bytes_in_buffer], sizeof(buf) - bytes_in_buffer); if (bytes_read <= 0) return 0; bytes_in_buffer += bytes_read; while (bytes_in_buffer && (bytes_read = internal_driver->process (buf, bytes_in_buffer))) { int i; bytes_in_buffer -= bytes_read; for (i = 0; i < bytes_in_buffer; i++) buf[i] = buf[i+bytes_read]; } return 1; } /* activate_mouse: * Put mouse device into the mode we want. */ static void activate_mouse (void) { } /* deactivate_mouse: * Restore the original settings. */ static void deactivate_mouse (void) { } /* suspend_mouse: * Suspend our mouse handling. */ static void suspend_mouse (void) { resume_count--; if (resume_count == 0) deactivate_mouse(); } /* resume_mouse: * Start/resume Allegro mouse handling. */ static void resume_mouse (void) { if (resume_count == 0) activate_mouse(); resume_count++; } /* __al_linux_mouse_init: * Sets up the mouse driver. */ int __al_linux_mouse_init (INTERNAL_MOUSE_DRIVER *drv) { internal_driver = drv; std_mouse.fd = drv->device; /* Mouse is disabled now. */ resume_count = 0; /* Register our driver (enables it too). */ __al_linux_add_standard_driver (&std_mouse); return internal_driver->num_buttons; } /* __al_linux_mouse_exit: * Removes our driver. */ void __al_linux_mouse_exit (void) { __al_linux_remove_standard_driver (&std_mouse); } allegro-4.4.3.1/src/linux/lkeybd.c0000664000175000017500000004046013437077643015650 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console keyboard module. * * By Marek Habersack, modified by George Foot. * * See readme.txt for copyright information. */ /* Make sure we don't #define our own KEY_ macros as linux has its * own. Instead, we use the __allegro_KEY_ constants in this file. */ #define ALLEGRO_NO_KEY_DEFINES #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #define PREFIX_I "al-ckey INFO: " #define PREFIX_W "al-ckey WARNING: " #define PREFIX_E "al-ckey ERROR: " static KEYBOARD_DRIVER keydrv_linux_console; /* list the available drivers */ _DRIVER_INFO _linux_keyboard_driver_list[] = { { KEYDRV_LINUX, &keydrv_linux_console, TRUE }, { 0, NULL, 0 } }; static int linux_key_init (void); static void linux_key_exit (void); static void linux_set_leds (int leds); static void linux_set_rate (int delay, int rate); static int linux_scancode_to_ascii (int scancode); static KEYBOARD_DRIVER keydrv_linux_console = { KEYDRV_LINUX, empty_string, empty_string, "Linux console keyboard", FALSE, linux_key_init, linux_key_exit, NULL, linux_set_leds, linux_set_rate, NULL, NULL, linux_scancode_to_ascii, NULL /* scancode_to_name */ }; static int update_keyboard (void); static void resume_keyboard (void); static void suspend_keyboard (void); static STD_DRIVER std_keyboard = { STD_KBD, update_keyboard, resume_keyboard, suspend_keyboard, -1 /* fd -- filled in later */ }; #include #include #include #include #include #include #include #include #include #include #include static int startup_kbmode; static int resume_count; static int main_pid; #define KB_MODIFIERS (__allegro_KB_SHIFT_FLAG | __allegro_KB_CTRL_FLAG | __allegro_KB_ALT_FLAG | \ __allegro_KB_LWIN_FLAG | __allegro_KB_RWIN_FLAG | __allegro_KB_MENU_FLAG) #define KB_LED_FLAGS (__allegro_KB_SCROLOCK_FLAG | __allegro_KB_NUMLOCK_FLAG | __allegro_KB_CAPSLOCK_FLAG) /* lookup table for converting kernel scancodes into Allegro format */ static unsigned char kernel_to_mycode[128] = { /* 0x00 */ 0, __allegro_KEY_ESC, __allegro_KEY_1, __allegro_KEY_2, /* 0x04 */ __allegro_KEY_3, __allegro_KEY_4, __allegro_KEY_5, __allegro_KEY_6, /* 0x08 */ __allegro_KEY_7, __allegro_KEY_8, __allegro_KEY_9, __allegro_KEY_0, /* 0x0C */ __allegro_KEY_MINUS, __allegro_KEY_EQUALS, __allegro_KEY_BACKSPACE, __allegro_KEY_TAB, /* 0x10 */ __allegro_KEY_Q, __allegro_KEY_W, __allegro_KEY_E, __allegro_KEY_R, /* 0x14 */ __allegro_KEY_T, __allegro_KEY_Y, __allegro_KEY_U, __allegro_KEY_I, /* 0x18 */ __allegro_KEY_O, __allegro_KEY_P, __allegro_KEY_OPENBRACE, __allegro_KEY_CLOSEBRACE, /* 0x1C */ __allegro_KEY_ENTER, __allegro_KEY_LCONTROL, __allegro_KEY_A, __allegro_KEY_S, /* 0x20 */ __allegro_KEY_D, __allegro_KEY_F, __allegro_KEY_G, __allegro_KEY_H, /* 0x24 */ __allegro_KEY_J, __allegro_KEY_K, __allegro_KEY_L, __allegro_KEY_COLON, /* 0x28 */ __allegro_KEY_QUOTE, __allegro_KEY_TILDE, __allegro_KEY_LSHIFT, __allegro_KEY_BACKSLASH, /* 0x2C */ __allegro_KEY_Z, __allegro_KEY_X, __allegro_KEY_C, __allegro_KEY_V, /* 0x30 */ __allegro_KEY_B, __allegro_KEY_N, __allegro_KEY_M, __allegro_KEY_COMMA, /* 0x34 */ __allegro_KEY_STOP, __allegro_KEY_SLASH, __allegro_KEY_RSHIFT, __allegro_KEY_ASTERISK, /* 0x38 */ __allegro_KEY_ALT, __allegro_KEY_SPACE, __allegro_KEY_CAPSLOCK, __allegro_KEY_F1, /* 0x3C */ __allegro_KEY_F2, __allegro_KEY_F3, __allegro_KEY_F4, __allegro_KEY_F5, /* 0x40 */ __allegro_KEY_F6, __allegro_KEY_F7, __allegro_KEY_F8, __allegro_KEY_F9, /* 0x44 */ __allegro_KEY_F10, __allegro_KEY_NUMLOCK, __allegro_KEY_SCRLOCK, __allegro_KEY_7_PAD, /* 0x48 */ __allegro_KEY_8_PAD, __allegro_KEY_9_PAD, __allegro_KEY_MINUS_PAD, __allegro_KEY_4_PAD, /* 0x4C */ __allegro_KEY_5_PAD, __allegro_KEY_6_PAD, __allegro_KEY_PLUS_PAD, __allegro_KEY_1_PAD, /* 0x50 */ __allegro_KEY_2_PAD, __allegro_KEY_3_PAD, __allegro_KEY_0_PAD, __allegro_KEY_DEL_PAD, /* 0x54 */ 0, 0, __allegro_KEY_BACKSLASH2, __allegro_KEY_F11, /* 0x58 */ __allegro_KEY_F12, 0, 0, 0, /* 0x5C */ 0, 0, 0, 0, /* 0x60 */ __allegro_KEY_ENTER_PAD, __allegro_KEY_RCONTROL, __allegro_KEY_SLASH_PAD, __allegro_KEY_PRTSCR, /* 0x64 */ __allegro_KEY_ALTGR, 0, __allegro_KEY_HOME, __allegro_KEY_UP, /* 0x68 */ __allegro_KEY_PGUP, __allegro_KEY_LEFT, __allegro_KEY_RIGHT, __allegro_KEY_END, /* 0x6C */ __allegro_KEY_DOWN, __allegro_KEY_PGDN, __allegro_KEY_INSERT, __allegro_KEY_DEL, /* 0x70 */ 0, 0, 0, 0, /* 0x74 */ 0, 0, 0, __allegro_KEY_PAUSE, /* 0x78 */ 0, 0, 0, 0, /* 0x7C */ 0, __allegro_KEY_LWIN, __allegro_KEY_RWIN, __allegro_KEY_MENU }; /* convert Allegro format scancodes into key_shifts flag bits */ static unsigned short modifier_table[__allegro_KEY_MAX - __allegro_KEY_MODIFIERS] = { __allegro_KB_SHIFT_FLAG, __allegro_KB_SHIFT_FLAG, __allegro_KB_CTRL_FLAG, __allegro_KB_CTRL_FLAG, __allegro_KB_ALT_FLAG, __allegro_KB_ALT_FLAG, __allegro_KB_LWIN_FLAG, __allegro_KB_RWIN_FLAG, __allegro_KB_MENU_FLAG, __allegro_KB_SCROLOCK_FLAG, __allegro_KB_NUMLOCK_FLAG, __allegro_KB_CAPSLOCK_FLAG }; #define NUM_PAD_KEYS 17 static char pad_asciis_numlock[NUM_PAD_KEYS] = "0123456789+-*/\r,."; static char pad_asciis_no_numlock[NUM_PAD_KEYS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, '+', '-', '*', '/', '\r', -1, -1 }; static void process_keyboard_data (unsigned char *buf, size_t bytes_read) { unsigned int ch; unsigned int code, mycode, press; int ascii; int map; int val; struct kbentry kbe; ASSERT(buf || bytes_read==0); /* Process all keys read from left to right */ for (ch = 0; ch < bytes_read; ch++) { /* Read kernel's fake scancode */ code = buf[ch] & 0x7f; press = !(buf[ch] & 0x80); /* Convert to Allegro's fake scancode */ mycode = kernel_to_mycode[code]; /* Process modifiers */ if (mycode >= __allegro_KEY_MODIFIERS) { int flag = modifier_table[mycode - __allegro_KEY_MODIFIERS]; if (press) { if (flag & KB_MODIFIERS) _key_shifts |= flag; else if ((flag & KB_LED_FLAGS) && key_led_flag) _key_shifts ^= flag; _handle_key_press (-1, mycode); } else { if (flag & KB_MODIFIERS) _key_shifts &= ~flag; _handle_key_release (mycode); } continue; } /* Releases only need the scancode */ if (!press) { _handle_key_release (mycode); continue; } /* Build kernel keymap number */ map = 0; if (key[__allegro_KEY_LSHIFT] || key[__allegro_KEY_RSHIFT]) map |= 1; if (key[__allegro_KEY_ALTGR]) map |= 2; if (key[__allegro_KEY_LCONTROL] || key[__allegro_KEY_RCONTROL]) map |= 4; if (key[__allegro_KEY_ALT]) map |= 8; /* Map scancode to type and value */ kbe.kb_table = map; kbe.kb_index = code; ioctl (std_keyboard.fd, KDGKBENT, &kbe); /* debugging */ /* TRACE(PREFIX_I "keypress: code=%3d mycode=%3d map=%2d kb_value=%04x\n", code, mycode, map, kbe.kb_value); */ /* Allegro wants Alt+key to return ASCII code zero */ if (key[__allegro_KEY_ALT]) ascii = 0; else /* Otherwise fill it in according to the key pressed */ switch (mycode) { case __allegro_KEY_BACKSPACE: ascii = 8; break; default: /* Most keys come here */ ascii = KVAL(kbe.kb_value); /* Handle invalid keymaps */ /* FIXME: Maybe we should just redo the * ioctl with keymap 0? */ if (kbe.kb_value == K_NOSUCHMAP) ascii = 0; } /* Finally do some things based on key type */ switch (KTYP(kbe.kb_value)) { case KT_CONS: if (!ioctl (__al_linux_console_fd, VT_ACTIVATE, KVAL(kbe.kb_value) + 1)) { _handle_key_press (-1, mycode); continue; } ascii = 0; break; case KT_LETTER: /* Apply capslock translation */ if (_key_shifts & __allegro_KB_CAPSLOCK_FLAG) ascii ^= 0x20; break; case KT_LATIN: case KT_ASCII: break; case KT_PAD: ascii = -1; val = KVAL(kbe.kb_value); if ((val >= 0) && (val < NUM_PAD_KEYS)) { if (_key_shifts & __allegro_KB_NUMLOCK_FLAG) ascii = pad_asciis_numlock[val]; else ascii = pad_asciis_no_numlock[val]; } break; case KT_SPEC: if (mycode == __allegro_KEY_ENTER) { ascii = '\r'; break; } case KT_FN: case KT_CUR: ascii = -1; break; default: /* Don't put anything in the buffer */ _handle_key_press (-1, mycode); } /* Replace -1 with the modifier state */ if (ascii == -1) ascii = _key_shifts & KB_MODIFIERS; /* three-finger salute for killing the program */ if (((mycode == __allegro_KEY_DEL) || (mycode == __allegro_KEY_END)) && (three_finger_flag) && (_key_shifts & __allegro_KB_CTRL_FLAG) && (_key_shifts & __allegro_KB_ALT_FLAG)) { TRACE(PREFIX_W "Three finger combo detected. SIGTERMing " "pid %d\n", main_pid); kill(main_pid, SIGTERM); } _handle_key_press (ascii, mycode); } } /* update_keyboard: * Read keys from keyboard, if there are any, and update all relevant * variables. * * We take full advantage of the kernel keyboard driver while still working * in the MEDIUM_RAW mode. This allows us to both keep track of the up/down * status of any key and return character codes from the kernel keymaps. */ static int update_keyboard (void) { unsigned char buf[128]; int bytes_read; fd_set set; struct timeval tv = { 0, 0 }; if (resume_count <= 0) return 0; FD_ZERO(&set); FD_SET(std_keyboard.fd, &set); if (select (FD_SETSIZE, &set, NULL, NULL, &tv) <= 0) return 0; bytes_read = read(std_keyboard.fd, &buf, sizeof(buf)); if (bytes_read < 1) return 0; process_keyboard_data(buf, bytes_read); return 1; } /* activate_keyboard: * Put keyboard into the mode we want. */ static void activate_keyboard (void) { tcsetattr (std_keyboard.fd, TCSANOW, &__al_linux_work_termio); ioctl (std_keyboard.fd, KDSKBMODE, K_MEDIUMRAW); } /* deactivate_keyboard: * Restore the original keyboard settings. */ static void deactivate_keyboard (void) { tcsetattr (std_keyboard.fd, TCSANOW, &__al_linux_startup_termio); ioctl (std_keyboard.fd, KDSKBMODE, startup_kbmode); } /* release_all_keys: * Sends release messages for all keys that are marked as pressed in the * key array. Maybe this should be a global function in `src/keyboard.c'; * it could be used by other platforms, and could work better with the * polled driver emulation system. */ static void release_all_keys (void) { int i; for (i = 0; i < __allegro_KEY_MAX; i++) if (key[i]) _handle_key_release (i); } /* suspend_keyboard: * Suspend our keyboard handling, restoring the original OS values, so that * the application can take advantage of Linux keyboard handling. */ static void suspend_keyboard (void) { resume_count--; if (resume_count == 0) deactivate_keyboard(); release_all_keys(); } /* resume_keyboard: * Start/resume Allegro keyboard handling. */ static void resume_keyboard(void) { if (resume_count == 0) activate_keyboard(); resume_count++; } static int linux_key_init (void) { if (__al_linux_use_console()) return 1; std_keyboard.fd = dup (__al_linux_console_fd); /* Set terminal attributes we need */ __al_linux_work_termio.c_iflag = 0; __al_linux_work_termio.c_cflag = CS8; __al_linux_work_termio.c_lflag = 0; /* Prevent `read' from blocking */ __al_linux_work_termio.c_cc[VMIN] = 0; __al_linux_work_termio.c_cc[VTIME] = 0; /* Save previous keyboard mode (probably XLATE) */ ioctl (std_keyboard.fd, KDGKBMODE, &startup_kbmode); /* Keyboard is disabled */ resume_count = 0; /* Get the pid, which we use for the three finger salute */ main_pid = getpid(); /* Register our driver (enables it too) */ __al_linux_add_standard_driver (&std_keyboard); return 0; } static void linux_key_exit (void) { /* Reset LED mode before exiting */ ioctl(std_keyboard.fd, KDSETLED, 8); __al_linux_remove_standard_driver (&std_keyboard); close (std_keyboard.fd); __al_linux_leave_console(); } static void linux_set_leds (int leds) { int val = 0; if (leds & __allegro_KB_SCROLOCK_FLAG) val |= LED_SCR; if (leds & __allegro_KB_NUMLOCK_FLAG) val |= LED_NUM; if (leds & __allegro_KB_CAPSLOCK_FLAG) val |= LED_CAP; ioctl(std_keyboard.fd, KDSETLED, val); } static void linux_set_rate (int delay, int rate) { } static int linux_scancode_to_ascii (int scancode) { int kernel_code; struct kbentry kbe; for (kernel_code = 0; kernel_code < 128; kernel_code++) if (scancode == kernel_to_mycode[kernel_code]) break; if (kernel_code == 128) return 0; kbe.kb_table = 0; kbe.kb_index = kernel_code; ioctl (std_keyboard.fd, KDGKBENT, &kbe); switch (KTYP(kbe.kb_value)) { case KT_LETTER: case KT_LATIN: case KT_ASCII: return KVAL(kbe.kb_value); case KT_SPEC: if (scancode == __allegro_KEY_ENTER) return '\r'; break; } return 0; } allegro-4.4.3.1/src/linux/ljoy.c0000664000175000017500000001603313437077643015352 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux joystick driver. * * By George Foot. * * Modified by Peter Wang. * * See readme.txt for copyright information. */ #include #include #include #include #include #include #define ALLEGRO_NO_KEY_DEFINES #include "allegro.h" #include "allegro/platform/aintunix.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_HAVE_LINUX_JOYSTICK_H /* To be safe, include sys/types.h before linux/joystick.h to avoid conflicting * definitions of fd_set. */ #include #include #define TOTAL_JOYSTICK_AXES (MAX_JOYSTICK_STICKS * MAX_JOYSTICK_AXIS) static int joy_fd[MAX_JOYSTICKS]; static JOYSTICK_AXIS_INFO *axis[MAX_JOYSTICKS][TOTAL_JOYSTICK_AXES]; static int joy_init(void) { JOYSTICK_INFO *j; AL_CONST char *device_name = NULL; char tmp[128], tmp1[128], tmp2[128]; unsigned int raw_version; char num_axes, num_buttons; int throttle; int i, s, a, b; for (i = 0; i < MAX_JOYSTICKS; i++) { /* Check for a user override on the device to use. */ uszprintf(tmp, sizeof(tmp), uconvert_ascii("joystick_device_%d", tmp1), i); device_name = get_config_string(uconvert_ascii("joystick", tmp1), tmp, NULL); /* Special case for the first joystick. */ if (!device_name && (i == 0)) device_name = get_config_string(uconvert_ascii("joystick", tmp1), uconvert_ascii("joystick_device", tmp2), NULL); if (device_name) { joy_fd[i] = open(uconvert_toascii(device_name, tmp), O_RDONLY|O_NONBLOCK); if (joy_fd[i] == -1) break; } else { snprintf(tmp, sizeof(tmp), "/dev/input/js%d", i); tmp[sizeof(tmp)-1] = 0; joy_fd[i] = open(tmp, O_RDONLY|O_NONBLOCK); if (joy_fd[i] == -1) { snprintf(tmp, sizeof(tmp), "/dev/js%d", i); tmp[sizeof(tmp)-1] = 0; joy_fd[i] = open(tmp, O_RDONLY|O_NONBLOCK); if (joy_fd[i] == -1) break; } } if (ioctl(joy_fd[i], JSIOCGVERSION, &raw_version) < 0) { /* NOTE: IOCTL fails if the joystick API is version 0.x */ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Your Linux joystick API is version 0.x which is unsupported.")); return -1; } ioctl(joy_fd[i], JSIOCGAXES, &num_axes); ioctl(joy_fd[i], JSIOCGBUTTONS, &num_buttons); if (num_axes > TOTAL_JOYSTICK_AXES) num_axes = TOTAL_JOYSTICK_AXES; if (num_buttons > MAX_JOYSTICK_BUTTONS) num_buttons = MAX_JOYSTICK_BUTTONS; /* User is allowed to override our simple assumption of which * axis number (kernel) the throttle is located at. */ uszprintf(tmp, sizeof(tmp), uconvert_ascii("throttle_axis_%d", tmp1), i); throttle = get_config_int(uconvert_ascii("joystick", tmp1), tmp, -1); if (throttle == -1) { throttle = get_config_int(uconvert_ascii("joystick", tmp1), uconvert_ascii("throttle_axis", tmp2), -1); } /* Each pair of axes is assumed to make up a stick unless it * is the sole remaining axis, or has been user specified, in * which case it is a throttle. */ j = &joy[i]; j->flags = JOYFLAG_ANALOGUE; for (s = 0, a = 0; (s < MAX_JOYSTICK_STICKS) && (a < num_axes); s++) { if ((a == throttle) || (a == num_axes-1)) { /* One axis throttle */ j->stick[s].flags = JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; j->stick[s].num_axis = 1; j->stick[s].axis[0].name = get_config_text("Throttle"); j->stick[s].name = ustrdup(j->stick[s].axis[0].name); axis[i][a++] = &j->stick[s].axis[0]; } else { /* Two axis stick. */ j->stick[s].flags = JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; j->stick[s].num_axis = 2; j->stick[s].axis[0].name = get_config_text("X"); j->stick[s].axis[1].name = get_config_text("Y"); j->stick[s].name = _AL_MALLOC_ATOMIC(32); ASSERT(j->stick[s].name); uszprintf((char *)j->stick[s].name, 32, get_config_text("Stick %d"), s+1); axis[i][a++] = &j->stick[s].axis[0]; axis[i][a++] = &j->stick[s].axis[1]; } } j->num_sticks = s; for (b = 0; b < num_buttons; b++) { j->button[b].name = _AL_MALLOC_ATOMIC(16); ASSERT(j->button[b].name); uszprintf((char *)j->button[b].name, 16, uconvert_ascii("%c", tmp), 'A' + b); } j->num_buttons = num_buttons; } num_joysticks = i; if (num_joysticks == 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to open %s: %s"), device_name ? device_name : uconvert_ascii("/dev/js0", tmp), ustrerror(errno)); return -1; } return 0; } static void joy_exit(void) { int i, j; for (i = 0; i < num_joysticks; i++) { close(joy_fd[i]); for (j = 0; j < joy[i].num_sticks; j++) _AL_FREE((void *)joy[i].stick[j].name); for (j = 0; j < joy[i].num_buttons; j++) _AL_FREE((void *)joy[i].button[j].name); } } static void set_axis(JOYSTICK_AXIS_INFO *axis, int value) { if (axis) { axis->pos = value * 127 / 32767; axis->d1 = (value < -8192); axis->d2 = (value > 8192); } } static int joy_poll(void) { fd_set set; struct timeval tv; struct js_event e[32]; int i, ready; int bytes, n, k; for (i = 0; i < num_joysticks; i++) { tv.tv_sec = tv.tv_usec = 0; FD_ZERO(&set); FD_SET(joy_fd[i], &set); ready = select(FD_SETSIZE, &set, NULL, NULL, &tv); if (ready <= 0) continue; while ((bytes = read(joy_fd[i], e, sizeof(e))) > 0) { n = bytes / sizeof(e[0]); for (k = 0; k < n; k++) { if (e[k].type & JS_EVENT_BUTTON) { if (e[k].number < joy[i].num_buttons) joy[i].button[e[k].number].b = e[k].value; } else if (e[k].type & JS_EVENT_AXIS) { if (e[k].number < TOTAL_JOYSTICK_AXES) set_axis (axis[i][e[k].number], e[k].value); } } } } return 0; } static int joy_save(void) { return 0; } static int joy_load(void) { return 0; } static AL_CONST char *joy_calib_name(int n) { return NULL; } static int joy_calib(int n) { return -1; } static JOYSTICK_DRIVER joystick_linux_analogue = { JOY_TYPE_LINUX_ANALOGUE, empty_string, empty_string, "Linux analogue joystick(s)", joy_init, joy_exit, joy_poll, joy_save, joy_load, joy_calib_name, joy_calib }; #endif /* list the available drivers */ _DRIVER_INFO _linux_joystick_driver_list[] = { #ifdef ALLEGRO_HAVE_LINUX_JOYSTICK_H { JOY_TYPE_LINUX_ANALOGUE, &joystick_linux_analogue, TRUE }, #endif { JOY_TYPE_NONE, &joystick_none, TRUE }, { 0, 0, 0 } }; allegro-4.4.3.1/src/linux/lasyncio.c0000664000175000017500000000627113437077643016221 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Asynchronous I/O helpers for Linux Allegro. * * By Marek Habersack, mangled by George Foot. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #include #include #include static SIGIO_HOOK user_sigio_hook = NULL; #define DEFAULT_ASYNC_IO_MODE ASYNC_BSD unsigned __al_linux_async_io_mode = 0; /* al_linux_install_sigio_hook: * Install a hook to be called from inside the SIGIO signal handler. * It will be invoked AFTER the standard drivers are called. Note * that it's not a very good way to handle SIGIO in your application. * If you really need to use SIGIO, consider updating input events * by hand, i.e. synchronously. Or, preferably, use the select(2) * facility for asynchronous input. * * The previous hook is returned, NULL if none. */ SIGIO_HOOK al_linux_install_sigio_hook (SIGIO_HOOK hook) { SIGIO_HOOK ret = user_sigio_hook; user_sigio_hook = hook; return ret; } /* async_io_event: * A handler for the SIGIO signal. It used to be inelegant, more * optimised for speed, but I changed that because it was causing * problems (mouse motion stopped the keyboard responding). */ static RETSIGTYPE async_io_event(int signo) { if (__al_linux_std_drivers[STD_MOUSE]) __al_linux_std_drivers[STD_MOUSE]->update(); if (__al_linux_std_drivers[STD_KBD]) __al_linux_std_drivers[STD_KBD]->update(); if (user_sigio_hook) user_sigio_hook(SIGIO); return; } /* al_linux_set_async_mode: * Sets the asynchronous I/O mode for the registered standard device * drivers. The async I/O is based on the BSD-compatible SIGIO signal. */ int al_linux_set_async_mode (unsigned type) { static struct sigaction org_sigio; struct sigaction sa; if (type == ASYNC_DEFAULT) type = DEFAULT_ASYNC_IO_MODE; /* Turn off drivers */ __al_linux_async_set_drivers (__al_linux_async_io_mode, 0); /* Shut down the previous mode */ switch (__al_linux_async_io_mode) { case ASYNC_BSD: sigaction (SIGIO, &org_sigio, NULL); break; } __al_linux_async_io_mode = type; /* Initialise the new mode */ switch (__al_linux_async_io_mode) { case ASYNC_BSD: sa.sa_flags = SA_RESTART; sa.sa_handler = async_io_event; sigfillset (&sa.sa_mask); sigaction (SIGIO, &sa, &org_sigio); break; } /* Turn drivers back on again */ __al_linux_async_set_drivers (__al_linux_async_io_mode, 1); return 0; } int al_linux_is_async_mode (void) { return (__al_linux_async_io_mode != ASYNC_OFF); } allegro-4.4.3.1/src/linux/lmseev.c0000664000175000017500000004225113437077643015671 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console internal mouse driver for event interface * (EVDEV). * * By Annie Testes. * * Handles all inputs that fill evdev with informations * about movement and click. * * See readme.txt for copyright information. */ /* linux/input.h also defines KEY_A et al. */ #define ALLEGRO_NO_KEY_DEFINES #include "allegro.h" #ifdef ALLEGRO_HAVE_LINUX_INPUT_H #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #include #include #include #define PREFIX_I "al-evdev INFO: " #define PREFIX_W "al-evdev WARNING: " #define PREFIX_E "al-evdev ERROR: " /* * Tools data */ /* Tool mode * This mode is the behavior the user sees, it is not the way the device * reports the position. * Tools that send relative informations can only be in relative mode, * tools that send absolute informations can be either in absolute mode or in * relative mode */ typedef enum { MODE_RELATIVE, MODE_ABSOLUTE } MODE; typedef struct TOOL { int tool_id; /* One of the BTN_TOOL_... from linux/input.h */ MODE mode; /* Relative or absolute */ } TOOL; static TOOL tools[] = { { BTN_TOOL_MOUSE, MODE_RELATIVE }, { BTN_TOOL_PEN, MODE_ABSOLUTE }, { BTN_TOOL_RUBBER, MODE_ABSOLUTE }, { BTN_TOOL_BRUSH, MODE_ABSOLUTE }, { BTN_TOOL_PENCIL, MODE_ABSOLUTE }, { BTN_TOOL_AIRBRUSH, MODE_ABSOLUTE }, { BTN_TOOL_FINGER, MODE_ABSOLUTE }, { BTN_TOOL_LENS, MODE_ABSOLUTE }, { -1, MODE_ABSOLUTE } /* No tool */ }; /* Default tool, in case the device does not send a tool id */ static TOOL *default_tool = tools + 0; static TOOL *no_tool = tools + (sizeof(tools)/sizeof(tools[0]) - 1); static TOOL *current_tool; /* find_tool: * Returns the tool with id 'tool_id' which is one of the BTN_TOOL_... defined * in linux/input.h. Returns 'default_tool' if not found. */ static TOOL *find_tool(int tool_id) { TOOL *t; for (t=tools; t!=no_tool; t++) { if (t->tool_id == tool_id) return t; } return default_tool; } /* * Pointer axis */ typedef struct AXIS { int in_min; /* For absolute mode */ int in_max; /* For absolute mode */ int out_min; /* For absolute mode */ int out_max; /* For absolute mode */ float speed; /* For set_mouse_speed */ int mickeys; /* For get_mouse_mickeys */ float scale; /* Scale factor, because tablet mice generate more movement than common mice */ int in_abs; /* Current absolute position, used for absolute input, whether the output is absolute or relative */ int out_abs; /* Position on the screen */ } AXIS; #define IN_RANGE(axis) ( (axis).in_max-(axis).in_min+1 ) #define OUT_RANGE(axis) ( (axis).out_max-(axis).out_min+1 ) /* in_to_screen: * maps an input absolute position to a screen position */ static int in_to_screen(AL_CONST AXIS *axis, int v) { return (((v-axis->in_min) * OUT_RANGE(*axis)) / IN_RANGE(*axis)) + axis->out_min; } /* rel_event: * returns the new screen position, given the input relative one. * The tool mode is always relative */ static int rel_event(AXIS *axis, int v) { /* When input only send relative events, the mode is always relative */ int ret = axis->out_abs + v*axis->speed; axis->mickeys += v; axis->in_abs += v; return ret; } /* abs_event: * returns the new screen position, given the input absolute one, * and depending on the tool mode */ static int abs_event(AXIS *axis, MODE mode, int v) { if (mode == MODE_ABSOLUTE) { axis->mickeys = 0; /* No mickeys in absolute mode */ axis->in_abs = v; return in_to_screen(axis, v); } else { /* Input is absolute, but tool is relative */ int value = (v-axis->in_abs)*axis->scale; axis->mickeys += value; axis->in_abs = v; return axis->out_abs + value*axis->speed; } } /* get_axis_value: * returns the input absolute position */ static void get_axis_value(int fd, AXIS *axis, int type) { int abs[5]; int ret = ioctl(fd, EVIOCGABS(type), abs); if (ret>=0) { axis->in_abs = abs[0]; } } /* has_event: * returns true if the device generates the event */ static int has_event(int fd, unsigned short type, unsigned short code) { const unsigned int len = sizeof(unsigned long)*8; const unsigned int max = MAX(EV_MAX, MAX(KEY_MAX, MAX(REL_MAX, MAX(ABS_MAX, MAX(LED_MAX, MAX(SND_MAX, FF_MAX)))))); unsigned long bits[(max+len-1)/len]; if (ioctl(fd, EVIOCGBIT(type, max), bits)) { return (bits[code/len] >> (code%len)) & 1; } return 0; } /* get_num_buttons: * return the number of buttons */ static int get_num_buttons(int fd) { if (has_event(fd, EV_KEY, BTN_MIDDLE)) return 3; if (has_event(fd, EV_KEY, BTN_RIGHT)) return 2; if (has_event(fd, EV_KEY, BTN_MOUSE)) return 1; return 0; /* Not a mouse */ } /* The three axis: horizontal, vertical and wheel */ static AXIS x_axis; static AXIS y_axis; static AXIS z_axis; /* * Previous button status */ static int button_left = 0; static int button_right = 0; static int button_middle = 0; /* * Initialization functions */ /* init_axis: * initialize an AXIS structure, from the device and the config file */ static void init_axis(int fd, AXIS *axis, AL_CONST char *name, AL_CONST char *section, int type) { char tmp1[256]; /* config string */ char tmp2[256]; /* format string */ char tmp3[256]; /* Converted 'name' */ int abs[5]; /* values given by the input */ int config_speed; uszprintf(tmp1, sizeof(tmp1), uconvert_ascii("ev_min_%s", tmp2), uconvert_ascii(name, tmp3)); axis->in_min = get_config_int(section, tmp1, 0); uszprintf(tmp1, sizeof(tmp1), uconvert_ascii("ev_max_%s", tmp2), uconvert_ascii(name, tmp3)); axis->in_max = get_config_int(section, tmp1, 0); uszprintf(tmp1, sizeof(tmp1), uconvert_ascii("ev_abs_to_rel_%s", tmp2), uconvert_ascii(name, tmp3)); config_speed = get_config_int(section, tmp1, 1); if (config_speed<=0) config_speed = 1; axis->scale = 1; /* Ask the input */ if (ioctl(fd, EVIOCGABS(type), abs)>=0) { if (axis->in_min==0) axis->in_min=abs[1]; if (axis->in_max==0) axis->in_max=abs[2]; axis->in_abs = abs[0]; axis->scale = 320.0*config_speed/IN_RANGE(*axis); } if (axis->in_min>axis->in_max) { axis->in_min = axis->in_max = 0; axis->scale = 1; } axis->out_min = 0; axis->out_max = 0; axis->speed = 1; axis->mickeys = 0; } /* init_tablet: * initialize the tools and axis */ static void init_tablet(int fd) { char tmp[256]; char *mouse_str = uconvert_ascii("mouse", tmp); char tmp2[256]; int default_abs = default_tool->mode==MODE_ABSOLUTE; default_abs = get_config_int(mouse_str, uconvert_ascii("ev_absolute", tmp2), default_abs); if (default_abs) { default_tool->mode = MODE_ABSOLUTE; } else { default_tool->mode = MODE_RELATIVE; } init_axis(fd, &x_axis, "x", mouse_str, ABS_X); init_axis(fd, &y_axis, "y", mouse_str, ABS_Y); init_axis(fd, &z_axis, "z", mouse_str, ABS_Z); } /* * Driver structure */ static int processor (unsigned char *buf, int buf_size); static INTERNAL_MOUSE_DRIVER intdrv = { -1, /* device, fill it later */ processor, 3 /* num_buttons */ }; /* * Process input functions */ /* process_key: * process events of type key (button clicks and vicinity events are currently * supported) */ static void process_key(AL_CONST struct input_event *event) { switch (event->code) { /* Buttons click * if event->value is 1 the button has just been pressed * if event->value is 0 the button has just been released */ case BTN_LEFT: /* Mouse */ case BTN_TOUCH: /* Stylus */ button_left = !!event->value; break; case BTN_RIGHT: /* Mouse */ case BTN_STYLUS: /* Stylus */ button_right = !!event->value; break; case BTN_MIDDLE: /* Mouse */ case BTN_STYLUS2: /* Stylus */ button_middle = !!event->value; break; /* Vicinity events * if event->value is 1, the tool enters the tablet vicinity * if event->value is 0, the tool leaves the tablet vicinity */ case BTN_TOOL_MOUSE: case BTN_TOOL_PEN: case BTN_TOOL_RUBBER: case BTN_TOOL_BRUSH: case BTN_TOOL_PENCIL: case BTN_TOOL_AIRBRUSH: case BTN_TOOL_FINGER: case BTN_TOOL_LENS: if (event->value) { current_tool = find_tool(event->code); get_axis_value(intdrv.device, &x_axis, ABS_X); get_axis_value(intdrv.device, &y_axis, ABS_Y); get_axis_value(intdrv.device, &z_axis, ABS_Z); #ifdef ABS_WHEEL /* absent in 2.2.x */ get_axis_value(intdrv.device, &z_axis, ABS_WHEEL); #endif } else { current_tool = no_tool; } break; } } /* process_rel: * process relative events (x, y and z movement are currently supported) */ static void process_rel(AL_CONST struct input_event *event) { /* The device can send a report when there's no tool */ if (current_tool!=no_tool) { switch (event->code) { case REL_X: x_axis.out_abs = rel_event(&x_axis, event->value); break; case REL_Y: y_axis.out_abs = rel_event(&y_axis, event->value); break; #ifdef REL_WHEEL /* absent in 2.2.x */ case REL_WHEEL: #endif case REL_Z: z_axis.out_abs = rel_event(&z_axis, event->value); break; } } } /* process_abs: * process absolute events (x, y and z movement are currently supported) */ static void process_abs(AL_CONST struct input_event *event) { /* The device can send a report when there's no tool */ if (current_tool!=no_tool) { switch (event->code) { case ABS_X: x_axis.out_abs = abs_event(&x_axis, current_tool->mode, event->value); break; case ABS_Y: y_axis.out_abs = abs_event(&y_axis, current_tool->mode, event->value); break; #ifdef ABS_WHEEL /* absent in 2.2.x */ case ABS_WHEEL: #endif case ABS_Z: z_axis.out_abs = abs_event(&z_axis, current_tool->mode, event->value); break; } } } /* processor: * Processes the first packet in the buffer, if any, returning the number * of bytes eaten. */ static int processor (unsigned char *buf, int buf_size) { struct input_event *event; if (buf_size < (int)sizeof(struct input_event)) return 0; /* not enough data */ event = (struct input_event*)buf; switch (event->type) { case EV_KEY: process_key(event); break; case EV_REL: process_rel(event); break; case EV_ABS: process_abs(event); break; } if (current_tool!=no_tool) { x_axis.out_abs = CLAMP(x_axis.out_min, x_axis.out_abs, x_axis.out_max); y_axis.out_abs = CLAMP(y_axis.out_min, y_axis.out_abs, y_axis.out_max); /* There's no range for z */ _mouse_x = x_axis.out_abs; _mouse_y = y_axis.out_abs; _mouse_z = z_axis.out_abs; _mouse_b = button_left + (button_right<<1) + (button_middle<<2); _handle_mouse_input(); } /* Returns the size of the data used */ return sizeof(struct input_event); } /* analyse_data: * Analyses the given data, returning 0 if it is unparsable, nonzero * if there's a reasonable chance that this driver can work with that * data. * Used in the setup code */ static int analyse_data (AL_CONST char *buffer, int size) { struct input_event *event; struct input_event *last=(struct input_event*)(buffer+size); if (size < (int)sizeof(struct input_event)) return 0; /* not enough data */ for (event=(struct input_event*)buffer; eventtype >= EV_MAX) return 0; switch (event->type) { case EV_KEY: if (event->code>=KEY_MAX) return 0; break; case EV_REL: if (event->code>=REL_MAX) return 0; break; case EV_ABS: if (event->code>=ABS_MAX) return 0; break; #ifdef EV_MSC /* absent in 2.2.x */ case EV_MSC: if (event->code>=MSC_MAX) return 0; break; #endif /* Mouse doesn't handle events of these types */ case EV_LED: case EV_SND: case EV_REP: #ifdef EV_FF /* absent in 2.2.x */ case EV_FF: #endif return 0; } } return event==last; } /* open_mouse_device: * Open the specified device file and check that it is a mouse device. * Returns the file descriptor if successful or a negative number on error. */ static int open_mouse_device (const char *device_file) { int fd; fd = open (device_file, O_RDONLY | O_NONBLOCK); if (fd >= 0) { TRACE(PREFIX_I "Opened device %s\n", device_file); /* The device is a mouse if it has a BTN_MOUSE */ if (has_event(fd, EV_KEY, BTN_MOUSE)) { TRACE(PREFIX_I "Device %s was a mouse.\n", device_file); } else { TRACE(PREFIX_I "Device %s was not mouse, closing.\n", device_file); close(fd); fd = -1; } } return fd; } /* mouse_init: * Here we open the mouse device, initialise anything that needs it, * and chain to the framework init routine. */ static int mouse_init (void) { char tmp1[128], tmp2[128]; AL_CONST char *udevice; /* Set the current tool */ current_tool = default_tool; /* Find the device filename */ udevice = get_config_string (uconvert_ascii ("mouse", tmp1), uconvert_ascii ("mouse_device", tmp2), NULL); /* Open mouse device. Devices are cool. */ if (udevice) { TRACE(PREFIX_I "Trying %s device\n", udevice); intdrv.device = open_mouse_device (uconvert_toascii (udevice, tmp1)); if (intdrv.device < 0) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to open %s: %s"), udevice, ustrerror (errno)); return -1; } } else { /* If not specified in the config file, try several /dev/input/event * devices. */ const char *device_name[] = { "/dev/input/event0", "/dev/input/event1", "/dev/input/event2", "/dev/input/event3", NULL }; int i; TRACE(PREFIX_I "Trying /dev/input/event[0-3] devices\n"); for (i=0; device_name[i]; i++) { intdrv.device = open_mouse_device (device_name[i]); if (intdrv.device >= 0) { break; } } if (!device_name[i]) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to open a mouse device: %s"), ustrerror (errno)); return -1; } } intdrv.num_buttons = get_num_buttons(intdrv.device); /* Init the tablet data */ init_tablet(intdrv.device); return __al_linux_mouse_init (&intdrv); } /* mouse_exit: * Chain to the framework, then uninitialise things. */ static void mouse_exit (void) { __al_linux_mouse_exit(); close (intdrv.device); } /* mouse_position: */ static void mouse_position(int x, int y) { DISABLE(); x_axis.out_abs = x; y_axis.out_abs = y; x_axis.mickeys = 0; y_axis.mickeys = 0; _mouse_x = x; _mouse_y = y; ENABLE(); } /* mouse_set_range: */ static void mouse_set_range(int x1, int y1, int x2, int y2) { x_axis.out_min = x1; y_axis.out_min = y1; x_axis.out_max = x2; y_axis.out_max = y2; /* There's no set range for z */ DISABLE(); _mouse_x = CLAMP(x1, _mouse_x, x2); _mouse_y = CLAMP(y1, _mouse_y, y2); ENABLE(); } /* mouse_set_speed: * Number of mickeys to cross the screen horizontally: speed * 320. */ static void mouse_set_speed(int speedx, int speedy) { float scale = 1; if (gfx_driver) scale = gfx_driver->w/320; DISABLE(); x_axis.speed = scale / MAX(1, speedx); y_axis.speed = scale / MAX(1, speedy); x_axis.mickeys = 0; y_axis.mickeys = 0; ENABLE(); } /* mouse_get_mickeys: */ static void mouse_get_mickeys(int *mickeyx, int *mickeyy) { int mx = x_axis.mickeys; int my = y_axis.mickeys; x_axis.mickeys -= mx; y_axis.mickeys -= my; *mickeyx = mx; *mickeyy = my; } MOUSE_DRIVER mousedrv_linux_evdev = { MOUSEDRV_LINUX_EVDEV, empty_string, empty_string, "Linux EVDEV mouse (and tablet)", mouse_init, mouse_exit, NULL, /* poll() */ NULL, /* timer_poll() */ mouse_position, mouse_set_range, mouse_set_speed, mouse_get_mickeys, analyse_data, NULL, /* enable_hardware_cursor */ NULL }; #endif allegro-4.4.3.1/src/linux/lconsole.c0000664000175000017500000002326513437077643016220 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Console control functions for Linux Allegro. * * Originally by Marek Habersack, mangled by George Foot. * * See readme.txt for copyright information. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" #include #include #include #include #include #include #include #include #include /* Console number and open file descriptor */ int __al_linux_vt = -1; int __al_linux_console_fd = -1; int __al_linux_prev_vt = -1; int __al_linux_got_text_message = FALSE; /* Startup termios and working copy */ struct termios __al_linux_startup_termio; struct termios __al_linux_work_termio; /* get_tty: * Compares the inodes of /dev/ttyn (1 <= n <= 24) with the inode of the * passed file, returning whichever it matches, 0 if none, -1 on error. */ static int get_tty (int fd) { char name[16]; int tty; ino_t inode; struct stat st; if (fstat (fd, &st)) return -1; inode = st.st_ino; for (tty = 1; tty <= 24; tty++) { snprintf (name, sizeof(name), "/dev/tty%d", tty); name[sizeof(name)-1] = 0; if (!stat (name, &st) && (inode == st.st_ino)) break; } return (tty <= 24) ? tty : 0; } /* init_console: * Initialises this subsystem. */ static int init_console(void) { char tmp[256]; /* Find our tty's VT number */ __al_linux_vt = get_tty(STDIN_FILENO); if (__al_linux_vt < 0) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error finding our VT: %s"), ustrerror(errno)); return 1; } if (__al_linux_vt != 0) { /* Open our current console */ if ((__al_linux_console_fd = open("/dev/tty", O_RDWR)) < 0) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to open %s: %s"), uconvert_ascii("/dev/tty", tmp), ustrerror(errno)); return 1; } } else { int tty, console_fd, fd, child; unsigned short mask; char tty_name[16]; struct vt_stat vts; /* Now we need to find a VT we can use. It must be readable and * writable by us, if we're not setuid root. VT_OPENQRY itself * isn't too useful because it'll only ever come up with one * suggestion, with no guarrantee that we actually have access * to it. * * At some stage I think this is a candidate for config * file overriding, but for now we'll stat the first N consoles * to see which ones we can write to (hopefully at least one!), * so that we can use that one to do ioctls. We used to use * /dev/console for that purpose but it looks like it's not * always writable by enough people. * * Having found and opened a writable device, we query the state * of the first sixteen (fifteen really) consoles, and try * opening each unused one in turn. */ if ((console_fd = open ("/dev/console", O_WRONLY)) < 0) { int n; uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, uconvert_ascii("%s /dev/console: %s", tmp), get_config_text("Unable to open"), ustrerror (errno)); /* Try some ttys instead... */ for (n = 1; n <= 24; n++) { snprintf (tty_name, sizeof(tty_name), "/dev/tty%d", n); tty_name[sizeof(tty_name)-1] = 0; if ((console_fd = open (tty_name, O_WRONLY)) >= 0) break; } if (n > 24) return 1; /* leave the error message about /dev/console */ } /* Get the state of the console -- in particular, the free VT field */ if (ioctl (console_fd, VT_GETSTATE, &vts)) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, uconvert_ascii("VT_GETSTATE: %s", tmp), ustrerror (errno)); close (console_fd); return 1; } __al_linux_prev_vt = vts.v_active; /* We attempt to set our euid to 0; if we were run with euid 0 to * start with, we'll be able to do this now. Otherwise, we'll just * ignore the error returned since it might not be a problem if the * ttys we look at are owned by the user running the program. */ seteuid(0); /* tty0 is not really a console, so start counting at 2. */ fd = -1; for (tty = 1, mask = 2; mask; tty++, mask <<= 1) { if (!(vts.v_state & mask)) { snprintf (tty_name, sizeof(tty_name), "/dev/tty%d", tty); tty_name[sizeof(tty_name)-1] = 0; if ((fd = open (tty_name, O_RDWR)) != -1) { close (fd); break; } } } seteuid (getuid()); if (!mask) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to find a usable VT")); close (console_fd); return 1; } /* OK, now fork into the background, detach from the current console, * and attach to the new one. */ child = fork(); if (child < 0) { /* fork failed */ uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, uconvert_ascii ("fork: %s", tmp), ustrerror (errno)); close (console_fd); return 1; } if (child) { /* We're the parent -- write a note to the user saying where the * app went, then quit */ fprintf (stderr, "Allegro application is running on VT %d\n", tty); exit (0); } /* We're the child. Detach from our controlling terminal, and start * a new session. */ close (console_fd); ioctl (0, TIOCNOTTY, 0); setsid(); /* Open the new one again. It becomes our ctty, because we started a * new session above. */ seteuid(0); fd = open (tty_name, O_RDWR); seteuid(getuid()); if (fd == -1) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to reopen new console")); return 1; } /* Try to switch to it -- should succeed, since it's our ctty */ ioctl (fd, VT_ACTIVATE, tty); __al_linux_vt = tty; __al_linux_console_fd = fd; /* Check we can reliably wait until we have the display */ if (__al_linux_wait_for_display()) { close (fd); ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("VT_WAITACTIVE failure")); return 1; } /* dup2 it to stdin, stdout and stderr if necessary */ if (isatty(0)) dup2 (fd, 0); if (isatty(1)) dup2 (fd, 1); if (isatty(2)) dup2 (fd, 2); } /* Get termio settings and make a working copy */ tcgetattr(__al_linux_console_fd, &__al_linux_startup_termio); __al_linux_work_termio = __al_linux_startup_termio; return 0; } /* done_console * Undo `init_console'. */ static int done_console (void) { char msg[256]; int ret; if (__al_linux_prev_vt >= 0) { if (__al_linux_got_text_message) { snprintf(msg, sizeof(msg), "\nProgram finished: press %s+F%d to switch back to the previous console\n", (__al_linux_prev_vt > 12) ? "AltGR" : "Alt", __al_linux_prev_vt%12); msg[sizeof(msg)-1] = 0; do { ret = write(STDERR_FILENO, msg, strlen(msg)); if ((ret < 0) && (errno != EINTR)) break; } while (ret < (int)strlen(msg)); __al_linux_got_text_message = FALSE; } else ioctl (__al_linux_console_fd, VT_ACTIVATE, __al_linux_prev_vt); __al_linux_prev_vt = -1; } tcsetattr (__al_linux_console_fd, TCSANOW, &__al_linux_startup_termio); close (__al_linux_console_fd); __al_linux_console_fd = -1; return 0; } static int console_users = 0; /* __al_linux_use_console: * Init Linux console if not initialized yet. */ int __al_linux_use_console(void) { console_users++; if (console_users > 1) return 0; if (init_console()) { console_users--; return 1; } /* Initialise the console switching system */ set_display_switch_mode (SWITCH_PAUSE); return __al_linux_init_vtswitch(); } /* __al_linux_leave_console: * Close Linux console if no driver uses it any more. */ int __al_linux_leave_console(void) { ASSERT (console_users > 0); console_users--; if (console_users > 0) return 0; /* shut down the console switching system */ if (__al_linux_done_vtswitch()) return 1; if (done_console()) return 1; return 0; } static int graphics_mode = 0; /* __al_linux_console_graphics: * Puts the Linux console into graphics mode. */ int __al_linux_console_graphics (void) { if (__al_linux_use_console()) return 1; if (graphics_mode) return 0; /* shouldn't happen */ __al_linux_display_switch_lock(TRUE, TRUE); ioctl(__al_linux_console_fd, KDSETMODE, KD_GRAPHICS); __al_linux_wait_for_display(); graphics_mode = 1; return 0; } /* __al_linux_console_text: * Returns the console to text mode. */ int __al_linux_console_text (void) { int ret; if (!graphics_mode) return 0; /* shouldn't happen */ ioctl(__al_linux_console_fd, KDSETMODE, KD_TEXT); do { ret = write(__al_linux_console_fd, "\e[H\e[J\e[0m", 10); if ((ret < 0) && (errno != EINTR)) break; } while (ret < 10); graphics_mode = 0; __al_linux_display_switch_lock(FALSE, FALSE); __al_linux_leave_console(); return 0; } /* __al_linux_wait_for_display: * Waits until we have the display. */ int __al_linux_wait_for_display (void) { int x; do { x = ioctl (__al_linux_console_fd, VT_WAITACTIVE, __al_linux_vt); } while (x && errno != EINTR); return x; } allegro-4.4.3.1/src/linux/lmseps2.c0000664000175000017500000001525013437077643015762 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Linux console internal mouse driver for PS/2. * * By George Foot. * * See readme.txt for copyright information. */ #include #include #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include "linalleg.h" static int intellimouse; static int packet_size; /* processor: * Processes the first packet in the buffer, if any, returning the number * of bytes eaten. * * PS/2 mouse protocol is pretty simple; packets consist of three bytes, * one header byte and two data bytes. In the header, the bottom three * bits show the current button state. The next bit should always be * set, but apparently some mice don't do this. The next two bits are * the X and Y sign bits, and the last two are the X and Y overflow * flags. The two data bytes are the X and Y deltas; prepend the * corresponding sign bit to get a nine-bit two's complement number. * * Finding the header byte can be tricky in you lose sync; bit 3 isn't * that useful, not only because some mice don't set it, but also * because a data byte could have it set. The overflow bits are very * rarely set, so we just test for these being zero. Of course the * data bytes can have zeros here too, but as soon as you move the * mouse down or left the data bytes become negative and have ones * here instead. */ static int processor (unsigned char *buf, int buf_size) { int r, l, m, x, y, z; if (buf_size < packet_size) return 0; /* not enough data, spit it out for now */ /* if data is invalid, return no motion and all buttons released */ if (intellimouse) { if ((buf[0] & 0xc8) != 0x08) return 1; /* invalid byte, eat it */ } else { if ((buf[0] & 0xc0) != 0x00) return 1; /* invalid byte, eat it */ } /* data is valid, process it */ l = !!(buf[0] & 1); r = !!(buf[0] & 2); m = !!(buf[0] & 4); x = buf[1]; y = buf[2]; if (buf[0] & 0x10) x -= 256; if (buf[0] & 0x20) y -= 256; if (intellimouse) { z = buf[3] & 0xf; if (z) z = (z-7) >> 3; } else z = 0; __al_linux_mouse_handler(x, y, z, l+(r<<1)+(m<<2)); return packet_size; /* yum */ } /* analyse_data: * Analyses the given data, returning 0 if it is unparsable, nonzero * if there's a reasonable chance that this driver can work with that * data. */ static int analyse_data (AL_CONST char *buffer, int size) { int pos = 0; int packets = 0, errors = 0; int step = 0; for (pos = 0; pos < size; pos++) switch (step) { case 3: packets++; step = 0; case 0: if (buffer[pos] & 0xC0) { errors++; } else { step++; } break; case 1: case 2: step++; break; } return (errors <= 5) || (errors < size / 20); /* 5% error allowance */ } static INTERNAL_MOUSE_DRIVER intdrv = { -1, processor, 3 }; /* sync_mouse: * To find the start of a packet, we just read all the data that's * waiting. This isn't a particularly good way, obviously. :) */ static void sync_mouse (int fd) { fd_set set; int result; struct timeval tv; char bitbucket; do { FD_ZERO (&set); FD_SET (fd, &set); tv.tv_sec = tv.tv_usec = 0; result = select (FD_SETSIZE, &set, NULL, NULL, &tv); if (result > 0) read (fd, &bitbucket, 1); } while (result > 0); } /* wakeup_im: * Intellimouse needs some special initialisation. */ static void wakeup_im (int fd) { unsigned char init[] = { 243, 200, 243, 100, 243, 80 }; int ret; do { ret = write (fd, init, sizeof (init)); if ((ret < 0) && (errno != EINTR)) break; } while (ret < (int)sizeof (init)); } /* mouse_init: * Here we open the mouse device, initialise anything that needs it, * and chain to the framework init routine. */ static int mouse_init (void) { char tmp1[128], tmp2[128]; AL_CONST char *udevice; int flags; static AL_CONST char * AL_CONST default_devices[] = { "/dev/mouse", "/dev/input/mice", }; /* Find the device filename */ udevice = get_config_string (uconvert_ascii ("mouse", tmp1), uconvert_ascii ("mouse_device", tmp2), NULL); /* Open mouse device. Devices are cool. */ flags = O_NONBLOCK | (intellimouse ? O_RDWR : O_RDONLY); if (udevice) { intdrv.device = open (uconvert_toascii (udevice, tmp1), flags); } else { size_t n; for (n = 0; n < sizeof(default_devices) / sizeof(default_devices[0]); n++) { intdrv.device = open (default_devices[n], flags); if (intdrv.device >= 0) break; } } if (intdrv.device < 0) { uszprintf (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to open %s: %s"), udevice ? udevice : get_config_text("one of the default mice devices"), ustrerror (errno)); return -1; } /* Put Intellimouse into wheel mode */ if (intellimouse) wakeup_im (intdrv.device); /* Discard any garbage, so the next thing we read is a packet header */ sync_mouse (intdrv.device); return __al_linux_mouse_init (&intdrv); } /* ps2_mouse_init: * Plain PS/2 mouse init. */ static int ps2_mouse_init (void) { intellimouse = FALSE; packet_size = 3; return mouse_init (); } /* ps2i_mouse_init: * PS/2 Intellimouse init. */ static int ips2_mouse_init (void) { intellimouse = TRUE; packet_size = 4; return mouse_init (); } /* mouse_exit: * Chain to the framework, then uninitialise things. */ static void mouse_exit (void) { __al_linux_mouse_exit(); close (intdrv.device); } MOUSE_DRIVER mousedrv_linux_ps2 = { MOUSEDRV_LINUX_PS2, empty_string, empty_string, "Linux PS/2 mouse", ps2_mouse_init, mouse_exit, NULL, /* poll() */ NULL, /* timer_poll() */ __al_linux_mouse_position, __al_linux_mouse_set_range, __al_linux_mouse_set_speed, __al_linux_mouse_get_mickeys, analyse_data, NULL, /* enable_hardware_cursor */ NULL }; MOUSE_DRIVER mousedrv_linux_ips2 = { MOUSEDRV_LINUX_IPS2, empty_string, empty_string, "Linux PS/2 Intellimouse", ips2_mouse_init, mouse_exit, NULL, /* poll() */ NULL, /* timer_poll() */ __al_linux_mouse_position, __al_linux_mouse_set_range, __al_linux_mouse_set_speed, __al_linux_mouse_get_mickeys, analyse_data, NULL, /* enable_hardware_cursor */ NULL }; allegro-4.4.3.1/src/lbm.c0000664000175000017500000001772513437077643014021 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * LBM reader. * * By Adrian Oboroc. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* load_lbm: * Loads IFF ILBM/PBM files with up to 8 bits per pixel, returning * a bitmap structure and storing the palette data in the specified * palette (this should be an array of at least 256 RGB structures). */ BITMAP *load_lbm(AL_CONST char *filename, RGB *pal) { #define IFF_FORM 0x4D524F46 /* 'FORM' - IFF FORM structure */ #define IFF_ILBM 0x4D424C49 /* 'ILBM' - interleaved bitmap */ #define IFF_PBM 0x204D4250 /* 'PBM ' - new DP2e format */ #define IFF_BMHD 0x44484D42 /* 'BMHD' - bitmap header */ #define IFF_CMAP 0x50414D43 /* 'CMAP' - color map (palette) */ #define IFF_BODY 0x59444F42 /* 'BODY' - bitmap data */ PACKFILE *f; PALETTE tmppal; BITMAP *b = NULL; int w, h, i, x, y, bpl, ppl, pbm_mode; char ch, cmp_type, bit_plane, color_depth; unsigned char uc, check_flags, bit_mask, *line_buf; long data_id, len, l; int dest_depth = _color_load_depth(8, FALSE); ASSERT(filename); if (!pal) pal = tmppal; f = pack_fopen(filename, F_READ); if (!f) return NULL; data_id = pack_igetl(f); /* read file header */ if (data_id != IFF_FORM) { /* check for 'FORM' id */ pack_fclose(f); return NULL; } pack_igetl(f); /* skip FORM length */ data_id = pack_igetl(f); /* read id */ /* check image type ('ILBM' or 'PBM ') */ if ((data_id != IFF_ILBM) && (data_id != IFF_PBM)) { pack_fclose(f); return NULL; } pbm_mode = data_id == IFF_PBM; data_id = pack_igetl(f); /* read id */ if (data_id != IFF_BMHD) { /* check for header */ pack_fclose(f); return NULL; } len = pack_mgetl(f); /* read header length */ if (len != 20) { /* check, if it is right */ pack_fclose(f); return NULL; } w = pack_mgetw(f); /* read screen width */ h = pack_mgetw(f); /* read screen height */ pack_igetw(f); /* skip initial x position */ pack_igetw(f); /* skip initial y position */ color_depth = pack_getc(f); /* get image depth */ if (color_depth > 8) { pack_fclose(f); return NULL; } pack_getc(f); /* skip masking type */ cmp_type = pack_getc(f); /* get compression type */ if ((cmp_type != 0) && (cmp_type != 1)) { pack_fclose(f); return NULL; } *allegro_errno = 0; pack_getc(f); /* skip unused field */ pack_igetw(f); /* skip transparent color */ pack_getc(f); /* skip x aspect ratio */ pack_getc(f); /* skip y aspect ratio */ pack_igetw(f); /* skip default page width */ pack_igetw(f); /* skip default page height */ check_flags = 0; do { /* We'll use cycle to skip possible junk */ /* chunks: ANNO, CAMG, GRAB, DEST, TEXT etc. */ data_id = pack_igetl(f); switch(data_id) { case IFF_CMAP: memset(pal, 0, 256 * 3); len = pack_mgetl(f) / 3; for (i=0; i> 2; pal[i].g = pack_getc(f) >> 2; pal[i].b = pack_getc(f) >> 2; } check_flags |= 1; /* flag "palette read" */ break; case IFF_BODY: pack_igetl(f); /* skip BODY size */ b = create_bitmap_ex(8, w, h); if (!b) { pack_fclose(f); return NULL; } memset(b->line[0], 0, w * h); if (pbm_mode) bpl = w; else { bpl = w >> 3; /* calc bytes per line */ if (w & 7) /* for finish bits */ bpl++; } if (bpl & 1) /* alignment */ bpl++; line_buf = _AL_MALLOC_ATOMIC(bpl); if (!line_buf) { pack_fclose(f); return NULL; } if (pbm_mode) { for (y = 0; y < h; y++) { if (cmp_type) { i = 0; while (i < bpl) { uc = pack_getc(f); if (uc < 128) { uc++; pack_fread(&line_buf[i], uc, f); i += uc; } else if (uc > 128) { uc = 257 - uc; ch = pack_getc(f); memset(&line_buf[i], ch, uc); i += uc; } /* 128 (0x80) means NOP - no operation */ } } else /* pure theoretical situation */ pack_fread(line_buf, bpl, f); memcpy(b->line[y], line_buf, bpl); } } else { for (y = 0; y < h; y++) { for (bit_plane = 0; bit_plane < color_depth; bit_plane++) { if (cmp_type) { i = 0; while (i < bpl) { uc = pack_getc(f); if (uc < 128) { uc++; pack_fread(&line_buf[i], uc, f); i += uc; } else if (uc > 128) { uc = 257 - uc; ch = pack_getc(f); memset(&line_buf[i], ch, uc); i += uc; } /* 128 (0x80) means NOP - no operation */ } } else pack_fread(line_buf, bpl, f); bit_mask = 1 << bit_plane; ppl = bpl; /* for all pixel blocks */ if (w & 7) /* may be, except the */ ppl--; /* the last */ for (x = 0; x < ppl; x++) { if (line_buf[x] & 128) b->line[y][x * 8] |= bit_mask; if (line_buf[x] & 64) b->line[y][x * 8 + 1] |= bit_mask; if (line_buf[x] & 32) b->line[y][x * 8 + 2] |= bit_mask; if (line_buf[x] & 16) b->line[y][x * 8 + 3] |= bit_mask; if (line_buf[x] & 8) b->line[y][x * 8 + 4] |= bit_mask; if (line_buf[x] & 4) b->line[y][x * 8 + 5] |= bit_mask; if (line_buf[x] & 2) b->line[y][x * 8 + 6] |= bit_mask; if (line_buf[x] & 1) b->line[y][x * 8 + 7] |= bit_mask; } /* last pixel block */ if (w & 7) { x = bpl - 1; /* no necessary to check if (w & 7) > 0 in */ /* first condition, because (w & 7) != 0 */ if (line_buf[x] & 128) b->line[y][x * 8] |= bit_mask; if ((line_buf[x] & 64) && ((w & 7) > 1)) b->line[y][x * 8 + 1] |= bit_mask; if ((line_buf[x] & 32) && ((w & 7) > 2)) b->line[y][x * 8 + 2] |= bit_mask; if ((line_buf[x] & 16) && ((w & 7) > 3)) b->line[y][x * 8 + 3] |= bit_mask; if ((line_buf[x] & 8) && ((w & 7) > 4)) b->line[y][x * 8 + 4] |= bit_mask; if ((line_buf[x] & 4) && ((w & 7) > 5)) b->line[y][x * 8 + 5] |= bit_mask; if ((line_buf[x] & 2) && ((w & 7) > 6)) b->line[y][x * 8 + 6] |= bit_mask; if ((line_buf[x] & 1) && ((w & 7) > 7)) b->line[y][x * 8 + 7] |= bit_mask; } } } } _AL_FREE(line_buf); check_flags |= 2; /* flag "bitmap read" */ break; default: /* skip useless chunks */ len = pack_mgetl(f); if (len & 1) len++; for (l=0; l < (len >> 1); l++) pack_igetw(f); } /* Exit from loop if we are at the end of file, */ /* or if we loaded both bitmap and palette */ } while ((check_flags != 3) && (!pack_feof(f))); pack_fclose(f); if (check_flags != 3) { if (check_flags & 2) destroy_bitmap(b); return FALSE; } if (*allegro_errno) { destroy_bitmap(b); return FALSE; } if (dest_depth != 8) b = _fixup_loaded_bitmap(b, pal, dest_depth); return b; } allegro-4.4.3.1/src/drvlist.c0000664000175000017500000000541213437077643014724 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Dynamic driver list helpers. * * By Peter Wang. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* count_drivers: * Returns the number of drivers in a list, not including the sentinel. */ static int count_drivers(_DRIVER_INFO *drvlist) { _DRIVER_INFO *start = drvlist; while (drvlist->driver) drvlist++; return drvlist - start; } /* _create_driver_list: * Creates a new driver list and returns it. Returns NULL on error. */ _DRIVER_INFO *_create_driver_list(void) { _DRIVER_INFO *drv; drv = _AL_MALLOC(sizeof(struct _DRIVER_INFO)); if (drv) { drv->id = 0; drv->driver = NULL; drv->autodetect = FALSE; } return drv; } /* _destroy_driver_list: * Frees a driver list. */ void _destroy_driver_list(_DRIVER_INFO *drvlist) { _AL_FREE(drvlist); } /* _driver_list_append_driver: * Adds a driver to the end of a driver list. */ void _driver_list_append_driver(_DRIVER_INFO **drvlist, int id, void *driver, int autodetect) { _DRIVER_INFO *drv; int c; ASSERT(*drvlist); c = count_drivers(*drvlist); drv = _AL_REALLOC(*drvlist, sizeof(_DRIVER_INFO) * (c+2)); if (!drv) return; drv[c].id = id; drv[c].driver = driver; drv[c].autodetect = autodetect; drv[c+1].id = 0; drv[c+1].driver = NULL; drv[c+1].autodetect = FALSE; *drvlist = drv; } /* _driver_list_prepend_driver: * Adds a driver to the start of a driver list. */ void _driver_list_prepend_driver(_DRIVER_INFO **drvlist, int id, void *driver, int autodetect) { _DRIVER_INFO *drv; int c; ASSERT(*drvlist); c = count_drivers(*drvlist); drv = _AL_REALLOC(*drvlist, sizeof(_DRIVER_INFO) * (c+2)); if (!drv) return; memmove(drv+1, drv, sizeof(_DRIVER_INFO) * (c+1)); drv[0].id = id; drv[0].driver = driver; drv[0].autodetect = autodetect; *drvlist = drv; } /* _driver_list_append_list: * Add drivers from one list to another list. */ void _driver_list_append_list(_DRIVER_INFO **drvlist, _DRIVER_INFO *srclist) { ASSERT(*drvlist); ASSERT(srclist); while (srclist->driver) { _driver_list_append_driver(drvlist, srclist->id, srclist->driver, srclist->autodetect); srclist++; } } allegro-4.4.3.1/src/unicode.c0000664000175000017500000020002013437077643014653 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * String handling functions (UTF-8, Unicode, ASCII, etc). * * By Shawn Hargreaves. * * Case conversion functions improved by Ole Laursen. * * ustrrchr() and usprintf() improvements by Sven Sandberg. * * Peter Cech added some non-ASCII characters to uissspace(). * * size-aware (aka 'z') functions added by Eric Botcazou. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" /* this is a valid encoding in any of the supported formats */ char empty_string[] = EMPTY_STRING; /* ascii_getc: * Reads a character from an ASCII string. */ static int ascii_getc(AL_CONST char *s) { return *((unsigned char *)s); } /* ascii_getx: * Reads a character from an ASCII string, advancing the pointer position. */ static int ascii_getx(char **s) { return *((unsigned char *)((*s)++)); } /* ascii_setc: * Sets a character in an ASCII string. */ static int ascii_setc(char *s, int c) { *s = c; return 1; } /* ascii_width: * Returns the width of an ASCII character. */ static int ascii_width(AL_CONST char *s) { return 1; } /* ascii_cwidth: * Returns the width of an ASCII character. */ static int ascii_cwidth(int c) { return 1; } /* ascii_isok: * Checks whether this character can be encoded in 8-bit ASCII format. */ static int ascii_isok(int c) { return ((c >= 0) && (c <= 255)); } /* lookup table for implementing 8-bit codepage modes */ static unsigned short _codepage_table[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, }; /* this default table reduces Latin-1 and Extended-A characters to 7 bits */ static unsigned short _codepage_extras[] = { 0xA1, '!', 0xA2, 'c', 0xA3, '#', 0xB5, 'u', 0xBF, '?', 0xC0, 'A', 0xC1, 'A', 0xC2, 'A', 0xC3, 'A', 0xC4, 'A', 0xC5, 'A', 0xC6, 'A', 0xC7, 'C', 0xC8, 'E', 0xC9, 'E', 0xCA, 'E', 0xCB, 'E', 0xCC, 'I', 0xCD, 'I', 0xCE, 'I', 0xCF, 'I', 0xD0, 'D', 0xD1, 'N', 0xD2, 'O', 0xD3, 'O', 0xD4, 'O', 0xD5, 'O', 0xD6, 'O', 0xD7, 'X', 0xD8, '0', 0xD9, 'U', 0xDA, 'U', 0xDB, 'U', 0xDC, 'U', 0xDD, 'Y', 0xDE, 'P', 0xDF, 'S', 0xE0, 'a', 0xE1, 'a', 0xE2, 'a', 0xE3, 'a', 0xE4, 'a', 0xE5, 'a', 0xE6, 'a', 0xE7, 'c', 0xE8, 'e', 0xE9, 'e', 0xEA, 'e', 0xEB, 'e', 0xEC, 'i', 0xED, 'i', 0xEE, 'i', 0xEF, 'i', 0xF0, 'o', 0xF1, 'n', 0xF2, 'o', 0xF3, 'o', 0xF4, 'o', 0xF5, 'o', 0xF6, 'o', 0xF8, 'o', 0xF9, 'u', 0xFA, 'u', 0xFB, 'u', 0xFC, 'u', 0xFD, 'y', 0xFE, 'p', 0xFF, 'y', 0x100, 'A', 0x101, 'a', 0x102, 'A', 0x103, 'a', 0x104, 'A', 0x105, 'a', 0x106, 'C', 0x107, 'c', 0x108, 'C', 0x109, 'c', 0x10a, 'C', 0x10b, 'c', 0x10c, 'C', 0x10d, 'c', 0x10e, 'D', 0x10f, 'd', 0x110, 'D', 0x111, 'd', 0x112, 'E', 0x113, 'e', 0x114, 'E', 0x115, 'e', 0x116, 'E', 0x117, 'e', 0x118, 'E', 0x119, 'e', 0x11a, 'E', 0x11b, 'e', 0x11c, 'G', 0x11d, 'g', 0x11e, 'G', 0x11f, 'g', 0x120, 'G', 0x121, 'g', 0x122, 'G', 0x123, 'g', 0x124, 'H', 0x125, 'h', 0x126, 'H', 0x127, 'h', 0x128, 'I', 0x129, 'i', 0x12a, 'I', 0x12b, 'i', 0x12c, 'I', 0x12d, 'i', 0x12e, 'I', 0x12f, 'i', 0x130, 'I', 0x131, 'i', 0x134, 'J', 0x135, 'j', 0x136, 'K', 0x137, 'k', 0x138, 'K', 0x139, 'L', 0x13a, 'l', 0x13b, 'L', 0x13c, 'l', 0x13d, 'L', 0x13e, 'l', 0x13f, 'L', 0x140, 'l', 0x141, 'L', 0x142, 'l', 0x143, 'N', 0x144, 'n', 0x145, 'N', 0x146, 'n', 0x147, 'N', 0x148, 'n', 0x149, 'n', 0x14a, 'N', 0x14b, 'n', 0x14c, 'O', 0x14d, 'o', 0x14e, 'O', 0x14f, 'o', 0x150, 'O', 0x151, 'o', 0x154, 'R', 0x155, 'r', 0x156, 'R', 0x157, 'r', 0x158, 'R', 0x159, 'r', 0x15a, 'S', 0x15b, 's', 0x15c, 'S', 0x15d, 's', 0x15e, 'S', 0x15f, 's', 0x160, 'S', 0x161, 's', 0x162, 'T', 0x163, 't', 0x164, 'T', 0x165, 't', 0x166, 'T', 0x167, 't', 0x168, 'U', 0x169, 'u', 0x16a, 'U', 0x16b, 'u', 0x16c, 'U', 0x16d, 'u', 0x16e, 'U', 0x16f, 'u', 0x170, 'U', 0x171, 'u', 0x172, 'U', 0x173, 'u', 0x174, 'W', 0x175, 'w', 0x176, 'Y', 0x177, 'y', 0x178, 'y', 0x179, 'Z', 0x17a, 'z', 0x17b, 'Z', 0x17c, 'z', 0x17d, 'Z', 0x17e, 'z', 0 }; /* access via pointers so they can be changed by the user */ static AL_CONST unsigned short *codepage_table = _codepage_table; static AL_CONST unsigned short *codepage_extras = _codepage_extras; /* ascii_cp_getc: * Reads a character from an ASCII codepage string. */ static int ascii_cp_getc(AL_CONST char *s) { return codepage_table[*((unsigned char *)s)]; } /* ascii_cp_getx: * Reads from an ASCII codepage string, advancing pointer position. */ static int ascii_cp_getx(char **s) { return codepage_table[*((unsigned char *)((*s)++))]; } /* ascii_cp_setc: * Sets a character in an ASCII codepage string. */ static int ascii_cp_setc(char *s, int c) { int i; for (i=0; i<256; i++) { if (codepage_table[i] == c) { *s = i; return 1; } } if (codepage_extras) { for (i=0; codepage_extras[i]; i+=2) { if (codepage_extras[i] == c) { *s = codepage_extras[i+1]; return 1; } } } *s = '^'; return 1; } /* ascii_cp_isok: * Checks whether this character can be encoded in ASCII codepage format. */ static int ascii_cp_isok(int c) { int i; for (i=0; i<256; i++) { if (codepage_table[i] == c) return TRUE; } if (codepage_extras) { for (i=0; codepage_extras[i]; i+=2) { if (codepage_extras[i] == c) return TRUE; } } return FALSE; } /* unicode_getc: * Reads a character from a Unicode string. */ static int unicode_getc(AL_CONST char *s) { return *((unsigned short *)s); } /* unicode_getx: * Reads a character from a Unicode string, advancing the pointer position. */ static int unicode_getx(char **s) { int c = *((unsigned short *)(*s)); (*s) += sizeof(unsigned short); return c; } /* unicode_setc: * Sets a character in a Unicode string. */ static int unicode_setc(char *s, int c) { *((unsigned short *)s) = c; return sizeof(unsigned short); } /* unicode_width: * Returns the width of a Unicode character. */ static int unicode_width(AL_CONST char *s) { return sizeof(unsigned short); } /* unicode_cwidth: * Returns the width of a Unicode character. */ static int unicode_cwidth(int c) { return sizeof(unsigned short); } /* unicode_isok: * Checks whether this character can be encoded in 16-bit Unicode format. */ static int unicode_isok(int c) { return ((c >= 0) && (c <= 65535)); } /* utf8_getc: * Reads a character from a UTF-8 string. */ static int utf8_getc(AL_CONST char *s) { int c = *((unsigned char *)(s++)); int n, t; if (c & 0x80) { n = 1; while (c & (0x80>>n)) n++; c &= (1<<(8-n))-1; while (--n > 0) { t = *((unsigned char *)(s++)); if ((!(t&0x80)) || (t&0x40)) return '^'; c = (c<<6) | (t&0x3F); } } return c; } /* utf8_getx: * Reads a character from a UTF-8 string, advancing the pointer position. */ static int utf8_getx(char **s) { int c = *((unsigned char *)((*s)++)); int n, t; if (c & 0x80) { n = 1; while (c & (0x80>>n)) n++; c &= (1<<(8-n))-1; while (--n > 0) { t = *((unsigned char *)((*s)++)); if ((!(t&0x80)) || (t&0x40)) { (*s)--; return '^'; } c = (c<<6) | (t&0x3F); } } return c; } /* utf8_setc: * Sets a character in a UTF-8 string. */ static int utf8_setc(char *s, int c) { int size, bits, b, i; if (c < 128) { *s = c; return 1; } bits = 7; while (c >= (1<>b; for (i=0; i>i); for (i=1; i>b)&0x3F); } return size; } /* utf8_width: * Returns the width of a UTF-8 character. */ static int utf8_width(AL_CONST char *s) { int c = *((unsigned char *)s); int n = 1; if (c & 0x80) { while (c & (0x80>>n)) n++; } return n; } /* utf8_cwidth: * Returns the width of a UTF-8 character. */ static int utf8_cwidth(int c) { int size, bits, b; if (c < 128) return 1; bits = 7; while (c >= (1<id; ugetc = info->u_getc; ugetx = (int (*)(char **)) info->u_getx; ugetxc = (int (*)(AL_CONST char **)) info->u_getx; usetc = info->u_setc; uwidth = info->u_width; ucwidth = info->u_cwidth; uisok = info->u_isok; } } /* get_uformat: * Returns the current text encoding format. */ int get_uformat(void) { return utype; } /* register_uformat: * Allows the user to hook in custom routines for supporting a new string * encoding format. */ void register_uformat(int type, int (*ugetc)(AL_CONST char *s), int (*ugetx)(char **s), int (*usetc)(char *s, int c), int (*uwidth)(AL_CONST char *s), int (*ucwidth)(int c), int (*uisok)(int c), int uwidth_max) { UTYPE_INFO *info = _find_utype(type); if (!info) info = _find_utype(0); if (info) { info->id = type; info->u_getc = ugetc; info->u_getx = ugetx; info->u_setc = usetc; info->u_width = uwidth; info->u_cwidth = ucwidth; info->u_isok = uisok; info->u_width_max = uwidth_max; } } /* set_ucodepage: * Sets lookup table data for the codepage conversion functions. */ void set_ucodepage(AL_CONST unsigned short *table, AL_CONST unsigned short *extras) { ASSERT(table); codepage_table = table; codepage_extras = extras; } /* need_uconvert: * Decides whether a conversion is required to make this string be in the * new type. No conversion will be needed if both types are the same, or * when going from ASCII <-> UTF8 where the data is 7-bit clean. */ int need_uconvert(AL_CONST char *s, int type, int newtype) { int c; ASSERT(s); if (type == U_CURRENT) type = utype; if (newtype == U_CURRENT) newtype = utype; if (type == newtype) return FALSE; if (((type == U_ASCII) || (type == U_UTF8)) && ((newtype == U_ASCII) || (newtype == U_UTF8))) { do { c = *((unsigned char *)(s++)); if (!c) return FALSE; } while (c <= 127); } return TRUE; } /* uconvert_size: * Returns the number of bytes this string will occupy when converted to * the specified type. */ int uconvert_size(AL_CONST char *s, int type, int newtype) { UTYPE_INFO *info, *outfo; int size = 0; int c; ASSERT(s); info = _find_utype(type); if (!info) return 0; outfo = _find_utype(newtype); if (!outfo) return 0; size = 0; while ((c = info->u_getx((char **)&s)) != 0) size += outfo->u_cwidth(c); return size + outfo->u_cwidth(0); } /* do_uconvert: * Converts a string from one format to another. */ void do_uconvert(AL_CONST char *s, int type, char *buf, int newtype, int size) { UTYPE_INFO *info, *outfo; int pos = 0; int c; ASSERT(s); ASSERT(buf); ASSERT(size > 0); info = _find_utype(type); if (!info) return; outfo = _find_utype(newtype); if (!outfo) return; size -= outfo->u_cwidth(0); ASSERT(size >= 0); while ((c = info->u_getx((char**)&s)) != 0) { if (!outfo->u_isok(c)) c = '^'; size -= outfo->u_cwidth(c); if (size < 0) break; pos += outfo->u_setc(buf+pos, c); } outfo->u_setc(buf+pos, 0); } /* uconvert: * Higher level version of do_uconvert(). This routine is intelligent * enough to just return a copy of the input string if no conversion * is required, and to use an internal static buffer if no user buffer * is provided. */ char *uconvert(AL_CONST char *s, int type, char *buf, int newtype, int size) { static char static_buf[1024]; ASSERT(s); ASSERT(size >= 0); if (!need_uconvert(s, type, newtype)) return (char *)s; if (!buf) { buf = static_buf; size = sizeof(static_buf); } do_uconvert(s, type, buf, newtype, size); return buf; } /* uoffset: * Returns the offset in bytes from the start of the string to the * character at the specified index. If the index is negative, counts * backward from the end of the string (-1 returns an offset to the * last character). */ int uoffset(AL_CONST char *s, int index) { AL_CONST char *orig = s; AL_CONST char *last; ASSERT(s); if (index < 0) index += ustrlen(s); while (index-- > 0) { last = s; if (!ugetxc(&s)) { s = last; break; } } return (long)s - (long)orig; } /* ugetat: * Returns the character from the specified index within the string. */ int ugetat(AL_CONST char *s, int index) { ASSERT(s); return ugetc(s + uoffset(s, index)); } /* usetat: * Modifies the character at the specified index within the string, * handling adjustments for variable width data. Returns how far the * rest of the string was moved. */ int usetat(char *s, int index, int c) { int oldw, neww; ASSERT(s); s += uoffset(s, index); oldw = uwidth(s); neww = ucwidth(c); if (oldw != neww) memmove(s+neww, s+oldw, ustrsizez(s+oldw)); usetc(s, c); return neww-oldw; } /* uinsert: * Inserts a character at the specified index within a string, sliding * following data along to make room. Returns how far the data was moved. */ int uinsert(char *s, int index, int c) { int w = ucwidth(c); ASSERT(s); s += uoffset(s, index); memmove(s+w, s, ustrsizez(s)); usetc(s, c); return w; } /* uremove: * Removes the character at the specified index within the string, sliding * following data back to make room. Returns how far the data was moved. */ int uremove(char *s, int index) { int w; ASSERT(s); s += uoffset(s, index); w = uwidth(s); memmove(s, s+w, ustrsizez(s+w)); return -w; } /* uwidth_max: * Returns the largest possible size of a character in the specified * encoding format, in bytes. */ int uwidth_max(int type) { UTYPE_INFO *info; info = _find_utype(type); if (!info) return 0; return info->u_width_max; } /* utolower: * Unicode-aware version of the ANSI tolower() function. */ int utolower(int c) { if ((c >= 65 && c <= 90) || (c >= 192 && c <= 214) || (c >= 216 && c <= 222) || (c >= 913 && c <= 929) || (c >= 931 && c <= 939) || (c >= 1040 && c <= 1071)) return c + 32; if ((c >= 393 && c <= 394)) return c + 205; if ((c >= 433 && c <= 434)) return c + 217; if ((c >= 904 && c <= 906)) return c + 37; if ((c >= 910 && c <= 911)) return c + 63; if ((c >= 1025 && c <= 1036) || (c >= 1038 && c <= 1039)) return c + 80; if ((c >= 1329 && c <= 1366) || (c >= 4256 && c <= 4293)) return c + 48; if ((c >= 7944 && c <= 7951) || (c >= 7960 && c <= 7965) || (c >= 7976 && c <= 7983) || (c >= 7992 && c <= 7999) || (c >= 8008 && c <= 8013) || (c >= 8040 && c <= 8047) || (c >= 8072 && c <= 8079) || (c >= 8088 && c <= 8095) || (c >= 8104 && c <= 8111) || (c >= 8120 && c <= 8121) || (c >= 8152 && c <= 8153) || (c >= 8168 && c <= 8169)) return c + -8; if ((c >= 8122 && c <= 8123)) return c + -74; if ((c >= 8136 && c <= 8139)) return c + -86; if ((c >= 8154 && c <= 8155)) return c + -100; if ((c >= 8170 && c <= 8171)) return c + -112; if ((c >= 8184 && c <= 8185)) return c + -128; if ((c >= 8186 && c <= 8187)) return c + -126; if ((c >= 8544 && c <= 8559)) return c + 16; if ((c >= 9398 && c <= 9423)) return c + 26; switch (c) { case 256: case 258: case 260: case 262: case 264: case 266: case 268: case 270: case 272: case 274: case 276: case 278: case 280: case 282: case 284: case 286: case 288: case 290: case 292: case 294: case 296: case 298: case 300: case 302: case 306: case 308: case 310: case 313: case 315: case 317: case 319: case 321: case 323: case 325: case 327: case 330: case 332: case 334: case 336: case 338: case 340: case 342: case 344: case 346: case 348: case 350: case 352: case 354: case 356: case 358: case 360: case 362: case 364: case 366: case 368: case 370: case 372: case 374: case 377: case 379: case 381: case 386: case 388: case 391: case 395: case 401: case 408: case 416: case 418: case 420: case 423: case 428: case 431: case 435: case 437: case 440: case 444: case 453: case 456: case 459: case 461: case 463: case 465: case 467: case 469: case 471: case 473: case 475: case 478: case 480: case 482: case 484: case 486: case 488: case 490: case 492: case 494: case 498: case 500: case 506: case 508: case 510: case 512: case 514: case 516: case 518: case 520: case 522: case 524: case 526: case 528: case 530: case 532: case 534: case 994: case 996: case 998: case 1000: case 1002: case 1004: case 1006: case 1120: case 1122: case 1124: case 1126: case 1128: case 1130: case 1132: case 1134: case 1136: case 1138: case 1140: case 1142: case 1144: case 1146: case 1148: case 1150: case 1152: case 1168: case 1170: case 1172: case 1174: case 1176: case 1178: case 1180: case 1182: case 1184: case 1186: case 1188: case 1190: case 1192: case 1194: case 1196: case 1198: case 1200: case 1202: case 1204: case 1206: case 1208: case 1210: case 1212: case 1214: case 1217: case 1219: case 1223: case 1227: case 1232: case 1234: case 1236: case 1238: case 1240: case 1242: case 1244: case 1246: case 1248: case 1250: case 1252: case 1254: case 1256: case 1258: case 1262: case 1264: case 1266: case 1268: case 1272: case 7680: case 7682: case 7684: case 7686: case 7688: case 7690: case 7692: case 7694: case 7696: case 7698: case 7700: case 7702: case 7704: case 7706: case 7708: case 7710: case 7712: case 7714: case 7716: case 7718: case 7720: case 7722: case 7724: case 7726: case 7728: case 7730: case 7732: case 7734: case 7736: case 7738: case 7740: case 7742: case 7744: case 7746: case 7748: case 7750: case 7752: case 7754: case 7756: case 7758: case 7760: case 7762: case 7764: case 7766: case 7768: case 7770: case 7772: case 7774: case 7776: case 7778: case 7780: case 7782: case 7784: case 7786: case 7788: case 7790: case 7792: case 7794: case 7796: case 7798: case 7800: case 7802: case 7804: case 7806: case 7808: case 7810: case 7812: case 7814: case 7816: case 7818: case 7820: case 7822: case 7824: case 7826: case 7828: case 7840: case 7842: case 7844: case 7846: case 7848: case 7850: case 7852: case 7854: case 7856: case 7858: case 7860: case 7862: case 7864: case 7866: case 7868: case 7870: case 7872: case 7874: case 7876: case 7878: case 7880: case 7882: case 7884: case 7886: case 7888: case 7890: case 7892: case 7894: case 7896: case 7898: case 7900: case 7902: case 7904: case 7906: case 7908: case 7910: case 7912: case 7914: case 7916: case 7918: case 7920: case 7922: case 7924: case 7926: case 7928: return c + 1; case 304: return c + -199; case 376: return c + -121; case 385: return c + 210; case 390: return c + 206; case 398: return c + 79; case 399: return c + 202; case 400: return c + 203; case 403: return c + 205; case 404: return c + 207; case 406: case 412: return c + 211; case 407: return c + 209; case 413: return c + 213; case 415: return c + 214; case 422: case 425: case 430: return c + 218; case 439: return c + 219; case 452: case 455: case 458: case 497: return c + 2; case 902: return c + 38; case 908: return c + 64; case 8025: case 8027: case 8029: case 8031: return c + -8; case 8124: case 8140: case 8188: return c + -9; case 8172: return c + -7; default: return c; } } /* utoupper: * Unicode-aware version of the ANSI toupper() function. */ int utoupper(int c) { if ((c >= 97 && c <= 122) || (c >= 224 && c <= 246) || (c >= 248 && c <= 254) || (c >= 945 && c <= 961) || (c >= 963 && c <= 971) || (c >= 1072 && c <= 1103)) return c + -32; if ((c >= 598 && c <= 599)) return c + -205; if ((c >= 650 && c <= 651)) return c + -217; if ((c >= 941 && c <= 943)) return c + -37; if ((c >= 973 && c <= 974)) return c + -63; if ((c >= 1105 && c <= 1116) || (c >= 1118 && c <= 1119)) return c + -80; if ((c >= 1377 && c <= 1414)) return c + -48; if ((c >= 7936 && c <= 7943) || (c >= 7952 && c <= 7957) || (c >= 7968 && c <= 7975) || (c >= 7984 && c <= 7991) || (c >= 8000 && c <= 8005) || (c >= 8032 && c <= 8039) || (c >= 8064 && c <= 8071) || (c >= 8080 && c <= 8087) || (c >= 8096 && c <= 8103) || (c >= 8112 && c <= 8113) || (c >= 8144 && c <= 8145) || (c >= 8160 && c <= 8161)) return c + 8; if ((c >= 8048 && c <= 8049)) return c + 74; if ((c >= 8050 && c <= 8053)) return c + 86; if ((c >= 8054 && c <= 8055)) return c + 100; if ((c >= 8056 && c <= 8057)) return c + 128; if ((c >= 8058 && c <= 8059)) return c + 112; if ((c >= 8060 && c <= 8061)) return c + 126; if ((c >= 8560 && c <= 8575)) return c + -16; if ((c >= 9424 && c <= 9449)) return c + -26; switch (c) { case 255: return c + 121; case 257: case 259: case 261: case 263: case 265: case 267: case 269: case 271: case 273: case 275: case 277: case 279: case 281: case 283: case 285: case 287: case 289: case 291: case 293: case 295: case 297: case 299: case 301: case 303: case 307: case 309: case 311: case 314: case 316: case 318: case 320: case 322: case 324: case 326: case 328: case 331: case 333: case 335: case 337: case 339: case 341: case 343: case 345: case 347: case 349: case 351: case 353: case 355: case 357: case 359: case 361: case 363: case 365: case 367: case 369: case 371: case 373: case 375: case 378: case 380: case 382: case 387: case 389: case 392: case 396: case 402: case 409: case 417: case 419: case 421: case 424: case 429: case 432: case 436: case 438: case 441: case 445: case 453: case 456: case 459: case 462: case 464: case 466: case 468: case 470: case 472: case 474: case 476: case 479: case 481: case 483: case 485: case 487: case 489: case 491: case 493: case 495: case 498: case 501: case 507: case 509: case 511: case 513: case 515: case 517: case 519: case 521: case 523: case 525: case 527: case 529: case 531: case 533: case 535: case 995: case 997: case 999: case 1001: case 1003: case 1005: case 1007: case 1121: case 1123: case 1125: case 1127: case 1129: case 1131: case 1133: case 1135: case 1137: case 1139: case 1141: case 1143: case 1145: case 1147: case 1149: case 1151: case 1153: case 1169: case 1171: case 1173: case 1175: case 1177: case 1179: case 1181: case 1183: case 1185: case 1187: case 1189: case 1191: case 1193: case 1195: case 1197: case 1199: case 1201: case 1203: case 1205: case 1207: case 1209: case 1211: case 1213: case 1215: case 1218: case 1220: case 1224: case 1228: case 1233: case 1235: case 1237: case 1239: case 1241: case 1243: case 1245: case 1247: case 1249: case 1251: case 1253: case 1255: case 1257: case 1259: case 1263: case 1265: case 1267: case 1269: case 1273: case 7681: case 7683: case 7685: case 7687: case 7689: case 7691: case 7693: case 7695: case 7697: case 7699: case 7701: case 7703: case 7705: case 7707: case 7709: case 7711: case 7713: case 7715: case 7717: case 7719: case 7721: case 7723: case 7725: case 7727: case 7729: case 7731: case 7733: case 7735: case 7737: case 7739: case 7741: case 7743: case 7745: case 7747: case 7749: case 7751: case 7753: case 7755: case 7757: case 7759: case 7761: case 7763: case 7765: case 7767: case 7769: case 7771: case 7773: case 7775: case 7777: case 7779: case 7781: case 7783: case 7785: case 7787: case 7789: case 7791: case 7793: case 7795: case 7797: case 7799: case 7801: case 7803: case 7805: case 7807: case 7809: case 7811: case 7813: case 7815: case 7817: case 7819: case 7821: case 7823: case 7825: case 7827: case 7829: case 7841: case 7843: case 7845: case 7847: case 7849: case 7851: case 7853: case 7855: case 7857: case 7859: case 7861: case 7863: case 7865: case 7867: case 7869: case 7871: case 7873: case 7875: case 7877: case 7879: case 7881: case 7883: case 7885: case 7887: case 7889: case 7891: case 7893: case 7895: case 7897: case 7899: case 7901: case 7903: case 7905: case 7907: case 7909: case 7911: case 7913: case 7915: case 7917: case 7919: case 7921: case 7923: case 7925: case 7927: case 7929: return c + -1; case 305: return c + -232; case 383: return c + -300; case 454: case 457: case 460: case 499: return c + -2; case 477: case 1010: return c + -79; case 595: return c + -210; case 596: return c + -206; case 601: return c + -202; case 603: return c + -203; case 608: return c + -205; case 611: return c + -207; case 616: return c + -209; case 617: case 623: return c + -211; case 626: return c + -213; case 629: return c + -214; case 640: case 643: case 648: return c + -218; case 658: return c + -219; case 837: return c + 84; case 940: return c + -38; case 962: return c + -31; case 972: return c + -64; case 976: return c + -62; case 977: return c + -57; case 981: return c + -47; case 982: return c + -54; case 1008: return c + -86; case 1009: return c + -80; case 7835: return c + -59; case 8017: case 8019: case 8021: case 8023: return c + 8; case 8115: case 8131: case 8179: return c + 9; case 8126: return c + -7205; case 8165: return c + 7; default: return c; } } /* uisspace: * Unicode-aware version of the ANSI isspace() function. */ int uisspace(int c) { return ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n') || (c == '\f') || (c == '\v') || (c == 0x1680) || ((c >= 0x2000) && (c <= 0x200A)) || (c == 0x2028) || (c == 0x202f) || (c == 0x3000)); } /* uisdigit: * Unicode-aware version of the ANSI isdigit() function. */ int uisdigit(int c) { return ((c >= '0') && (c <= '9')); } /* ustrdup: * Returns a newly allocated copy of the src string, which must later be * freed by the caller. This function is for external use by Allegro * clients only. Internal code should use _al_ustrdup(). */ char *_ustrdup(AL_CONST char *src, AL_METHOD(void *, malloc_func, (size_t))) { char *s; int size; ASSERT(src); ASSERT(malloc_func); size = ustrsizez(src); s = malloc_func(size); if (s) ustrzcpy(s, size, src); else *allegro_errno = ENOMEM; return s; } /* _al_ustrdup: * Returns a newly allocated copy of the src string, which must later be * freed by the caller using _AL_FREE(). This function is for internal use * by Allegro clients only. External code should use ustrdup(). */ char *_al_ustrdup(AL_CONST char *src) { int size; char *newstring; ASSERT(src); size = ustrsizez(src); newstring = _AL_MALLOC(size); if (newstring) ustrzcpy(newstring, size, src); return newstring; } /* ustrsize: * Returns the size of the specified string in bytes, not including the * trailing zero. */ int ustrsize(AL_CONST char *s) { AL_CONST char *orig = s; AL_CONST char *last; ASSERT(s); do { last = s; } while (ugetxc(&s) != 0); return (long)last - (long)orig; } /* ustrsizez: * Returns the size of the specified string in bytes, including the * trailing zero. */ int ustrsizez(AL_CONST char *s) { AL_CONST char *orig = s; ASSERT(s); do { } while (ugetxc(&s) != 0); return (long)s - (long)orig; } /* ustrzcpy: * Enhanced Unicode-aware version of the ANSI strcpy() function * that can handle the size (in bytes) of the destination string. * The raw Unicode-aware version of ANSI strcpy() is defined as: * #define ustrcpy(dest, src) ustrzcpy(dest, INT_MAX, src) */ char *ustrzcpy(char *dest, int size, AL_CONST char *src) { int pos = 0; int c; ASSERT(dest); ASSERT(src); ASSERT(size > 0); size -= ucwidth(0); ASSERT(size >= 0); while ((c = ugetxc(&src)) != 0) { size -= ucwidth(c); if (size < 0) break; pos += usetc(dest+pos, c); } usetc(dest+pos, 0); return dest; } /* ustrzcat: * Enhanced Unicode-aware version of the ANSI strcat() function * that can handle the size (in bytes) of the destination string. * The raw Unicode-aware version of ANSI strcat() is defined as: * #define ustrcat(dest, src) ustrzcat(dest, INT_MAX, src) */ char *ustrzcat(char *dest, int size, AL_CONST char *src) { int pos; int c; ASSERT(dest); ASSERT(src); ASSERT(size > 0); pos = ustrsize(dest); size -= pos + ucwidth(0); ASSERT(size >= 0); while ((c = ugetxc(&src)) != 0) { size -= ucwidth(c); if (size < 0) break; pos += usetc(dest+pos, c); } usetc(dest+pos, 0); return dest; } /* ustrlen: * Unicode-aware version of the ANSI strlen() function. */ int ustrlen(AL_CONST char *s) { int c = 0; ASSERT(s); while (ugetxc(&s)) c++; return c; } /* ustrcmp: * Unicode-aware version of the ANSI strcmp() function. */ int ustrcmp(AL_CONST char *s1, AL_CONST char *s2) { int c1, c2; ASSERT(s1); ASSERT(s2); for (;;) { c1 = ugetxc(&s1); c2 = ugetxc(&s2); if (c1 != c2) return c1 - c2; if (!c1) return 0; } } /* ustrzncpy: * Enhanced Unicode-aware version of the ANSI strncpy() function * that can handle the size (in bytes) of the destination string. * The raw Unicode-aware version of ANSI strncpy() is defined as: * #define ustrncpy(dest, src, n) ustrzncpy(dest, INT_MAX, src, n) */ char *ustrzncpy(char *dest, int size, AL_CONST char *src, int n) { int pos = 0, len = 0; int ansi_oddness = FALSE; int c; ASSERT(dest); ASSERT(src); ASSERT(size > 0); ASSERT(n >= 0); /* detect raw ustrncpy() call */ if (size == INT_MAX) ansi_oddness = TRUE; size -= ucwidth(0); ASSERT(size >= 0); /* copy at most n characters */ while (((c = ugetxc(&src)) != 0) && (len < n)) { size -= ucwidth(c); if (size<0) break; pos += usetc(dest+pos, c); len++; } /* pad with NULL characters */ while (len < n) { size -= ucwidth(0); if (size < 0) break; pos += usetc(dest+pos, 0); len++; } /* ANSI C doesn't append the terminating NULL character */ if (!ansi_oddness) usetc(dest+pos, 0); return dest; } /* ustrzncat: * Enhanced Unicode-aware version of the ANSI strncat() function * that can handle the size (in bytes) of the destination string. * The raw Unicode-aware version of ANSI strncat() is defined as: * #define ustrncat(dest, src, n) ustrzncat(dest, INT_MAX, src, n) */ char *ustrzncat(char *dest, int size, AL_CONST char *src, int n) { int pos, len = 0; int c; ASSERT(dest); ASSERT(src); ASSERT(size >= 0); ASSERT(n >= 0); pos = ustrsize(dest); size -= pos + ucwidth(0); while (((c = ugetxc(&src)) != 0) && (len < n)) { size -= ucwidth(c); if (size<0) break; pos += usetc(dest+pos, c); len++; } usetc(dest+pos, 0); return dest; } /* ustrncmp: * Unicode-aware version of the ANSI strncmp() function. */ int ustrncmp(AL_CONST char *s1, AL_CONST char *s2, int n) { int c1, c2; ASSERT(s1); ASSERT(s2); if (n <= 0) return 0; for (;;) { c1 = ugetxc(&s1); c2 = ugetxc(&s2); if (c1 != c2) return c1 - c2; if ((!c1) || (--n <= 0)) return 0; } } /* ustricmp: * Unicode-aware version of the DJGPP stricmp() function. */ int ustricmp(AL_CONST char *s1, AL_CONST char *s2) { int c1, c2; ASSERT(s1); ASSERT(s2); for (;;) { c1 = utolower(ugetxc(&s1)); c2 = utolower(ugetxc(&s2)); if (c1 != c2) return c1 - c2; if (!c1) return 0; } } /* ustrnicmp: * Unicode-aware version of the DJGPP strnicmp() function. */ int ustrnicmp(AL_CONST char *s1, AL_CONST char *s2, int n) { int c1, c2; ASSERT(s1); ASSERT(s2); if (n <= 0) return 0; for (;;) { c1 = utolower(ugetxc(&s1)); c2 = utolower(ugetxc(&s2)); if (c1 != c2) return c1 - c2; if ((!c1) || (--n <= 0)) return 0; } } /* ustrlwr: * Unicode-aware version of the ANSI strlwr() function. */ char *ustrlwr(char *s) { int pos = 0; int c, lc; ASSERT(s); while ((c = ugetc(s+pos)) != 0) { lc = utolower(c); if (lc != c) usetat(s+pos, 0, lc); pos += uwidth(s+pos); } return s; } /* ustrupr: * Unicode-aware version of the ANSI strupr() function. */ char *ustrupr(char *s) { int pos = 0; int c, uc; ASSERT(s); while ((c = ugetc(s+pos)) != 0) { uc = utoupper(c); if (uc != c) usetat(s+pos, 0, uc); pos += uwidth(s+pos); } return s; } /* ustrchr: * Unicode-aware version of the ANSI strchr() function. */ char *ustrchr(AL_CONST char *s, int c) { int d; ASSERT(s); while ((d = ugetc(s)) != 0) { if (c == d) return (char *)s; s += uwidth(s); } if (!c) return (char *)s; return NULL; } /* ustrrchr: * Unicode-aware version of the ANSI strrchr() function. */ char *ustrrchr(AL_CONST char *s, int c) { AL_CONST char *last_match = NULL; int c1, pos = 0; ASSERT(s); for (c1=ugetc(s); c1; c1=ugetc(s+pos)) { if (c1 == c) last_match = s + pos; pos += ucwidth(c1); } return (char *)last_match; } /* ustrstr: * Unicode-aware version of the ANSI strstr() function. */ char *ustrstr(AL_CONST char *s1, AL_CONST char *s2) { int len; ASSERT(s1); ASSERT(s2); len = ustrlen(s2); while (ugetc(s1)) { if (ustrncmp(s1, s2, len) == 0) return (char *)s1; s1 += uwidth(s1); } return NULL; } /* ustrpbrk: * Unicode-aware version of the ANSI strpbrk() function. */ char *ustrpbrk(AL_CONST char *s, AL_CONST char *set) { AL_CONST char *setp; int c, d; ASSERT(s); ASSERT(set); while ((c = ugetc(s)) != 0) { setp = set; while ((d = ugetxc(&setp)) != 0) { if (c == d) return (char *)s; } s += uwidth(s); } return NULL; } /* ustrtok: * Unicode-aware version of the ANSI strtok() function. */ char *ustrtok(char *s, AL_CONST char *set) { static char *last = NULL; return ustrtok_r(s, set, &last); } /* ustrtok_r: * Unicode-aware version of the strtok_r() function. */ char *ustrtok_r(char *s, AL_CONST char *set, char **last) { char *prev_str, *tok; AL_CONST char *setp; int c, sc; ASSERT(last); if (!s) { s = *last; if (!s) return NULL; } skip_leading_delimiters: prev_str = s; c = ugetx(&s); setp = set; while ((sc = ugetxc(&setp)) != 0) { if (c == sc) goto skip_leading_delimiters; } if (!c) { *last = NULL; return NULL; } tok = prev_str; for (;;) { prev_str = s; c = ugetx(&s); setp = set; do { sc = ugetxc(&setp); if (sc == c) { if (!c) { *last = NULL; return tok; } else { s += usetat(prev_str, 0, 0); *last = s; return tok; } } } while (sc); } } /* uatof: * Unicode-aware version of the ANSI atof() function. No need to bother * implementing this ourselves, since all floating point numbers are * valid ASCII in any case. */ double uatof(AL_CONST char *s) { char tmp[64]; ASSERT(s); return atof(uconvert_toascii(s, tmp)); } /* ustrtol: * Unicode-aware version of the ANSI strtol() function. Note the * nicely bodged implementation :-) */ long ustrtol(AL_CONST char *s, char **endp, int base) { char tmp[64]; char *myendp; long ret; char *t; ASSERT(s); t = uconvert_toascii(s, tmp); ret = strtol(t, &myendp, base); if (endp) *endp = (char *)s + uoffset(s, (long)myendp - (long)t); return ret; } /* ustrtod: * Unicode-aware version of the ANSI strtod() function. Note the * nicely bodged implementation :-) */ double ustrtod(AL_CONST char *s, char **endp) { char tmp[64]; char *myendp; double ret; char *t; ASSERT(s); t = uconvert_toascii(s, tmp); ret = strtod(t, &myendp); if (endp) *endp = (char *)s + uoffset(s, (long)myendp - (long)t); return ret; } /* ustrerror: * Fetch the error description from the OS and convert to Unicode. */ AL_CONST char *ustrerror(int err) { AL_CONST char *s = strerror(err); static char tmp[1024]; return uconvert_ascii(s, tmp); } /*******************************************************************/ /*** Unicode-aware sprintf() functions ***/ /*******************************************************************/ /* information about the current format conversion mode */ typedef struct SPRINT_INFO { int flags; int field_width; int precision; int num_special; } SPRINT_INFO; #define SPRINT_FLAG_LEFT_JUSTIFY 1 #define SPRINT_FLAG_FORCE_PLUS_SIGN 2 #define SPRINT_FLAG_FORCE_SPACE 4 #define SPRINT_FLAG_ALTERNATE_CONVERSION 8 #define SPRINT_FLAG_PAD_ZERO 16 #define SPRINT_FLAG_SHORT_INT 32 #define SPRINT_FLAG_LONG_INT 64 #define SPRINT_FLAG_LONG_DOUBLE 128 #define SPRINT_FLAG_LONG_LONG 256 /* decoded string argument type */ typedef struct STRING_ARG { char *data; int size; /* in bytes without the terminating '\0' */ struct STRING_ARG *next; } STRING_ARG; /* LONGEST: * 64-bit integers on platforms that support it, 32-bit otherwise. */ #ifdef LONG_LONG #define LONGEST LONG_LONG #else #define LONGEST long #endif /* va_int: * Helper for reading an integer from the varargs list. */ #ifdef LONG_LONG #define va_int(args, flags) \ ( \ ((flags) & SPRINT_FLAG_SHORT_INT) ? \ va_arg(args, signed int) \ : \ (((flags) & SPRINT_FLAG_LONG_LONG) ? \ va_arg(args, signed LONG_LONG) \ : \ (((flags) & SPRINT_FLAG_LONG_INT) ? \ va_arg(args, signed long int) \ : \ va_arg(args, signed int))) \ ) #else #define va_int(args, flags) \ ( \ ((flags) & SPRINT_FLAG_SHORT_INT) ? \ va_arg(args, signed int) \ : \ (((flags) & SPRINT_FLAG_LONG_INT) ? \ va_arg(args, signed long int) \ : \ va_arg(args, signed int)) \ ) #endif /* va_uint: * Helper for reading an unsigned integer from the varargs list. */ #ifdef LONG_LONG #define va_uint(args, flags) \ ( \ ((flags) & SPRINT_FLAG_SHORT_INT) ? \ va_arg(args, unsigned int) \ : \ (((flags) & SPRINT_FLAG_LONG_LONG) ? \ va_arg(args, unsigned LONG_LONG) \ : \ (((flags) & SPRINT_FLAG_LONG_INT) ? \ va_arg(args, unsigned long int) \ : \ va_arg(args, unsigned int))) \ ) #else #define va_uint(args, flags) \ ( \ ((flags) & SPRINT_FLAG_SHORT_INT) ? \ va_arg(args, unsigned int) \ : \ (((flags) & SPRINT_FLAG_LONG_INT) ? \ va_arg(args, unsigned long int) \ : \ va_arg(args, unsigned int)) \ ) #endif /* sprint_char: * Helper for formatting (!) a character. */ static int sprint_char(STRING_ARG *string_arg, SPRINT_INFO *info, long val) { int pos = 0; /* 1 character max for... a character */ string_arg->data = _AL_MALLOC((MAX(1, info->field_width) * uwidth_max(U_CURRENT) + ucwidth(0)) * sizeof(char)); pos += usetc(string_arg->data, val); string_arg->size = pos; usetc(string_arg->data+pos, 0); return 1; } /* sprint_i: * Worker function for formatting integers. */ static int sprint_i(STRING_ARG *string_arg, unsigned LONGEST val, int precision) { char tmp[24]; /* for 64-bit integers */ int i = 0, pos = string_arg->size; int len; do { tmp[i++] = val % 10; val /= 10; } while (val); for (len=i; lendata+pos, '0'); while (i > 0) pos += usetc(string_arg->data+pos, tmp[--i] + '0'); string_arg->size = pos; usetc(string_arg->data+pos, 0); return len; } /* sprint_plus_sign: * Helper to add a plus sign or space in front of a number. */ #define sprint_plus_sign(len) \ { \ if (info->flags & SPRINT_FLAG_FORCE_PLUS_SIGN) { \ pos += usetc(string_arg->data+pos, '+'); \ len++; \ } \ else if (info->flags & SPRINT_FLAG_FORCE_SPACE) { \ pos += usetc(string_arg->data+pos, ' '); \ len++; \ } \ } /* sprint_int: * Helper for formatting a signed integer. */ static int sprint_int(STRING_ARG *string_arg, SPRINT_INFO *info, LONGEST val) { int pos = 0, len = 0; /* 24 characters max for a 64-bit integer */ string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + ucwidth(0)) * sizeof(char)); if (val < 0) { val = -val; pos += usetc(string_arg->data+pos, '-'); len++; } else sprint_plus_sign(len); info->num_special = len; string_arg->size = pos; return sprint_i(string_arg, val, info->precision) + info->num_special; } /* sprint_unsigned: * Helper for formatting an unsigned integer. */ static int sprint_unsigned(STRING_ARG *string_arg, SPRINT_INFO *info, unsigned LONGEST val) { int pos = 0; /* 24 characters max for a 64-bit integer */ string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + ucwidth(0)) * sizeof(char)); sprint_plus_sign(info->num_special); string_arg->size = pos; return sprint_i(string_arg, val, info->precision) + info->num_special; } /* sprint_hex: * Helper for formatting a hex integer. */ static int sprint_hex(STRING_ARG *string_arg, SPRINT_INFO *info, int caps, unsigned LONGEST val) { static char hex_digit_caps[] = "0123456789ABCDEF"; static char hex_digit[] = "0123456789abcdef"; char tmp[24]; /* for 64-bit integers */ char *table; int pos = 0, i = 0; int len; /* 24 characters max for a 64-bit integer */ string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + ucwidth(0)) * sizeof(char)); sprint_plus_sign(info->num_special); if (info->flags & SPRINT_FLAG_ALTERNATE_CONVERSION) { pos += usetc(string_arg->data+pos, '0'); pos += usetc(string_arg->data+pos, 'x'); info->num_special += 2; } do { tmp[i++] = val & 15; val >>= 4; } while (val); for (len=i; lenprecision; len++) pos += usetc(string_arg->data+pos, '0'); if (caps) table = hex_digit_caps; else table = hex_digit; while (i > 0) pos += usetc(string_arg->data+pos, table[(int)tmp[--i]]); string_arg->size = pos; usetc(string_arg->data+pos, 0); return len + info->num_special; } /* sprint_octal: * Helper for formatting an octal integer. */ static int sprint_octal(STRING_ARG *string_arg, SPRINT_INFO *info, unsigned LONGEST val) { char tmp[24]; /* for 64-bit integers */ int pos = 0, i = 0; int len; /* 24 characters max for a 64-bit integer */ string_arg->data = _AL_MALLOC((MAX(24, info->field_width) * uwidth_max(U_CURRENT) + ucwidth(0)) * sizeof(char)); sprint_plus_sign(info->num_special); if (info->flags & SPRINT_FLAG_ALTERNATE_CONVERSION) { pos += usetc(string_arg->data+pos, '0'); info->num_special++; } do { tmp[i++] = val & 7; val >>= 3; } while (val); for (len=i; lenprecision; len++) pos += usetc(string_arg->data+pos, '0'); while (i > 0) pos += usetc(string_arg->data+pos, tmp[--i] + '0'); string_arg->size = pos; usetc(string_arg->data+pos, 0); return len + info->num_special; } /* sprint_float: * Helper for formatting a float (piggyback on the libc implementation). */ static int sprint_float(STRING_ARG *string_arg, SPRINT_INFO *info, double val, int conversion) { char format[256], tmp[256]; int len = 0, size; format[len++] = '%'; if (info->flags & SPRINT_FLAG_LEFT_JUSTIFY) format[len++] = '-'; if (info->flags & SPRINT_FLAG_FORCE_PLUS_SIGN) format[len++] = '+'; if (info->flags & SPRINT_FLAG_FORCE_SPACE) format[len++] = ' '; if (info->flags & SPRINT_FLAG_ALTERNATE_CONVERSION) format[len++] = '#'; if (info->flags & SPRINT_FLAG_PAD_ZERO) format[len++] = '0'; if (info->field_width > 0) len += sprintf(format+len, "%d", info->field_width); if (info->precision >= 0) len += sprintf(format+len, ".%d", info->precision); format[len++] = conversion; format[len] = 0; len = sprintf(tmp, format, val); size = len * uwidth_max(U_CURRENT) + ucwidth(0); string_arg->data = _AL_MALLOC(size * sizeof(char)); do_uconvert(tmp, U_ASCII, string_arg->data, U_CURRENT, size); info->field_width = 0; string_arg->size = ustrsize(string_arg->data); return len; } /* sprint_string: * Helper for formatting a string. */ static int sprint_string(STRING_ARG *string_arg, SPRINT_INFO *info, AL_CONST char *s) { int pos = 0, len = 0; int c; string_arg->data = _AL_MALLOC((MAX(ustrlen(s), info->field_width) * uwidth_max(U_CURRENT) + ucwidth(0)) * sizeof(char)); while ((c = ugetxc(&s)) != 0) { if ((info->precision >= 0) && (len >= info->precision)) break; pos += usetc(string_arg->data+pos, c); len++; } string_arg->size = pos; usetc(string_arg->data+pos, 0); return len; } /* decode_format_string: * Worker function for decoding the format string (with those pretty '%' characters) */ static int decode_format_string(char *buf, STRING_ARG *string_arg, AL_CONST char *format, va_list args) { SPRINT_INFO info; int *pstr_pos; int done, slen, c, i, pos; int shift, shiftbytes, shiftfiller; int len = 0; while ((c = ugetxc(&format)) != 0) { if (c == '%') { if ((c = ugetc(format)) == '%') { /* percent sign escape */ format += uwidth(format); buf += usetc(buf, '%'); buf += usetc(buf, '%'); len++; } else { /* format specifier */ #define NEXT_C() \ { \ format += uwidth(format); \ c = ugetc(format); \ } /* set default conversion flags */ info.flags = 0; info.field_width = 0; info.precision = -1; info.num_special = 0; /* check for conversion flags */ done = FALSE; do { switch (c) { case '-': info.flags |= SPRINT_FLAG_LEFT_JUSTIFY; NEXT_C(); break; case '+': info.flags |= SPRINT_FLAG_FORCE_PLUS_SIGN; NEXT_C(); break; case ' ': info.flags |= SPRINT_FLAG_FORCE_SPACE; NEXT_C(); break; case '#': info.flags |= SPRINT_FLAG_ALTERNATE_CONVERSION; NEXT_C(); break; case '0': info.flags |= SPRINT_FLAG_PAD_ZERO; NEXT_C(); break; default: done = TRUE; break; } } while (!done); /* check for a field width specifier */ if (c == '*') { NEXT_C(); info.field_width = va_arg(args, int); if (info.field_width < 0) { info.flags |= SPRINT_FLAG_LEFT_JUSTIFY; info.field_width = -info.field_width; } } else if ((c >= '0') && (c <= '9')) { info.field_width = 0; do { info.field_width *= 10; info.field_width += c - '0'; NEXT_C(); } while ((c >= '0') && (c <= '9')); } /* check for a precision specifier */ if (c == '.') NEXT_C(); if (c == '*') { NEXT_C(); info.precision = va_arg(args, int); if (info.precision < 0) info.precision = 0; } else if ((c >= '0') && (c <= '9')) { info.precision = 0; do { info.precision *= 10; info.precision += c - '0'; NEXT_C(); } while ((c >= '0') && (c <= '9')); } /* check for size qualifiers */ done = FALSE; do { switch (c) { case 'h': info.flags |= SPRINT_FLAG_SHORT_INT; NEXT_C(); break; case 'l': if (info.flags & SPRINT_FLAG_LONG_INT) info.flags |= SPRINT_FLAG_LONG_LONG; else info.flags |= SPRINT_FLAG_LONG_INT; NEXT_C(); break; case 'L': info.flags |= (SPRINT_FLAG_LONG_DOUBLE | SPRINT_FLAG_LONG_LONG); NEXT_C(); break; default: done = TRUE; break; } } while (!done); /* format the data */ switch (c) { case 'c': /* character */ slen = sprint_char(string_arg, &info, va_arg(args, int)); NEXT_C(); break; case 'd': case 'i': /* signed integer */ slen = sprint_int(string_arg, &info, va_int(args, info.flags)); NEXT_C(); break; case 'D': /* signed long integer */ slen = sprint_int(string_arg, &info, va_int(args, info.flags | SPRINT_FLAG_LONG_INT)); NEXT_C(); break; case 'e': case 'E': case 'f': case 'g': case 'G': /* double */ if (info.flags & SPRINT_FLAG_LONG_DOUBLE) slen = sprint_float(string_arg, &info, va_arg(args, long double), c); else slen = sprint_float(string_arg, &info, va_arg(args, double), c); NEXT_C(); break; case 'n': /* store current string position */ pstr_pos = va_arg(args, int *); *pstr_pos = len; slen = -1; NEXT_C(); break; case 'o': /* unsigned octal integer */ slen = sprint_octal(string_arg, &info, va_uint(args, info.flags)); NEXT_C(); break; case 'p': /* pointer */ slen = sprint_hex(string_arg, &info, FALSE, (unsigned long)(va_arg(args, void *))); NEXT_C(); break; case 's': /* string */ slen = sprint_string(string_arg, &info, va_arg(args, char *)); NEXT_C(); break; case 'u': /* unsigned integer */ slen = sprint_unsigned(string_arg, &info, va_uint(args, info.flags)); NEXT_C(); break; case 'U': /* unsigned long integer */ slen = sprint_unsigned(string_arg, &info, va_uint(args, info.flags | SPRINT_FLAG_LONG_INT)); NEXT_C(); break; case 'x': case 'X': /* unsigned hex integer */ slen = sprint_hex(string_arg, &info, (c == 'X'), va_uint(args, info.flags)); NEXT_C(); break; default: /* weird shit... */ slen = -1; break; } if (slen >= 0) { if (slen < info.field_width) { if (info.flags & SPRINT_FLAG_LEFT_JUSTIFY) { /* left align the result */ pos = string_arg->size; while (slen < info.field_width) { pos += usetc(string_arg->data+pos, ' '); slen++; } string_arg->size = pos; usetc(string_arg->data+pos, 0); } else { /* right align the result */ shift = info.field_width - slen; if (shift > 0) { pos = 0; if (info.flags & SPRINT_FLAG_PAD_ZERO) { shiftfiller = '0'; for (i=0; idata+pos); } else shiftfiller = ' '; shiftbytes = shift * ucwidth(shiftfiller); memmove(string_arg->data+pos+shiftbytes, string_arg->data+pos, string_arg->size-pos+ucwidth(0)); string_arg->size += shiftbytes; slen += shift; for (i=0; idata+pos, shiftfiller); } } } buf += usetc(buf, '%'); buf += usetc(buf, 's'); len += slen; /* allocate next item */ string_arg->next = _AL_MALLOC(sizeof(STRING_ARG)); string_arg = string_arg->next; string_arg->next = NULL; } } } else { /* normal character */ buf += usetc(buf, c); len++; } } usetc(buf, 0); return len; } /* uvszprintf: * Enhanced Unicode-aware version of the ANSI vsprintf() function * than can handle the size (in bytes) of the destination buffer. * The raw Unicode-aware version of ANSI vsprintf() is defined as: * #define uvsprintf(buf, format, args) uvszprintf(buf, INT_MAX, format, args) */ int uvszprintf(char *buf, int size, AL_CONST char *format, va_list args) { char *decoded_format, *df; STRING_ARG *string_args, *iter_arg; int c, len; ASSERT(buf); ASSERT(size >= 0); ASSERT(format); /* decoding can only lower the length of the format string */ df = decoded_format = _AL_MALLOC_ATOMIC(ustrsizez(format) * sizeof(char)); /* allocate first item */ string_args = _AL_MALLOC(sizeof(STRING_ARG)); string_args->next = NULL; /* 1st pass: decode */ len = decode_format_string(decoded_format, string_args, format, args); size -= ucwidth(0); iter_arg = string_args; /* 2nd pass: concatenate */ while ((c = ugetx(&decoded_format)) != 0) { if (c == '%') { if ((c = ugetx(&decoded_format)) == '%') { /* percent sign escape */ size -= ucwidth('%'); if (size<0) break; buf += usetc(buf, '%'); } else if (c == 's') { /* string argument */ ustrzcpy(buf, size+ucwidth(0), iter_arg->data); buf += iter_arg->size; size -= iter_arg->size; if (size<0) { buf += size; break; } iter_arg = iter_arg->next; } } else { /* normal character */ size -= ucwidth(c); if (size<0) break; buf += usetc(buf, c); } } usetc(buf, 0); /* free allocated resources */ while (string_args->next) { _AL_FREE(string_args->data); iter_arg = string_args; string_args = string_args->next; _AL_FREE(iter_arg); } _AL_FREE(string_args); _AL_FREE(df); /* alias for decoded_format */ return len; } /* usprintf: * Unicode-aware version of the ANSI sprintf() function. */ int usprintf(char *buf, AL_CONST char *format, ...) { int ret; va_list ap; ASSERT(buf); ASSERT(format); va_start(ap, format); ret = uvszprintf(buf, INT_MAX, format, ap); va_end(ap); return ret; } /* uszprintf: * Enhanced Unicode-aware version of the ANSI sprintf() function * that can handle the size (in bytes) of the destination buffer. */ int uszprintf(char *buf, int size, AL_CONST char *format, ...) { int ret; va_list ap; ASSERT(buf); ASSERT(size >= 0); ASSERT(format); va_start(ap, format); ret = uvszprintf(buf, size, format, ap); va_end(ap); return ret; } allegro-4.4.3.1/src/rle.c0000664000175000017500000001327313437077643014023 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * RLE sprite generation routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* get_rle_sprite: * Creates a run length encoded sprite based on the specified bitmap. * The returned sprite is likely to be a lot smaller than the original * bitmap, and can be drawn to the screen with draw_rle_sprite(). * * The compression is done individually for each line of the image. * Format is a series of command bytes, 1-127 marks a run of that many * solid pixels, negative numbers mark a gap of -n pixels, and 0 marks * the end of a line (since zero can't occur anywhere else in the data, * this can be used to find the start of a specified line when clipping). * For truecolor RLE sprites, the data and command bytes are both in the * same format (16 or 32 bits, 24 bpp data is padded to 32 bit aligment), * and the mask color (bright pink) is used as the EOL marker. */ RLE_SPRITE *get_rle_sprite(BITMAP *bitmap) { int depth; RLE_SPRITE *s; int x, y; int run; int pix; int c; ASSERT(bitmap); depth = bitmap_color_depth(bitmap); #define WRITE_TO_SPRITE8(x) { \ _grow_scratch_mem(c+1); \ p = (signed char *)_scratch_mem; \ p[c] = x; \ c++; \ } #define WRITE_TO_SPRITE16(x) { \ _grow_scratch_mem((c+1)*sizeof(int16_t)); \ p = (int16_t *)_scratch_mem; \ p[c] = x; \ c++; \ } #define WRITE_TO_SPRITE32(x) { \ _grow_scratch_mem((c+1)*sizeof(int32_t)); \ p = (int32_t *)_scratch_mem; \ p[c] = x; \ c++; \ } /* helper for building an RLE run */ #define DO_RLE(bits) \ { \ for (y=0; yh; y++) { \ run = -1; \ for (x=0; xw; x++) { \ pix = getpixel(bitmap, x, y) & 0xFFFFFF; \ if (pix != bitmap->vtable->mask_color) { \ if ((run >= 0) && (p[run] > 0) && (p[run] < 127)) \ p[run]++; \ else { \ run = c; \ WRITE_TO_SPRITE##bits(1); \ } \ WRITE_TO_SPRITE##bits(getpixel(bitmap, x, y)); \ } \ else { \ if ((run >= 0) && (p[run] < 0) && (p[run] > -128)) \ p[run]--; \ else { \ run = c; \ WRITE_TO_SPRITE##bits(-1); \ } \ } \ } \ WRITE_TO_SPRITE##bits(bitmap->vtable->mask_color); \ } \ } c = 0; switch (depth) { #ifdef ALLEGRO_COLOR8 case 8: { signed char *p = (signed char *)_scratch_mem; DO_RLE(8); } break; #endif #ifdef ALLEGRO_COLOR16 case 15: case 16: { signed short *p = (signed short *)_scratch_mem; DO_RLE(16); c *= sizeof(short); } break; #endif #if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) case 24: case 32: { int32_t *p = (int32_t *)_scratch_mem; DO_RLE(32); c *= sizeof(int32_t); } break; #endif } s = _AL_MALLOC(sizeof(RLE_SPRITE) + c); if (s) { s->w = bitmap->w; s->h = bitmap->h; s->color_depth = depth; s->size = c; memcpy(s->dat, _scratch_mem, c); } return s; } /* destroy_rle_sprite: * Destroys an RLE sprite structure returned by get_rle_sprite(). */ void destroy_rle_sprite(RLE_SPRITE *sprite) { if (sprite) _AL_FREE(sprite); } allegro-4.4.3.1/src/colblend.c0000664000175000017500000005566013437077643015031 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Interpolation routines for hicolor and truecolor pixels. * * By Cloud Wu and Burton Radons. * * Alpha blending optimised by Peter Cech. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #define BLEND(bpp, r, g, b) _blender_trans##bpp(makecol##bpp(r, g, b), y, n) #define T(x, y, n) (((y) - (x)) * (n) / 255 + (x)) /* _blender_black: * Fallback routine for when we don't have anything better to do. */ unsigned long _blender_black(unsigned long x, unsigned long y, unsigned long n) { return 0; } #if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) #if (defined ALLEGRO_NO_ASM) || (!defined ALLEGRO_I386) /* i386 asm version is in imisc.s */ /* _blender_trans24: * 24 bit trans blender function. */ unsigned long _blender_trans24(unsigned long x, unsigned long y, unsigned long n) { unsigned long res, g; if (n) n++; res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; y &= 0xFF00; x &= 0xFF00; g = (x - y) * n / 256 + y; res &= 0xFF00FF; g &= 0xFF00; return res | g; } #endif /* C version */ /* _blender_alpha24: * Combines a 32 bit RGBA sprite with a 24 bit RGB destination. */ unsigned long _blender_alpha24(unsigned long x, unsigned long y, unsigned long n) { unsigned long xx = makecol24(getr32(x), getg32(x), getb32(x)); unsigned long res, g; n = geta32(x); if (n) n++; res = ((xx & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; y &= 0xFF00; xx &= 0xFF00; g = (xx - y) * n / 256 + y; res &= 0xFF00FF; g &= 0xFF00; return res | g; } /* _blender_alpha32: * Combines a 32 bit RGBA sprite with a 32 bit RGB destination. */ unsigned long _blender_alpha32(unsigned long x, unsigned long y, unsigned long n) { unsigned long res, g; n = geta32(x); if (n) n++; res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; y &= 0xFF00; x &= 0xFF00; g = (x - y) * n / 256 + y; res &= 0xFF00FF; g &= 0xFF00; return res | g; } /* _blender_alpha24_bgr: * Combines a 32 bit RGBA sprite with a 24 bit RGB destination, optimised * for when one is in a BGR format and the other is RGB. */ unsigned long _blender_alpha24_bgr(unsigned long x, unsigned long y, unsigned long n) { unsigned long res, g; n = x >> 24; if (n) n++; x = ((x>>16)&0xFF) | (x&0xFF00) | ((x<<16)&0xFF0000); res = ((x & 0xFF00FF) - (y & 0xFF00FF)) * n / 256 + y; y &= 0xFF00; x &= 0xFF00; g = (x - y) * n / 256 + y; res &= 0xFF00FF; g &= 0xFF00; return res | g; } /* _blender_add24: * 24 bit additive blender function. */ unsigned long _blender_add24(unsigned long x, unsigned long y, unsigned long n) { int r = getr24(y) + getr24(x) * n / 256; int g = getg24(y) + getg24(x) * n / 256; int b = getb24(y) + getb24(x) * n / 256; r = MIN(r, 255); g = MIN(g, 255); b = MIN(b, 255); return makecol24(r, g, b); } /* _blender_burn24: * 24 bit burn blender function. */ unsigned long _blender_burn24(unsigned long x, unsigned long y, unsigned long n) { return BLEND(24, MAX(getr24(x) - getr24(y), 0), MAX(getg24(x) - getg24(y), 0), MAX(getb24(x) - getb24(y), 0)); } /* _blender_color24: * 24 bit color blender function. */ unsigned long _blender_color24(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr24(x), getg24(x), getb24(x), &xh, &xs, &xv); rgb_to_hsv(getr24(y), getg24(y), getb24(y), &yh, &ys, &yv); xs = T(xs, ys, n); xh = T(xh, yh, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol24(r, g, b); } /* _blender_difference24: * 24 bit difference blender function. */ unsigned long _blender_difference24(unsigned long x, unsigned long y, unsigned long n) { return BLEND(24, ABS(getr24(y) - getr24(x)), ABS(getg24(y) - getg24(x)), ABS(getb24(y) - getb24(x))); } /* _blender_dissolve24: * 24 bit dissolve blender function. */ unsigned long _blender_dissolve24(unsigned long x, unsigned long y, unsigned long n) { if (n == 255) return x; return ((_al_rand() & 255) < (int)n) ? x : y; } /* _blender_dodge24: * 24 bit dodge blender function. */ unsigned long _blender_dodge24(unsigned long x, unsigned long y, unsigned long n) { return BLEND(24, getr24(x) + (getr24(y) * n / 256), getg24(x) + (getg24(y) * n / 256), getb24(x) + (getb24(y) * n / 256)); } /* _blender_hue24: * 24 bit hue blender function. */ unsigned long _blender_hue24(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr24(x), getg24(x), getb24(x), &xh, &xs, &xv); rgb_to_hsv(getr24(y), getg24(y), getb24(y), &yh, &ys, &yv); xh = T(xh, yh, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol24(r, g, b); } /* _blender_invert24: * 24 bit invert blender function. */ unsigned long _blender_invert24(unsigned long x, unsigned long y, unsigned long n) { return BLEND(24, 255-getr24(x), 255-getg24(x), 255-getb24(x)); } /* _blender_luminance24: * 24 bit luminance blender function. */ unsigned long _blender_luminance24(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr24(x), getg24(x), getb24(x), &xh, &xs, &xv); rgb_to_hsv(getr24(y), getg24(y), getb24(y), &yh, &ys, &yv); xv = T(xv, yv, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol24(r, g, b); } /* _blender_multiply24: * 24 bit multiply blender function. */ unsigned long _blender_multiply24(unsigned long x, unsigned long y, unsigned long n) { return BLEND(24, getr24(x) * getr24(y) / 256, getg24(x) * getg24(y) / 256, getb24(x) * getb24(y) / 256); } /* _blender_saturation24: * 24 bit saturation blender function. */ unsigned long _blender_saturation24(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr24(x), getg24(x), getb24(x), &xh, &xs, &xv); rgb_to_hsv(getr24(y), getg24(y), getb24(y), &yh, &ys, &yv); xs = T(xs, ys, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol24(r, g, b); } /* _blender_screen24: * 24 bit screen blender function. */ unsigned long _blender_screen24(unsigned long x, unsigned long y, unsigned long n) { return BLEND(24, 255 - ((255 - getr24(x)) * (255 - getr24(y))) / 256, 255 - ((255 - getg24(x)) * (255 - getg24(y))) / 256, 255 - ((255 - getb24(x)) * (255 - getb24(y))) / 256); } #endif /* end of 24/32 bit routines */ #if (defined ALLEGRO_COLOR15) || (defined ALLEGRO_COLOR16) /* _blender_trans16: * 16 bit trans blender function. */ unsigned long _blender_trans16(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; if (n) n = (n + 1) / 8; x = ((x & 0xFFFF) | (x << 16)) & 0x7E0F81F; y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; result = ((x - y) * n / 32 + y) & 0x7E0F81F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_alpha16: * Combines a 32 bit RGBA sprite with a 16 bit RGB destination. */ unsigned long _blender_alpha16(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; n = geta32(x); if (n) n = (n + 1) / 8; x = makecol16(getr32(x), getg32(x), getb32(x)); x = (x | (x << 16)) & 0x7E0F81F; y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; result = ((x - y) * n / 32 + y) & 0x7E0F81F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_alpha16_rgb * Combines a 32 bit RGBA sprite with a 16 bit RGB destination, optimised * for when both pixels are in an RGB layout. */ unsigned long _blender_alpha16_rgb(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; n = x >> 24; if (n) n = (n + 1) / 8; x = ((x>>3)&0x001F) | ((x>>5)&0x07E0) | ((x>>8)&0xF800); x = (x | (x << 16)) & 0x7E0F81F; y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; result = ((x - y) * n / 32 + y) & 0x7E0F81F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_alpha16_bgr * Combines a 32 bit RGBA sprite with a 16 bit RGB destination, optimised * for when one pixel is in an RGB layout and the other is BGR. */ unsigned long _blender_alpha16_bgr(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; n = x >> 24; if (n) n = (n + 1) / 8; x = ((x>>19)&0x001F) | ((x>>5)&0x07E0) | ((x<<8)&0xF800); x = (x | (x << 16)) & 0x7E0F81F; y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F; result = ((x - y) * n / 32 + y) & 0x7E0F81F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_add16: * 16 bit additive blender function. */ unsigned long _blender_add16(unsigned long x, unsigned long y, unsigned long n) { int r = getr16(y) + getr16(x) * n / 256; int g = getg16(y) + getg16(x) * n / 256; int b = getb16(y) + getb16(x) * n / 256; r = MIN(r, 255); g = MIN(g, 255); b = MIN(b, 255); return makecol16(r, g, b); } /* _blender_burn16: * 16 bit burn blender function. */ unsigned long _blender_burn16(unsigned long x, unsigned long y, unsigned long n) { return BLEND(16, MAX(getr16(x) - getr16(y), 0), MAX(getg16(x) - getg16(y), 0), MAX(getb16(x) - getb16(y), 0)); } /* _blender_color16: * 16 bit color blender function. */ unsigned long _blender_color16(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr16(x), getg16(x), getb16(x), &xh, &xs, &xv); rgb_to_hsv(getr16(y), getg16(y), getb16(y), &yh, &ys, &yv); xs = T(xs, ys, n); xh = T(xh, yh, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol16(r, g, b); } /* _blender_difference16: * 16 bit difference blender function. */ unsigned long _blender_difference16(unsigned long x, unsigned long y, unsigned long n) { return BLEND(16, ABS(getr16(y) - getr16(x)), ABS(getg16(y) - getg16(x)), ABS(getb16(y) - getb16(x))); } /* _blender_dissolve16: * 16 bit dissolve blender function. */ unsigned long _blender_dissolve16(unsigned long x, unsigned long y, unsigned long n) { if (n == 255) return x; return ((_al_rand() & 255) < (int)n) ? x : y; } /* _blender_dodge16: * 16 bit dodge blender function. */ unsigned long _blender_dodge16(unsigned long x, unsigned long y, unsigned long n) { return BLEND(16, getr16(x) + (getr16(y) * n / 256), getg16(x) + (getg16(y) * n / 256), getb16(x) + (getb16(y) * n / 256)); } /* _blender_hue16: * 16 bit hue blender function. */ unsigned long _blender_hue16(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr16(x), getg16(x), getb16(x), &xh, &xs, &xv); rgb_to_hsv(getr16(y), getg16(y), getb16(y), &yh, &ys, &yv); xh = T(xh, yh, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol16(r, g, b); } /* _blender_invert16: * 16 bit invert blender function. */ unsigned long _blender_invert16(unsigned long x, unsigned long y, unsigned long n) { return BLEND(16, 255-getr16(x), 255-getg16(x), 255-getb16(x)); } /* _blender_luminance16: * 16 bit luminance blender function. */ unsigned long _blender_luminance16(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr16(x), getg16(x), getb16(x), &xh, &xs, &xv); rgb_to_hsv(getr16(y), getg16(y), getb16(y), &yh, &ys, &yv); xv = T(xv, yv, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol16(r, g, b); } /* _blender_multiply16: * 16 bit multiply blender function. */ unsigned long _blender_multiply16(unsigned long x, unsigned long y, unsigned long n) { return BLEND(16, getr16(x) * getr16(y) / 256, getg16(x) * getg16(y) / 256, getb16(x) * getb16(y) / 256); } /* _blender_saturation16: * 16 bit saturation blender function. */ unsigned long _blender_saturation16(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr16(x), getg16(x), getb16(x), &xh, &xs, &xv); rgb_to_hsv(getr16(y), getg16(y), getb16(y), &yh, &ys, &yv); xs = T(xs, ys, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol16(r, g, b); } /* _blender_screen16: * 16 bit screen blender function. */ unsigned long _blender_screen16(unsigned long x, unsigned long y, unsigned long n) { return BLEND(16, 255 - ((255 - getr16(x)) * (255 - getr16(y))) / 256, 255 - ((255 - getg16(x)) * (255 - getg16(y))) / 256, 255 - ((255 - getb16(x)) * (255 - getb16(y))) / 256); } /* _blender_trans15: * 15 bit trans blender function. */ unsigned long _blender_trans15(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; if (n) n = (n + 1) / 8; x = ((x & 0xFFFF) | (x << 16)) & 0x3E07C1F; y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; result = ((x - y) * n / 32 + y) & 0x3E07C1F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_alpha15: * Combines a 32 bit RGBA sprite with a 15 bit RGB destination. */ unsigned long _blender_alpha15(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; n = geta32(x); if (n) n = (n + 1) / 8; x = makecol15(getr32(x), getg32(x), getb32(x)); x = (x | (x << 16)) & 0x3E07C1F; y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; result = ((x - y) * n / 32 + y) & 0x3E07C1F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_alpha15_rgb * Combines a 32 bit RGBA sprite with a 15 bit RGB destination, optimised * for when both pixels are in an RGB layout. */ unsigned long _blender_alpha15_rgb(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; n = x >> 24; if (n) n = (n + 1) / 8; x = ((x>>3)&0x001F) | ((x>>6)&0x03E0) | ((x>>9)&0xEC00); x = (x | (x << 16)) & 0x3E07C1F; y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; result = ((x - y) * n / 32 + y) & 0x3E07C1F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_alpha15_bgr * Combines a 32 bit RGBA sprite with a 15 bit RGB destination, optimised * for when one pixel is in an RGB layout and the other is BGR. */ unsigned long _blender_alpha15_bgr(unsigned long x, unsigned long y, unsigned long n) { unsigned long result; n = x >> 24; if (n) n = (n + 1) / 8; x = ((x>>19)&0x001F) | ((x>>6)&0x03E0) | ((x<<7)&0xEC00); x = (x | (x << 16)) & 0x3E07C1F; y = ((y & 0xFFFF) | (y << 16)) & 0x3E07C1F; result = ((x - y) * n / 32 + y) & 0x3E07C1F; return ((result & 0xFFFF) | (result >> 16)); } /* _blender_add15: * 15 bit additive blender function. */ unsigned long _blender_add15(unsigned long x, unsigned long y, unsigned long n) { int r = getr15(y) + getr15(x) * n / 256; int g = getg15(y) + getg15(x) * n / 256; int b = getb15(y) + getb15(x) * n / 256; r = MIN(r, 255); g = MIN(g, 255); b = MIN(b, 255); return makecol15(r, g, b); } /* _blender_burn15: * 15 bit burn blender function. */ unsigned long _blender_burn15(unsigned long x, unsigned long y, unsigned long n) { return BLEND(15, MAX(getr15(x) - getr15(y), 0), MAX(getg15(x) - getg15(y), 0), MAX(getb15(x) - getb15(y), 0)); } /* _blender_color15: * 15 bit color blender function. */ unsigned long _blender_color15(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr15(x), getg15(x), getb15(x), &xh, &xs, &xv); rgb_to_hsv(getr15(y), getg15(y), getb15(y), &yh, &ys, &yv); xs = T(xs, ys, n); xh = T(xh, yh, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol15(r, g, b); } /* _blender_difference15: * 15 bit difference blender function. */ unsigned long _blender_difference15(unsigned long x, unsigned long y, unsigned long n) { return BLEND(15, ABS(getr15(y) - getr15(x)), ABS(getg15(y) - getg15(x)), ABS(getb15(y) - getb15(x))); } /* _blender_dissolve15: * 15 bit dissolve blender function. */ unsigned long _blender_dissolve15(unsigned long x, unsigned long y, unsigned long n) { if (n == 255) return x; return ((_al_rand() & 255) < (int)n) ? x : y; } /* _blender_dodge15: * 15 bit dodge blender function. */ unsigned long _blender_dodge15(unsigned long x, unsigned long y, unsigned long n) { return BLEND(15, getr15(x) + (getr15(y) * n / 256), getg15(x) + (getg15(y) * n / 256), getb15(x) + (getb15(y) * n / 256)); } /* _blender_hue15: * 15 bit hue blender function. */ unsigned long _blender_hue15(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr15(x), getg15(x), getb15(x), &xh, &xs, &xv); rgb_to_hsv(getr15(y), getg15(y), getb15(y), &yh, &ys, &yv); xh = T(xh, yh, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol15(r, g, b); } /* _blender_invert15: * 15 bit invert blender function. */ unsigned long _blender_invert15(unsigned long x, unsigned long y, unsigned long n) { return BLEND(15, 255-getr15(x), 255-getg15(x), 255-getb15(x)); } /* _blender_luminance15: * 15 bit luminance blender function. */ unsigned long _blender_luminance15(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr15(x), getg15(x), getb15(x), &xh, &xs, &xv); rgb_to_hsv(getr15(y), getg15(y), getb15(y), &yh, &ys, &yv); xv = T(xv, yv, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol15(r, g, b); } /* _blender_multiply15: * 15 bit multiply blender function. */ unsigned long _blender_multiply15(unsigned long x, unsigned long y, unsigned long n) { return BLEND(15, getr15(x) * getr15(y) / 256, getg15(x) * getg15(y) / 256, getb15(x) * getb15(y) / 256); } /* _blender_saturation15: * 15 bit saturation blender function. */ unsigned long _blender_saturation15(unsigned long x, unsigned long y, unsigned long n) { float xh, xs, xv; float yh, ys, yv; int r, g, b; rgb_to_hsv(getr15(x), getg15(x), getb15(x), &xh, &xs, &xv); rgb_to_hsv(getr15(y), getg15(y), getb15(y), &yh, &ys, &yv); xs = T(xs, ys, n); hsv_to_rgb(xh, xs, xv, &r, &g, &b); return makecol15(r, g, b); } /* _blender_screen15: * 15 bit screen blender function. */ unsigned long _blender_screen15(unsigned long x, unsigned long y, unsigned long n) { return BLEND(15, 255 - ((255 - getr15(x)) * (255 - getr15(y))) / 256, 255 - ((255 - getg15(x)) * (255 - getg15(y))) / 256, 255 - ((255 - getb15(x)) * (255 - getb15(y))) / 256); } #endif /* end of 15/16 bit routines */ #ifdef ALLEGRO_COLOR16 #define BF16(name) name #else #define BF16(name) _blender_black #endif #if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) #define BF24(name) name #else #define BF24(name) _blender_black #endif /* these functions are all the same, so we can generate them with a macro */ #define SET_BLENDER_FUNC(name) \ void set_##name##_blender(int r, int g, int b, int a) \ { \ if (gfx_driver && gfx_driver->set_blender_mode) \ gfx_driver->set_blender_mode(blender_mode_##name, r, g, b, a);\ set_blender_mode(BF16(_blender_##name##15), \ BF16(_blender_##name##16), \ BF24(_blender_##name##24), \ r, g, b, a); \ } SET_BLENDER_FUNC(trans); SET_BLENDER_FUNC(add); SET_BLENDER_FUNC(burn); SET_BLENDER_FUNC(color); SET_BLENDER_FUNC(difference); SET_BLENDER_FUNC(dissolve); SET_BLENDER_FUNC(dodge); SET_BLENDER_FUNC(hue); SET_BLENDER_FUNC(invert); SET_BLENDER_FUNC(luminance); SET_BLENDER_FUNC(multiply); SET_BLENDER_FUNC(saturation); SET_BLENDER_FUNC(screen); /* set_alpha_blender: * Sets the special RGBA blending mode. */ void set_alpha_blender(void) { BLENDER_FUNC f15, f16, f24, f32; int r, b; /* Call gfx_driver->set_blender_mode() for hardware acceleration */ if (gfx_driver && gfx_driver->set_blender_mode) gfx_driver->set_blender_mode(blender_mode_alpha, 0, 0, 0, 0); /* check which way around the 32 bit pixels are */ if ((_rgb_g_shift_32 == 8) && (_rgb_a_shift_32 == 24)) { r = (_rgb_r_shift_32) ? 1 : 0; b = (_rgb_b_shift_32) ? 1 : 0; } else r = b = 0; #ifdef ALLEGRO_COLOR16 /* decide which 15 bit blender to use */ if ((_rgb_r_shift_15 == r*10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == b*10)) f15 = _blender_alpha15_rgb; else if ((_rgb_r_shift_15 == b*10) && (_rgb_g_shift_15 == 5) && (_rgb_b_shift_15 == r*10)) f15 = _blender_alpha15_bgr; else f15 = _blender_alpha15; /* decide which 16 bit blender to use */ if ((_rgb_r_shift_16 == r*11) && (_rgb_g_shift_16 == 5) && (_rgb_b_shift_16 == b*11)) f16 = _blender_alpha16_rgb; else if ((_rgb_r_shift_16 == b*11) && (_rgb_g_shift_16 == 5) && (_rgb_b_shift_16 == r*11)) f16 = _blender_alpha16_bgr; else f16 = _blender_alpha16; #else /* hicolor not included in this build */ f15 = _blender_black; f16 = _blender_black; #endif #ifdef ALLEGRO_COLOR24 /* decide which 24 bit blender to use */ if ((_rgb_r_shift_24 == r*16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == b*16)) f24 = _blender_alpha32; else if ((_rgb_r_shift_24 == b*16) && (_rgb_g_shift_24 == 8) && (_rgb_b_shift_24 == r*16)) f24 = _blender_alpha24_bgr; else f24 = _blender_alpha24; #else /* 24 bit color not included in this build */ f24 = _blender_black; #endif #ifdef ALLEGRO_COLOR32 f32 = _blender_alpha32; #else f32 = _blender_black; #endif set_blender_mode_ex(_blender_black, _blender_black, _blender_black, f32, f15, f16, f24, 0, 0, 0, 0); } #ifdef ALLEGRO_COLOR32 /* _blender_write_alpha: * Overlays an alpha channel onto an existing 32 bit RGBA bitmap. */ unsigned long _blender_write_alpha(unsigned long x, unsigned long y, unsigned long n) { return (y & 0xFFFFFF) | (x << 24); } #endif /* set_write_alpha_blender: * Sets the special RGBA editing mode. */ void set_write_alpha_blender(void) { BLENDER_FUNC f32; #ifdef ALLEGRO_COLOR32 f32 = _blender_write_alpha; #else f32 = _blender_black; #endif set_blender_mode_ex(_blender_black, _blender_black, _blender_black, f32, _blender_black, _blender_black, _blender_black, 0, 0, 0, 0); } allegro-4.4.3.1/src/fsel.c0000664000175000017500000006206013437077643014170 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The file selector. * * By Shawn Hargreaves. * * Guilherme Silveira and Theuzifan Sumachingun both independently * modified it to only list valid drive letters. * * Peter Pavlovic modified it not to list the logical drives, such * as the b: drive assigned as a logical drive for a: on single * floppy disk drive equipped systems and improved the browsing * through directories. * * Peter Wang and Eric Botcazou modified it to stretch to screen and * font sizes. * * Annie Testes modified it so that buffer overflows cannot occur * anymore. * * Eric Botcazou optimized the handling of the extension string. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0') #define FSEL_HAVE_DIR_LIST #endif static int fs_edit_proc(int, DIALOG *, int); static int fs_flist_proc(int, DIALOG *, int); static char *fs_flist_getter(int, int *); #ifdef FSEL_HAVE_DIR_LIST static int fs_dlist_proc(int, DIALOG *, int); static char *fs_dlist_getter(int, int *); #endif /* Number of entries is limited by available memory * Initial capacity is given by FLIST_START_CAPACITY, structure can grow beyond * this. Normally keeps the structure in memory between invocations, but it * attempts to free memory after processing a directory with more than * FLIST_UPPER_CAPACITY */ #define FLIST_START_CAPACITY 128 #define FLIST_UPPER_CAPACITY 2048 typedef struct FLIST { char dir[1024]; int size; int capacity; char** name; } FLIST; static FLIST *flist = NULL; /* file extensions */ static char *fext = NULL; /* tokenized extension string (dynamically allocated) */ static char **fext_p = NULL; /* list of pointers to the tokens (dynamically allocated) */ static int fext_size = 0; /* size of the list */ /* file attributes (rhsda order) */ #define ATTRB_MAX 5 /* number of attributes */ #define ATTRB_DIREC 3 /* index of FA_DIREC */ typedef enum { ATTRB_ABSENT, ATTRB_UNSET, ATTRB_SET } attrb_state_t; #define DEFAULT_ATTRB_STATE { ATTRB_ABSENT, ATTRB_UNSET, ATTRB_UNSET, ATTRB_ABSENT, ATTRB_ABSENT } static int attrb_flag[ATTRB_MAX] = { FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_DIREC, FA_ARCH }; static attrb_state_t attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE; static char updir[1024]; static DIALOG file_selector[] = { #ifdef FSEL_HAVE_DIR_LIST /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { _gui_shadow_box_proc, 0, 0, 305, 161, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 152, 8, 1, 1, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 208, 107, 81, 17, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 208, 129, 81, 17, 0, 0, 27, D_EXIT, 0, 0, NULL, NULL, NULL }, { fs_edit_proc, 16, 28, 272, 8, 0, 0, 0, 0, 79, 0, NULL, NULL, NULL }, { fs_flist_proc, 16, 46, 177, 100, 0, 0, 0, D_EXIT, 0, 0, fs_flist_getter, NULL, NULL }, { fs_dlist_proc, 208, 46, 81, 52, 0, 0, 0, D_EXIT, 0, 0, fs_dlist_getter, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, #else /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { _gui_shadow_box_proc, 0, 0, 305, 189, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 152, 8, 1, 1, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 64, 160, 81, 17, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 160, 160, 81, 17, 0, 0, 27, D_EXIT, 0, 0, NULL, NULL, NULL }, { fs_edit_proc, 16, 28, 272, 8, 0, 0, 0, 0, 79, 0, NULL, NULL, NULL }, { fs_flist_proc, 16, 46, 273, 100, 0, 0, 0, D_EXIT, 0, 0, fs_flist_getter, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, #endif { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; #define FS_FRAME 0 #define FS_MESSAGE 1 #define FS_OK 2 #define FS_CANCEL 3 #define FS_EDIT 4 #define FS_FILES 5 #ifdef FSEL_HAVE_DIR_LIST /* not all platforms need a directory list */ #define FS_DISKS 6 #define FS_YIELD 7 /* count_disks: * Counts the number of valid drives. */ static int count_disks(void) { int c, i; c = 0; for (i=0; i<26; i++) if (_al_drive_exists(i)) c++; return c; } /* get_x_drive: * Returns the drive letter matching the specified list index. */ static int get_x_drive(int index) { int c, i; c = 0; for (i=0; i<26; i++) { if (_al_drive_exists(i)) { c++; if (c == index) return i; } } return -1; } /* fs_dlist_getter: * Listbox data getter routine for the file selector disk list. */ static char *fs_dlist_getter(int index, int *list_size) { static char d[8]; int pos, c; if (index < 0) { if (list_size) *list_size = count_disks(); return NULL; } c = 'A' + get_x_drive(index+1); if ((c < 'A') || (c > 'Z')) c = 'C'; pos = usetc(d, c); pos += usetc(d+pos, DEVICE_SEPARATOR); pos += usetc(d+pos, OTHER_PATH_SEPARATOR); usetc(d+pos, 0); return d; } /* fs_dlist_proc: * Dialog procedure for the file selector disk list. */ static int fs_dlist_proc(int msg, DIALOG *d, int c) { char *s = file_selector[FS_EDIT].dp; int ret, i, temp; if (msg == MSG_START) { d->d1 = d->d2 = 0; temp = utoupper(ugetc(s)); if (((temp >= 'A') && (temp <= 'Z')) && (ugetat(s, 1) == DEVICE_SEPARATOR)) { temp -= 'A'; for (i=0; id1++; } } ret = _gui_text_list_proc(msg, d, c); if (ret == D_CLOSE) { temp = 'A' + get_x_drive(d->d1+1); if ((temp < 'A') || (temp > 'Z')) temp = 'C'; s += usetc(s, temp); s += usetc(s, DEVICE_SEPARATOR); s += usetc(s, OTHER_PATH_SEPARATOR); usetc(s, 0); object_message(file_selector+FS_FILES, MSG_START, 0); object_message(file_selector+FS_FILES, MSG_DRAW, 0); object_message(file_selector+FS_EDIT, MSG_START, 0); object_message(file_selector+FS_EDIT, MSG_DRAW, 0); return D_O_K; } return ret; } #else #define FS_YIELD 6 #endif /* FSEL_HAVE_DIR_LIST */ /* fs_edit_proc: * Dialog procedure for the file selector editable string. */ static int fs_edit_proc(int msg, DIALOG *d, int c) { char *s = d->dp; int size = (d->d1 + 1) * uwidth_max(U_CURRENT); /* of s (in bytes) */ int list_size; int found = 0; char b[1024], tmp[16]; int ch, attr; int i; if (msg == MSG_START) { canonicalize_filename(b, s, sizeof(b)); ustrzcpy(s, size, b); } if (msg == MSG_KEY) { if ((!ugetc(s)) || (ugetat(s, -1) == DEVICE_SEPARATOR)) ustrzcat(s, size, uconvert_ascii("./", tmp)); canonicalize_filename(b, s, sizeof(b)); ustrzcpy(s, size - ucwidth(OTHER_PATH_SEPARATOR), b); ch = ugetat(s, -1); if ((ch != '/') && (ch != OTHER_PATH_SEPARATOR)) { if (file_exists(s, FA_RDONLY | FA_HIDDEN | FA_DIREC, &attr)) { if (attr & FA_DIREC) put_backslash(s); else return D_CLOSE; } else return D_CLOSE; } object_message(file_selector+FS_FILES, MSG_START, 0); /* did we `cd ..' ? */ if (ustrlen(updir)) { /* now we have to find a directory name equal to updir */ for (i = 0; isize; i++) { if (!ustrcmp(updir, flist->name[i])) { /* we got it ! */ file_selector[FS_FILES].d1 = i; /* we have to know the number of visible lines in the filelist */ /* -1 to avoid an off-by-one problem */ list_size = (file_selector[FS_FILES].h-4) / text_height(font) - 1; if (i>list_size) file_selector[FS_FILES].d2 = i-list_size; else file_selector[FS_FILES].d2 = 0; found = 1; break; /* ok, our work is done... */ } } /* by some strange reason, we didn't find the old directory... */ if (!found) { file_selector[FS_FILES].d1 = 0; file_selector[FS_FILES].d2 = 0; } } /* and continue... */ object_message(file_selector+FS_FILES, MSG_DRAW, 0); object_message(d, MSG_START, 0); object_message(d, MSG_DRAW, 0); return D_O_K; } if (msg == MSG_UCHAR) { if ((c >= 'a') && (c <= 'z')) { if (!ALLEGRO_LFN) c = utoupper(c); } else if (c == '/') { c = OTHER_PATH_SEPARATOR; } else if (ALLEGRO_LFN) { if ((c > 127) || (c < 32)) return D_O_K; } else { if ((c != OTHER_PATH_SEPARATOR) && (c != '_') && (c != DEVICE_SEPARATOR) && (c != '.') && ((c < 'A') || (c > 'Z')) && ((c < '0') || (c > '9'))) return D_O_K; } } return _gui_edit_proc(msg, d, c); } /* ustrfilecmp: * ustricmp for filenames: makes sure that eg "foo.bar" comes before * "foo-1.bar", and also that "foo9.bar" comes before "foo10.bar". */ static int ustrfilecmp(AL_CONST char *s1, AL_CONST char *s2) { int c1, c2; int x1, x2; char *t1, *t2; for (;;) { c1 = utolower(ugetxc(&s1)); c2 = utolower(ugetxc(&s2)); if ((c1 >= '0') && (c1 <= '9') && (c2 >= '0') && (c2 <= '9')) { x1 = ustrtol(s1 - ucwidth(c1), &t1, 10); x2 = ustrtol(s2 - ucwidth(c2), &t2, 10); if (x1 != x2) return x1 - x2; else if (t1 - s1 != t2 - s2) return (t2 - s2) - (t1 - s1); s1 = t1; s2 = t2; } else if (c1 != c2) { if (!c1) return -1; else if (!c2) return 1; else if (c1 == '.') return -1; else if (c2 == '.') return 1; return c1 - c2; } if (!c1) return 0; } } /* fs_flist_putter: * Callback routine for for_each_file() to fill the file selector listbox. */ static int fs_flist_putter(AL_CONST char *str, int attrib, void *check_attrib) { char *s, *ext, *name; int c, c2; s = get_filename(str); fix_filename_case(s); if (!(attrib & FA_DIREC)) { /* Check if file extension matches. */ if (fext_p) { ext = get_extension(s); for (c=0; csize; c++) { if (ugetat(flist->name[c], -1) == OTHER_PATH_SEPARATOR) { if (attrib & FA_DIREC) if (ustrfilecmp(name, flist->name[c]) < 0) break; } else { if (attrib & FA_DIREC) break; if (ustrfilecmp(name, flist->name[c]) < 0) break; } } /* Do we need to allocate more space in the structure? */ /* This doubles the capacity of the array each time, */ /* which gives 'linear' compexity */ if (flist->size == flist->capacity) { flist->capacity *= 2; flist->name = _al_sane_realloc(flist->name, sizeof(char *) * flist->capacity); if (flist->name == NULL) { *allegro_errno = ENOMEM; /* Stop the enumeration by returning non-zero */ return -1; } } /* Shift in preparation for inserting the new entry. */ for (c2=flist->size; c2>c; c2--) flist->name[c2] = flist->name[c2-1]; /* Insert the new entry. */ flist->name[c] = name; flist->size++; } return 0; } /* fs_flist_getter: * Listbox data getter routine for the file selector list. */ static char *fs_flist_getter(int index, int *list_size) { if (index < 0) { if (list_size) *list_size = flist->size; return NULL; } return flist->name[index]; } /* build_attrb_flag: * Returns the cumulative flag for all attributes in state STATE. */ static int build_attrb_flag(attrb_state_t state) { int i, flag = 0; for (i = 0; i < ATTRB_MAX; i++) { if (attrb_state[i] == state) flag |= attrb_flag[i]; } return flag; } /* fs_flist_proc: * Dialog procedure for the file selector list. */ static int fs_flist_proc(int msg, DIALOG *d, int c) { static int recurse_flag = 0; char *s = file_selector[FS_EDIT].dp; char tmp[32]; int size = (file_selector[FS_EDIT].d1 + 1) * uwidth_max(U_CURRENT); /* of s (in bytes) */ int sel = d->d1; int i, ret; int ch, count; if (msg == MSG_START) { if (!flist) { flist = _AL_MALLOC(sizeof(FLIST)); if (!flist) { *allegro_errno = ENOMEM; return D_CLOSE; } flist->capacity = FLIST_START_CAPACITY; flist->name = _AL_MALLOC(flist->capacity * sizeof(char *)); if (!flist->name) { *allegro_errno = ENOMEM; return D_CLOSE; } } else { for (i=0; isize; i++) { if (flist->name[i]) { _AL_FREE(flist->name[i]); /* PH add: maybe avoid multiple frees */ flist->name[i] = NULL; } } /* Maybe shrink the structure */ if (flist->capacity > FLIST_UPPER_CAPACITY) { flist->capacity = FLIST_UPPER_CAPACITY; flist->name = _al_sane_realloc(flist->name, sizeof(char *) * flist->capacity); if (!flist) { /* Oops! Should never happen, I hope */ *allegro_errno = ENOMEM; return D_CLOSE; } } } flist->size = 0; replace_filename(flist->dir, s, uconvert_ascii("*.*", tmp), sizeof(flist->dir)); /* The semantics of the attributes passed to file_select_ex() is * different from that of for_each_file_ex() in one case: when * the 'd' attribute is not mentioned in the set of characters, * the other attributes are not taken into account for directories, * i.e the directories are all included. So we can't filter with * for_each_file_ex() in that case. */ if (attrb_state[ATTRB_DIREC] == ATTRB_ABSENT) for_each_file_ex(flist->dir, 0 /* accept all dirs */, FA_LABEL, fs_flist_putter, (void *)1UL /* check */); else for_each_file_ex(flist->dir, build_attrb_flag(ATTRB_SET), build_attrb_flag(ATTRB_UNSET) | FA_LABEL, fs_flist_putter, (void *)0UL /* don't check */); usetc(get_filename(flist->dir), 0); d->d1 = d->d2 = 0; sel = 0; } if (msg == MSG_END) { if (flist) { for (i=0; isize; i++) if (flist->name[i]) _AL_FREE(flist->name[i]); _AL_FREE(flist->name); _AL_FREE(flist); flist = NULL; } } recurse_flag++; ret = _gui_text_list_proc(msg, d, c); /* call the parent procedure */ recurse_flag--; if (((sel != d->d1) || (ret == D_CLOSE)) && (recurse_flag == 0)) { replace_filename(s, flist->dir, flist->name[d->d1], size); /* check if we want to `cd ..' */ if ((!ustrncmp(flist->name[d->d1], uconvert_ascii("..", tmp), 2)) && (ret == D_CLOSE)) { /* let's remember the previous directory */ usetc(updir, 0); i = ustrlen(flist->dir); count = 0; while (i>0) { ch = ugetat(flist->dir, i); if ((ch == '/') || (ch == OTHER_PATH_SEPARATOR)) { if (++count == 2) break; } uinsert(updir, 0, ch); i--; } /* ok, we have the dirname in updir */ } else { usetc(updir, 0); } object_message(file_selector+FS_EDIT, MSG_START, 0); object_message(file_selector+FS_EDIT, MSG_DRAW, 0); if (ret == D_CLOSE) return object_message(file_selector+FS_EDIT, MSG_KEY, 0); } return ret; } /* parse_extension_string: * Parses the extension string, possibly containing attribute characters. */ static void parse_extension_string(AL_CONST char *ext) { attrb_state_t state; char ext_tokens[32], attrb_char[32]; char *last, *p, *attrb_p; int c, c2, i; fext = _al_ustrdup(ext); if (!fext) return; /* Tokenize the extension string and record the pointers to the * beginning of each token in a dynamically growing array. * ???? We rely on the implementation of ustrtok_r() which writes * null characters in the string to delimit the tokens. Yuck. */ c = usetc(ext_tokens, ' '); c += usetc(ext_tokens+c, ','); c += usetc(ext_tokens+c, ';'); usetc(ext_tokens+c, 0); p = ustrtok_r(fext, ext_tokens, &last); if (!ugetc(p)) return; i = 0; fext_size = 0; fext_p = NULL; attrb_p = NULL; do { /* Set of attribute characters. */ if (ugetc(p) == '/') { attrb_p = p + ucwidth('/'); continue; } /* Dynamically grow the array if needed. */ if (i >= fext_size) { fext_size = (fext_size ? fext_size*2 : 2); fext_p = (char **)_al_sane_realloc(fext_p, fext_size * sizeof(char *)); } /* Record a pointer to the beginning of the token. */ fext_p[i++] = p; } while ((p = ustrtok_r(NULL, ext_tokens, &last))); /* This is the meaningful size now. */ fext_size = i; if (attrb_p) { state = ATTRB_SET; c = usetc(attrb_char, 'r'); c += usetc(attrb_char+c, 'h'); c += usetc(attrb_char+c, 's'); c += usetc(attrb_char+c, 'd'); c += usetc(attrb_char+c, 'a'); c += usetc(attrb_char+c, '+'); c += usetc(attrb_char+c, '-'); usetc(attrb_char+c, 0); /* Scan the string. */ while ((c = utolower(ugetx(&attrb_p)))) { p = attrb_char; for (i = 0; (c2 = ugetx(&p)); i++) { if (c == c2) { if (i < ATTRB_MAX) attrb_state[i] = state; else state = (i == ATTRB_MAX) ? ATTRB_SET : ATTRB_UNSET; break; } } } } } /* stretch_dialog: * Stretch the dialog horizontally and vertically to the specified * size and the font in use. * (all the magic numbers come from the "historical" file selector) */ static void stretch_dialog(DIALOG *d, int width, int height) { int font_w, font_h, hpad, vpad; char tmp[16]; #ifdef FSEL_HAVE_DIR_LIST /* horizontal settings */ font_w = text_length(font, uconvert_ascii("A", tmp)); if (width == 0) width = 0.95*SCREEN_W + 1; hpad = 0.05*width + 1; d[FS_FRAME].w = width; d[FS_FRAME].x = 0; d[FS_MESSAGE].w = width - 2; d[FS_MESSAGE].x = 1; d[FS_EDIT].w = d[FS_FRAME].w - 2*hpad - 1; d[FS_EDIT].x = hpad; d[FS_CANCEL].w = 10*font_w + 1; d[FS_CANCEL].x = d[FS_FRAME].w - hpad - d[FS_CANCEL].w; d[FS_OK].w = d[FS_CANCEL].w; d[FS_OK].x = d[FS_CANCEL].x; d[FS_DISKS].w = d[FS_OK].w; d[FS_DISKS].x = d[FS_OK].x; d[FS_FILES].x = hpad; d[FS_FILES].w = d[FS_CANCEL].x - d[FS_FILES].x - hpad + 1; d[FS_YIELD].x = 0; /* vertical settings */ font_h = text_height(font); if (height == 0) height = 0.80*SCREEN_H + 1; vpad = 0.05*height; d[FS_FRAME].h = height; d[FS_FRAME].y = 0; d[FS_MESSAGE].h = font_h; d[FS_MESSAGE].y = vpad; d[FS_EDIT].h = font_h; d[FS_EDIT].y = 2*vpad + d[FS_MESSAGE].h + 4; d[FS_CANCEL].h = font_h + 9; d[FS_CANCEL].y = d[FS_FRAME].h - 2*vpad - d[FS_CANCEL].h + 1; d[FS_OK].h = d[FS_CANCEL].h; d[FS_OK].y = d[FS_CANCEL].y - vpad/2 - d[FS_OK].h - 1; d[FS_DISKS].y = d[FS_EDIT].y + d[FS_EDIT].h + vpad + 2; d[FS_DISKS].h = d[FS_OK].y - d[FS_DISKS].y - vpad - 1; d[FS_FILES].y = d[FS_DISKS].y; d[FS_FILES].h = d[FS_FRAME].h - d[FS_FILES].y - 2*vpad + 1; d[FS_YIELD].y = 0; #else /* horizontal settings */ font_w = text_length(font, uconvert_ascii("A", tmp)); if (width == 0) width = 0.95*SCREEN_W + 1; hpad = 0.05*width + 1; d[FS_FRAME].w = width; d[FS_FRAME].x = 0; d[FS_MESSAGE].w = width - 2; d[FS_MESSAGE].x = 1; d[FS_EDIT].w = d[FS_FRAME].w - 2*hpad - 1; d[FS_EDIT].x = hpad; d[FS_FILES].w = d[FS_FRAME].w - 2*hpad; d[FS_FILES].x = hpad; d[FS_OK].w = 10*font_w + 1; d[FS_OK].x = (d[FS_FRAME].w - 2*d[FS_OK].w - hpad + 1)/2; d[FS_CANCEL].w = d[FS_OK].w; d[FS_CANCEL].x = d[FS_FRAME].w - d[FS_OK].x - d[FS_CANCEL].w; d[FS_YIELD].x = 0; /* vertical settings */ font_h = text_height(font); if (height == 0) height = 0.95*SCREEN_H - 1; vpad = 0.04*height + 1; d[FS_FRAME].h = height; d[FS_FRAME].y = 0; d[FS_MESSAGE].h = font_h; d[FS_MESSAGE].y = vpad; d[FS_EDIT].h = font_h; d[FS_EDIT].y = 2*vpad + d[FS_MESSAGE].h + 4; d[FS_OK].h = font_h + 9; d[FS_OK].y = d[FS_FRAME].h - 1.5*vpad - d[FS_OK].h; d[FS_CANCEL].h = d[FS_OK].h; d[FS_CANCEL].y = d[FS_OK].y; d[FS_FILES].y = d[FS_EDIT].y + d[FS_EDIT].h + vpad + 2; d[FS_FILES].h = d[FS_OK].y - d[FS_FILES].y - vpad - 6; d[FS_YIELD].y = 0; #endif } /* file_select_ex: * Displays the Allegro file selector, with the message as caption. * Allows the user to select a file, and stores the selection in the * path buffer, whose length in bytes is given by size and should have * room for at least 80 characters. The files are filtered according to * the file extensions in ext. Passing NULL includes all files, "PCX;BMP" * includes only files with .PCX or .BMP extensions. Returns zero if it * was closed with the Cancel button or non-zero if it was OK'd. */ int file_select_ex(AL_CONST char *message, char *path, AL_CONST char *ext, int size, int width, int height) { static attrb_state_t default_attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE; int ret; char *p, *backup; char tmp[32]; ASSERT(message); ASSERT(path); backup = _al_ustrdup(path); if (!backup) return FALSE; if (width == OLD_FILESEL_WIDTH) width = 305; #ifdef FSEL_HAVE_DIR_LIST if (height == OLD_FILESEL_HEIGHT) height = 161; #else if (height == OLD_FILESEL_HEIGHT) height = 189; #endif /* for fs_dlist_proc() */ ASSERT(size >= 4 * uwidth_max(U_CURRENT)); usetc(updir, 0); file_selector[FS_MESSAGE].dp = (char *)message; file_selector[FS_EDIT].d1 = size/uwidth_max(U_CURRENT) - 1; file_selector[FS_EDIT].dp = path; file_selector[FS_OK].dp = (void*)get_config_text("OK"); file_selector[FS_CANCEL].dp = (void*)get_config_text("Cancel"); /* Set default attributes. */ memcpy(attrb_state, default_attrb_state, sizeof(default_attrb_state)); /* Parse extension string. */ if (ext && ugetc(ext)) parse_extension_string(ext); if (!ugetc(path)) { #ifdef FSEL_HAVE_DIR_LIST int drive = _al_getdrive(); #else int drive = 0; #endif _al_getdcwd(drive, path, size - ucwidth(OTHER_PATH_SEPARATOR)); fix_filename_case(path); fix_filename_slashes(path); put_backslash(path); } clear_keybuf(); do { } while (gui_mouse_b()); stretch_dialog(file_selector, width, height); centre_dialog(file_selector); set_dialog_color(file_selector, gui_fg_color, gui_bg_color); ret = popup_dialog(file_selector, FS_EDIT); if (fext) { _AL_FREE(fext); fext = NULL; } if (fext_p) { _AL_FREE(fext_p); fext_p = NULL; } if (ret == FS_CANCEL) { ustrcpy(path, backup); _AL_FREE(backup); return FALSE; } _AL_FREE(backup); if (ugetc(get_filename(path))) { p = get_extension(path); if ((!ugetc(p)) && (ext) && (ugetc(ext)) && (!ustrpbrk(ext, uconvert_ascii(" ,;", tmp)))) { size -= ((long)p - (long)path + ucwidth('.')); if (size >= uwidth_max(U_CURRENT) + ucwidth(0)) { /* do not end with '.' */ p += usetc(p, '.'); ustrzcpy(p, size, ext); } } } return TRUE; } allegro-4.4.3.1/src/blit.c0000664000175000017500000006650313437077643014177 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Blitting functions. * * By Shawn Hargreaves. * * Dithering code by James Hyman. * * Transparency preserving code by Elias Pschernig. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* get_replacement_mask_color: * Helper function to get a replacement color for the bitmap's mask color. */ static int get_replacement_mask_color(BITMAP *bmp) { int depth, c, g = 0; depth = bitmap_color_depth(bmp); if (depth == 8) { if (rgb_map) return rgb_map->data[31][1][31]; else return bestfit_color(_current_palette, 63, 1, 63); } else { do c = makecol_depth(depth, 255, ++g, 255); while (c == bitmap_mask_color(bmp)); return c; } } /* blit_from_256: * Expands 256 color images onto a truecolor destination. */ static void blit_from_256(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { #ifdef ALLEGRO_COLOR8 int *dest_palette_color; uintptr_t s, d; unsigned char *ss; int x, y, c, rc; /* lookup table avoids repeated color format conversions */ if (_color_conv & COLORCONV_KEEP_TRANS) { dest_palette_color = _AL_MALLOC_ATOMIC(256*sizeof(int)); memcpy(dest_palette_color, _palette_expansion_table(bitmap_color_depth(dest)), 256*sizeof(int)); rc = get_replacement_mask_color(dest); dest_palette_color[MASK_COLOR_8] = bitmap_mask_color(dest); for (c=0; c<256; c++) { if ((c != MASK_COLOR_8) && (dest_palette_color[c] == bitmap_mask_color(dest))) dest_palette_color[c] = rc; } } else dest_palette_color = _palette_expansion_table(bitmap_color_depth(dest)); /* worker macro */ #define EXPAND_BLIT(bits, dsize) \ { \ if (is_memory_bitmap(src)) { \ /* fast version when reading from memory bitmap */ \ bmp_select(dest); \ \ for (y=0; yline[s_y+y] + s_x; \ d = bmp_write_line(dest, d_y+y) + d_x*dsize; \ \ for (x=0; x 255) n[i] = 255; if (n[i] < 0) n[i] = 0; } /* find the nearest matching colour */ nc = makecol8(n[0], n[1], n[2]); if (_color_conv & COLORCONV_KEEP_TRANS) { if (c == bitmap_mask_color(src)) putpixel(dest, d_x+x, d_y+y, bitmap_mask_color(dest)); else if (nc == bitmap_mask_color(dest)) putpixel(dest, d_x+x, d_y+y, rc); else putpixel(dest, d_x+x, d_y+y, nc); } else { putpixel(dest, d_x+x, d_y+y, nc); } v[0] = getr8(nc); v[1] = getg8(nc); v[2] = getb8(nc); /* calculate the error and store it */ for (i=0; i<3; i++) { e[i] = n[i] - v[i]; errpixel[i] = (int)((e[i] * 3)/8); errnextline[i][x] += errpixel[i]; if (x != w-1) errnextline[i][x+1] = (int)(e[i]/4); } } /* update error buffers */ for (i=0; i<3; i++) { memcpy(errline[i], errnextline[i], sizeof(int) * w); memset(errnextline[i], 0, sizeof(int) * w); } } _drawing_mode = prev_drawmode; getout: for (i=0; i<3; i++) { if (errline[i]) _AL_FREE(errline[i]); if (errnextline[i]) _AL_FREE(errnextline[i]); } } #endif /* blit_from_15: * Converts 15 bpp images onto some other destination format. */ static void blit_from_15(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { #ifdef ALLEGRO_COLOR16 int x, y, c, r, g, b; uintptr_t s, d; switch (bitmap_color_depth(dest)) { #ifdef ALLEGRO_COLOR8 case 8: if (_color_conv & COLORCONV_DITHER_PAL) dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); else CONVERT_BLIT(15, sizeof(int16_t), 8, 1) break; #endif case 16: CONVERT_BLIT(15, sizeof(int16_t), 16, sizeof(int16_t)) break; #ifdef ALLEGRO_COLOR24 case 24: CONVERT_BLIT(15, sizeof(int16_t), 24, 3) break; #endif #ifdef ALLEGRO_COLOR32 case 32: CONVERT_BLIT(15, sizeof(int16_t), 32, sizeof(int32_t)) break; #endif } #endif } /* blit_from_16: * Converts 16 bpp images onto some other destination format. */ static void blit_from_16(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { #ifdef ALLEGRO_COLOR16 int x, y, c, r, g, b; uintptr_t s, d; switch (bitmap_color_depth(dest)) { #ifdef ALLEGRO_COLOR8 case 8: if (_color_conv & COLORCONV_DITHER_PAL) dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); else CONVERT_BLIT(16, sizeof(int16_t), 8, 1) break; #endif case 15: CONVERT_BLIT(16, sizeof(int16_t), 15, sizeof(int16_t)) break; #ifdef ALLEGRO_COLOR24 case 24: CONVERT_BLIT(16, sizeof(int16_t), 24, 3) break; #endif #ifdef ALLEGRO_COLOR32 case 32: CONVERT_BLIT(16, sizeof(int16_t), 32, sizeof(int32_t)) break; #endif } #endif } /* blit_from_24: * Converts 24 bpp images onto some other destination format. */ static void blit_from_24(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { #ifdef ALLEGRO_COLOR24 int x, y, c, r, g, b; uintptr_t s, d; switch (bitmap_color_depth(dest)) { #ifdef ALLEGRO_COLOR8 case 8: if (_color_conv & COLORCONV_DITHER_PAL) dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); else CONVERT_BLIT(24, 3, 8, 1); break; #endif #ifdef ALLEGRO_COLOR16 case 15: if (_color_conv & COLORCONV_DITHER_HI) CONVERT_DITHER_BLIT(24, 3, 15, sizeof(int16_t)) else CONVERT_BLIT(24, 3, 15, sizeof(int16_t)) break; case 16: if (_color_conv & COLORCONV_DITHER_HI) CONVERT_DITHER_BLIT(24, 3, 16, sizeof(int16_t)) else CONVERT_BLIT(24, 3, 16, sizeof(int16_t)) break; #endif #ifdef ALLEGRO_COLOR32 case 32: CONVERT_BLIT(24, 3, 32, sizeof(int32_t)) break; #endif } #endif } /* blit_from_32: * Converts 32 bpp images onto some other destination format. */ static void blit_from_32(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { #ifdef ALLEGRO_COLOR32 int x, y, c, r, g, b; uintptr_t s, d; switch (bitmap_color_depth(dest)) { #ifdef ALLEGRO_COLOR8 case 8: if (_color_conv & COLORCONV_DITHER_PAL) dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); else CONVERT_BLIT(32, sizeof(int32_t), 8, 1) break; #endif #ifdef ALLEGRO_COLOR16 case 15: if (_color_conv & COLORCONV_DITHER_HI) CONVERT_DITHER_BLIT(32, sizeof(int32_t), 15, sizeof(int16_t)) else CONVERT_BLIT(32, sizeof(int32_t), 15, sizeof(int16_t)) break; case 16: if (_color_conv & COLORCONV_DITHER_HI) CONVERT_DITHER_BLIT(32, sizeof(int32_t), 16, sizeof(int16_t)) else CONVERT_BLIT(32, sizeof(int32_t), 16, sizeof(int16_t)) break; #endif #ifdef ALLEGRO_COLOR24 case 24: CONVERT_BLIT(32, sizeof(int32_t), 24, 3) break; #endif } #endif } /* blit_to_or_from_modex: * Converts between truecolor and planar mode-X bitmaps. This function is * painfully slow, but I don't think it is something that people will need * to do very often... */ static void blit_to_or_from_modex(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { #ifdef ALLEGRO_GFX_HAS_VGA int x, y, c, r, g, b; int src_depth = bitmap_color_depth(src); int dest_depth = bitmap_color_depth(dest); int prev_drawmode = _drawing_mode; _drawing_mode = DRAW_MODE_SOLID; if ((src_depth != 8) && (_color_conv & COLORCONV_DITHER_PAL)) dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h); else { for (y=0; yid & BMP_ID_NOBLIT) { /* with single-banked cards we have to use a temporary bitmap */ tmp = create_bitmap(w, h); if (tmp) { src->vtable->blit_to_memory(src, tmp, s_x, s_y, 0, 0, w, h); dest->vtable->blit_from_memory(tmp, dest, 0, 0, d_x, d_y, w, h); destroy_bitmap(tmp); } } else { /* check which way round to do the blit */ sx = s_x + src->x_ofs; sy = s_y + src->y_ofs; dx = d_x + dest->x_ofs; dy = d_y + dest->y_ofs; if ((sx+w <= dx) || (dx+w <= sx) || (sy+h <= dy) || (dy+h <= sy)) dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); else if ((sy > dy) || ((sy == dy) && (sx > dx))) dest->vtable->blit_to_self_forward(src, dest, s_x, s_y, d_x, d_y, w, h); else if ((sx != dx) || (sy != dy)) dest->vtable->blit_to_self_backward(src, dest, s_x, s_y, d_x, d_y, w, h); } } /* helper for clipping a blit rectangle */ #define BLIT_CLIP() \ /* check for ridiculous cases */ \ if ((s_x >= src->w) || (s_y >= src->h) || \ (d_x >= dest->cr) || (d_y >= dest->cb)) \ return; \ \ /* clip src left */ \ if (s_x < 0) { \ w += s_x; \ d_x -= s_x; \ s_x = 0; \ } \ \ /* clip src top */ \ if (s_y < 0) { \ h += s_y; \ d_y -= s_y; \ s_y = 0; \ } \ \ /* clip src right */ \ if (s_x+w > src->w) \ w = src->w - s_x; \ \ /* clip src bottom */ \ if (s_y+h > src->h) \ h = src->h - s_y; \ \ /* clip dest left */ \ if (d_x < dest->cl) { \ d_x -= dest->cl; \ w += d_x; \ s_x -= d_x; \ d_x = dest->cl; \ } \ \ /* clip dest top */ \ if (d_y < dest->ct) { \ d_y -= dest->ct; \ h += d_y; \ s_y -= d_y; \ d_y = dest->ct; \ } \ \ /* clip dest right */ \ if (d_x+w > dest->cr) \ w = dest->cr - d_x; \ \ /* clip dest bottom */ \ if (d_y+h > dest->cb) \ h = dest->cb - d_y; \ \ /* bottle out if zero size */ \ if ((w <= 0) || (h <= 0)) \ return; /* blit: * Copies an area of the source bitmap to the destination bitmap. s_x and * s_y give the top left corner of the area of the source bitmap to copy, * and d_x and d_y give the position in the destination bitmap. w and h * give the size of the area to blit. This routine respects the clipping * rectangle of the destination bitmap, and will work correctly even when * the two memory areas overlap (ie. src and dest are the same). */ void blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { ASSERT(src); ASSERT(dest); BLIT_CLIP(); if (src->vtable->color_depth != dest->vtable->color_depth) { /* need to do a color conversion */ dest->vtable->blit_between_formats(src, dest, s_x, s_y, d_x, d_y, w, h); } else if (is_same_bitmap(src, dest)) { /* special handling for overlapping regions */ blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); } else if (is_video_bitmap(dest)) { /* drawing onto video bitmaps */ if (is_video_bitmap(src)) dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); else if (is_system_bitmap(src)) dest->vtable->blit_from_system(src, dest, s_x, s_y, d_x, d_y, w, h); else dest->vtable->blit_from_memory(src, dest, s_x, s_y, d_x, d_y, w, h); } else if (is_system_bitmap(dest)) { /* drawing onto system bitmaps */ if (is_video_bitmap(src)) src->vtable->blit_to_system(src, dest, s_x, s_y, d_x, d_y, w, h); else if (is_system_bitmap(src)) dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); else dest->vtable->blit_from_memory(src, dest, s_x, s_y, d_x, d_y, w, h); } else { /* drawing onto memory bitmaps */ if ((is_video_bitmap(src)) || (is_system_bitmap(src))) src->vtable->blit_to_memory(src, dest, s_x, s_y, d_x, d_y, w, h); else dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h); } } END_OF_FUNCTION(blit); /* masked_blit: * Version of blit() that skips zero pixels. The source must be a memory * bitmap, and the source and dest regions must not overlap. */ void masked_blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h) { ASSERT(src); ASSERT(dest); ASSERT(src->vtable->color_depth == dest->vtable->color_depth); BLIT_CLIP(); dest->vtable->masked_blit(src, dest, s_x, s_y, d_x, d_y, w, h); } allegro-4.4.3.1/src/fli.c0000664000175000017500000006604613437077643014021 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * FLI/FLC player. * * By Shawn Hargreaves, based on code provided by Jonathan Tarbox. * * Major portability and reliability improvements by Michael Bukin. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #define FLI_MAGIC1 0xAF11 /* file header magic number */ #define FLI_MAGIC2 0xAF12 /* file magic number (Pro) */ #define FLI_FRAME_MAGIC 0xF1FA /* frame header magic number */ #define FLI_FRAME_PREFIX 0xF100 /* FLC's prefix info */ #define FLI_FRAME_USELESS 0x00A1 /* FLC's garbage frame */ typedef struct FLI_HEADER { long size; unsigned short type; unsigned short frame_count; unsigned short width; unsigned short height; unsigned short bits_a_pixel; unsigned short flags; unsigned short speed; long next_head; long frames_in_table; char reserved[102]; } FLI_HEADER; #define sizeof_FLI_HEADER (4+2+2+2+2+2+2+2+4+4+102) typedef struct FLI_FRAME { unsigned long size; unsigned short type; unsigned short chunks; char pad[8]; } FLI_FRAME; #define sizeof_FLI_FRAME (4+2+2+8) typedef struct FLI_CHUNK { unsigned long size; unsigned short type; } FLI_CHUNK; #define sizeof_FLI_CHUNK (4+2) static int fli_status = FLI_NOT_OPEN; /* current state of the FLI player */ BITMAP *fli_bitmap = NULL; /* current frame of the FLI */ PALETTE fli_palette; /* current palette the FLI is using */ int fli_bmp_dirty_from = INT_MAX; /* what part of fli_bitmap is dirty */ int fli_bmp_dirty_to = INT_MIN; int fli_pal_dirty_from = INT_MAX; /* what part of fli_palette is dirty */ int fli_pal_dirty_to = INT_MIN; int fli_frame = 0; /* current frame number in the FLI */ volatile int fli_timer = 0; /* for timing FLI playback */ static PACKFILE *fli_file = NULL; /* the file we are reading */ static char *fli_filename = NULL; /* name of the file */ static void *fli_mem_data = NULL; /* the memory FLI we are playing */ static int fli_mem_pos = 0; /* position in the memory FLI */ static FLI_HEADER fli_header; /* header structure */ static FLI_FRAME frame_header; /* frame header structure */ static unsigned char _fli_broken_data[3 * 256]; /* data substituted for broken chunks */ /* fli_timer_callback: * Timer interrupt handler for syncing FLI files. */ static void fli_timer_callback(void) { fli_timer++; } END_OF_STATIC_FUNCTION(fli_timer_callback); /* fli_read: * Helper function to get a block of data from the FLI, which can read * from disk or a copy of the FLI held in memory. If buf is set, that is * where it stores the data, otherwise it uses the scratch buffer. Returns * a pointer to the data, or NULL on error. */ static void *fli_read(void *buf, int size) { int result; if (fli_mem_data) { if (buf) memcpy(buf, (char *)fli_mem_data+fli_mem_pos, size); else buf = (char *)fli_mem_data+fli_mem_pos; fli_mem_pos += size; } else { if (!buf) { _grow_scratch_mem(size); buf = _scratch_mem; } result = pack_fread(buf, size, fli_file); if (result != size) return NULL; } return buf; } /* fli_rewind: * Helper function to rewind to the beginning of the FLI file data. * Pass offset from the beginning of the data in bytes. */ static void fli_rewind(int offset) { if (fli_mem_data) { fli_mem_pos = offset; } else { pack_fclose(fli_file); fli_file = pack_fopen(fli_filename, F_READ); if (fli_file) pack_fseek(fli_file, offset); else fli_status = FLI_ERROR; } } /* fli_skip: * Helper function to skip some bytes of the FLI file data. * Pass number of bytes to skip. */ static void fli_skip(int bytes) { if (fli_mem_data) { fli_mem_pos += bytes; } else { pack_fseek(fli_file, bytes); } } /* helpers for reading FLI chunk data */ #if 0 /* the "cast expression as lvalue" extension is deprecated in GCC 3.4 */ #define READ_BYTE_NC(p) (*((unsigned char *)(p))++) #define READ_CHAR_NC(p) (*((signed char *)(p))++) #else #define READ_BYTE_NC(p) (*(unsigned char *)(p)++) #define READ_CHAR_NC(p) (*(signed char *)(p)++) #endif #if (defined ALLEGRO_GCC) && (defined ALLEGRO_LITTLE_ENDIAN) && (!defined ALLEGRO_ARM) && (!defined ALLEGRO_PSP) #if 0 /* the "cast expression as lvalue" extension is deprecated in GCC 3.4 */ #define READ_WORD_NC(p) (*((uint16_t *)(p))++) #define READ_SHORT_NC(p) (*((int16_t *)(p))++) #define READ_ULONG_NC(p) (*((uint32_t *)(p))++) #define READ_LONG_NC(p) (*((int32_t *)(p))++) #else /* we use the "statement-expression" extension instead */ #define READ_WORD_NC(p) ({ uint16_t *__p = (uint16_t *)(p); p+=2; *__p; }) #define READ_SHORT_NC(p) ({ int16_t *__p = (int16_t *)(p); p+=2; *__p; }) #define READ_ULONG_NC(p) ({ uint32_t *__p = (uint32_t *)(p); p+=4; *__p; }) #define READ_LONG_NC(p) ({ int32_t *__p = (int32_t *)(p); p+=4; *__p; }) #endif #else static unsigned short _fli_read_word_nc(unsigned char **p) { unsigned short t; t = (((unsigned short) *((unsigned char*) (*p))) | ((unsigned short) *((unsigned char*) (*p) + 1) << 8)); *p += 2; return t; } static signed short _fli_read_short_nc(unsigned char **p) { unsigned short t = _fli_read_word_nc(p); if (t & (unsigned short) 0x8000) return -(signed short) (~(t - 1) & (unsigned short) 0x7FFF); else return (signed short) t; } static unsigned long _fli_read_ulong_nc(unsigned char **p) { unsigned long t; t = (((unsigned long) *((unsigned char*) (*p))) | ((unsigned long) *((unsigned char*) (*p) + 1) << 8) | ((unsigned long) *((unsigned char*) (*p) + 2) << 16) | ((unsigned long) *((unsigned char*) (*p) + 3) << 24)); *p += 4; return t; } static signed long _fli_read_long_nc(unsigned char **p) { unsigned long t = _fli_read_ulong_nc(p); if (t & (unsigned long) 0x80000000L) return -(signed long) (~(t - 1) & (unsigned long) 0x7FFFFFFFL); else return (signed long) t; } #define READ_WORD_NC(p) _fli_read_word_nc(&(p)) #define READ_SHORT_NC(p) _fli_read_short_nc(&(p)) #define READ_ULONG_NC(p) _fli_read_ulong_nc(&(p)) #define READ_LONG_NC(p) _fli_read_long_nc(&(p)) #endif #define READ_BLOCK_NC(p,pos,size) \ { \ memcpy((pos), (p), (size)); \ (p) += (size); \ } #define READ_RLE_BYTE_NC(p,pos,size) \ memset((pos), READ_BYTE_NC(p), (size)) #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) #define READ_RLE_WORD_NC(p,pos,size) \ { \ int c; \ uint16_t *ptr = (uint16_t*) (pos); \ unsigned short v = READ_WORD_NC(p); \ \ for (c = 0; c < (size); c++) \ *ptr++ = v; \ } #else #define READ_RLE_WORD_NC(p,pos,size) \ { \ int c; \ unsigned char *ptr = (pos); \ unsigned char v1 = READ_BYTE_NC(p); \ unsigned char v2 = READ_BYTE_NC(p); \ \ for (c = 0; c < (size); c++) { \ *ptr++ = v1; \ *ptr++ = v2; \ } \ } #endif /* support for broken chunks (copy reminder of chunk and add zeros) * this needs not be fast because FLI data should not be broken. * p is a pointer to reminder of chunk data * sz is a size of chunk after subtructing size bytes (known to be < 0) * size is how much bytes we need * (size + sz) is how much bytes is left in chunk */ #define FLI_KLUDGE(p,sz,size) \ { \ if (((size) + (sz)) <= 0) { \ memset(_fli_broken_data, 0, (size)); \ } \ else { \ memcpy(_fli_broken_data, (p), (size) + (sz)); \ memset(_fli_broken_data + (size) + (sz), 0, -(sz)); \ } \ (p) = _fli_broken_data; \ } /* do_fli_256_color: * Processes an FLI 256_COLOR chunk */ static void do_fli_256_color(unsigned char *p, int sz) { int packets; int end; int offset; int length; offset = 0; if ((sz -= 2) < 0) return; packets = READ_SHORT_NC(p); while (packets-- > 0) { if ((sz -= 2) < 0) return; offset += READ_BYTE_NC(p); length = READ_BYTE_NC(p); if (length == 0) length = 256; end = offset + length; if (end > PAL_SIZE) return; else if ((sz -= length * 3) < 0) { FLI_KLUDGE(p, sz, length * 3); } fli_pal_dirty_from = MIN(fli_pal_dirty_from, offset); fli_pal_dirty_to = MAX(fli_pal_dirty_to, end-1); for(; offset < end; offset++) { fli_palette[offset].r = READ_BYTE_NC(p) / 4; fli_palette[offset].g = READ_BYTE_NC(p) / 4; fli_palette[offset].b = READ_BYTE_NC(p) / 4; } } } /* do_fli_delta: * Processes an FLI DELTA chunk */ static void do_fli_delta(unsigned char *p, int sz) { int lines; int packets; int size; int y; unsigned char *curr; unsigned char *bitmap_end = fli_bitmap->line[fli_bitmap->h-1] + fli_bitmap->w; y = 0; if ((sz -= 2) < 0) return; lines = READ_SHORT_NC(p); while (lines-- > 0) { /* for each line... */ if ((sz -= 2) < 0) return; packets = READ_SHORT_NC(p); while (packets < 0) { if (packets & 0x4000) y -= packets; else if (y < fli_bitmap->h) fli_bitmap->line[y][fli_bitmap->w-1] = packets & 0xFF; if ((sz -= 2) < 0) return; packets = READ_SHORT_NC(p); } if (y >= fli_bitmap->h) return; curr = fli_bitmap->line[y]; fli_bmp_dirty_from = MIN(fli_bmp_dirty_from, y); fli_bmp_dirty_to = MAX(fli_bmp_dirty_to, y); while (packets-- > 0) { if ((sz -= 2) < 0) return; curr += READ_BYTE_NC(p); /* skip bytes */ size = READ_CHAR_NC(p); if (size > 0) { /* copy size words */ if ((curr + size * 2) > bitmap_end) return; else if ((sz -= size * 2) < 0) { FLI_KLUDGE(p, sz, size * 2); } READ_BLOCK_NC(p, curr, size*2); curr += size*2; } else if (size < 0) { /* repeat word -size times */ size = -size; if ((curr + size * 2) > bitmap_end) return; else if ((sz -= 2) < 0) { FLI_KLUDGE(p, sz, 2); } READ_RLE_WORD_NC(p, curr, size); curr += size*2; } } y++; } } /* do_fli_color: * Processes an FLI COLOR chunk */ static void do_fli_color(unsigned char *p, int sz) { int packets; int end; int offset; int length; offset = 0; if ((sz -= 2) < 0) return; packets = READ_SHORT_NC(p); while (packets-- > 0) { if ((sz -= 2) < 0) return; offset += READ_BYTE_NC(p); length = READ_BYTE_NC(p); if (length == 0) length = 256; end = offset + length; if (end > PAL_SIZE) return; else if ((sz -= length * 3) < 0) { FLI_KLUDGE(p, sz, length * 3); } fli_pal_dirty_from = MIN(fli_pal_dirty_from, offset); fli_pal_dirty_to = MAX(fli_pal_dirty_to, end-1); for(; offset < end; offset++) { fli_palette[offset].r = READ_BYTE_NC(p); fli_palette[offset].g = READ_BYTE_NC(p); fli_palette[offset].b = READ_BYTE_NC(p); } } } /* do_fli_lc: * Processes an FLI LC chunk */ static void do_fli_lc(unsigned char *p, int sz) { int lines; int packets; int size; int y; unsigned char *curr; unsigned char *bitmap_end = fli_bitmap->line[fli_bitmap->h-1] + fli_bitmap->w; if ((sz -= 4) < 0) return; y = READ_WORD_NC(p); lines = READ_SHORT_NC(p); if (y >= fli_bitmap->h) return; else if ((y + lines) > fli_bitmap->h) lines = fli_bitmap->h - y; fli_bmp_dirty_from = MIN(fli_bmp_dirty_from, y); fli_bmp_dirty_to = MAX(fli_bmp_dirty_to, y+lines-1); while (lines-- > 0) { /* for each line... */ if ((sz -= 1) < 0) return; packets = READ_BYTE_NC(p); curr = fli_bitmap->line[y]; while (packets-- > 0) { if ((sz -= 2) < 0) return; curr += READ_BYTE_NC(p); /* skip bytes */ size = READ_CHAR_NC(p); if (size > 0) { /* copy size bytes */ if ((curr + size) > bitmap_end) return; else if ((sz -= size) < 0) { FLI_KLUDGE(p, sz, size); } READ_BLOCK_NC(p, curr, size); curr += size; } else if (size < 0) { /* repeat byte -size times */ size = -size; if ((curr + size) > bitmap_end) return; else if ((sz -= 1) < 0) { FLI_KLUDGE(p, sz, 1); } READ_RLE_BYTE_NC(p, curr, size); curr += size; } } y++; } } /* do_fli_black: * Processes an FLI BLACK chunk */ static void do_fli_black(void) { clear_bitmap(fli_bitmap); fli_bmp_dirty_from = 0; fli_bmp_dirty_to = fli_bitmap->h-1; } /* do_fli_brun: * Processes an FLI BRUN chunk */ static void do_fli_brun(unsigned char *p, int sz) { int packets; int size; int y; unsigned char *curr; unsigned char *bitmap_end = fli_bitmap->line[fli_bitmap->h-1] + fli_bitmap->w; fli_bmp_dirty_from = 0; fli_bmp_dirty_to = fli_bitmap->h-1; for (y=0; yh; y++) { /* for each line... */ if ((sz -= 1) < 0) return; packets = READ_BYTE_NC(p); curr = fli_bitmap->line[y]; if (packets == 0) { /* FLC chunk (fills the whole line) */ unsigned char *line_end = curr + fli_bitmap->w; while (curr < line_end) { if ((sz -= 1) < 0) return; size = READ_CHAR_NC(p); if (size < 0) { /* copy -size bytes */ size = -size; if ((curr + size) > bitmap_end) return; else if ((sz -= size) < 0) { FLI_KLUDGE(p, sz, size); } READ_BLOCK_NC(p, curr, size); curr += size; } else if (size > 0) { /* repeat byte size times */ if ((curr + size) > bitmap_end) return; else if ((sz -= 1) < 0) { FLI_KLUDGE(p, sz, 1); } READ_RLE_BYTE_NC(p, curr, size); curr += size; } } } else { /* FLI chunk (uses packets count) */ while (packets-- > 0) { if ((sz -= 1) < 0) return; size = READ_CHAR_NC(p); if (size < 0) { /* copy -size bytes */ size = -size; if ((curr + size) > bitmap_end) return; if ((sz -= size) < 0) { FLI_KLUDGE(p, sz, size); } READ_BLOCK_NC(p, curr, size); curr += size; } else if (size > 0) { /* repeat byte size times */ if ((curr + size) > bitmap_end) return; if ((sz -= 1) < 0) { FLI_KLUDGE(p, sz, 1); } READ_RLE_BYTE_NC(p, curr, size); curr += size; } } } } } /* do_fli_copy: * Processes an FLI COPY chunk */ static void do_fli_copy(unsigned char *p, int sz) { int y; if ((sz -= (fli_bitmap->w * fli_bitmap->h)) < 0) return; for (y=0; yh; y++) READ_BLOCK_NC(p, fli_bitmap->line[y], fli_bitmap->w); fli_bmp_dirty_from = 0; fli_bmp_dirty_to = fli_bitmap->h-1; } /* _fli_read_header: * Reads FLI file header (0 -- OK). */ static int _fli_read_header(FLI_HEADER *header) { unsigned char *p = fli_read(NULL, sizeof_FLI_HEADER); if (!p) return -1; header->size = READ_LONG_NC(p); header->type = READ_WORD_NC(p); header->frame_count = READ_WORD_NC(p); header->width = READ_WORD_NC(p); header->height = READ_WORD_NC(p); header->bits_a_pixel = READ_WORD_NC(p); header->flags = READ_WORD_NC(p); header->speed = READ_WORD_NC(p); header->next_head = READ_LONG_NC(p); header->frames_in_table = READ_LONG_NC(p); return ((header->size < sizeof_FLI_HEADER) ? -1 : 0); } /* _fli_read_frame: * Reads FLI frame header (0 -- OK). */ static int _fli_read_frame(FLI_FRAME *frame) { unsigned char *p = fli_read(NULL, sizeof_FLI_FRAME); if (!p) return -1; frame->size = READ_ULONG_NC(p); frame->type = READ_WORD_NC(p); frame->chunks = READ_WORD_NC(p); return ((frame->size < sizeof_FLI_FRAME) ? -1 : 0); } /* _fli_parse_chunk: * Parses one FLI chunk. */ static int _fli_parse_chunk(FLI_CHUNK *chunk, unsigned char *p, unsigned long frame_size) { if (frame_size < sizeof_FLI_CHUNK) return -1; chunk->size = READ_ULONG_NC(p); chunk->type = READ_WORD_NC(p); return (((chunk->size < sizeof_FLI_CHUNK) || (chunk->size > frame_size)) ? -1 : 0); } /* read_frame: * Advances to the next frame in the FLI. */ static void read_frame(void) { unsigned char *p; FLI_CHUNK chunk; int c, sz, frame_size; if (fli_status != FLI_OK) return; /* clear the first frame (we need it for looping, because we don't support ring frame) */ if (fli_frame == 0) { clear_bitmap(fli_bitmap); fli_bmp_dirty_from = 0; fli_bmp_dirty_to = fli_bitmap->h-1; } get_another_frame: /* read the frame header */ if (_fli_read_frame(&frame_header) != 0) { fli_status = FLI_ERROR; return; } /* skip FLC's useless frame */ if ((frame_header.type == FLI_FRAME_PREFIX) || (frame_header.type == FLI_FRAME_USELESS)) { fli_skip(frame_header.size-sizeof_FLI_FRAME); if (++fli_frame >= fli_header.frame_count) return; goto get_another_frame; } if (frame_header.type != FLI_FRAME_MAGIC) { fli_status = FLI_ERROR; return; } /* bytes left in this frame */ frame_size = frame_header.size - sizeof_FLI_FRAME; /* return if there is no data in the frame */ if (frame_size == 0) { fli_frame++; return; } /* read the frame data */ p = fli_read(NULL, frame_size); if (!p) { fli_status = FLI_ERROR; return; } /* now to decode it */ for (c=0; cw, 1+fli_bmp_dirty_to-fli_bmp_dirty_from); } reset_fli_variables(); if (callback) { ret = (*callback)(); if (ret != FLI_OK) break; } ret = next_fli_frame(loop); while (fli_timer <= 0) { /* wait a bit */ rest(0); } } close_fli(); return (ret == FLI_EOF) ? FLI_OK : ret; } /* play_fli: * Top level FLI playing function. Plays the specified file, displaying * it at the top left corner of the specified bitmap. If the callback * function is not NULL it will be called for each frame in the file, and * can return zero to continue playing or non-zero to stop the FLI. If * loop is non-zero the player will cycle through the animation (in this * case the callback function is the only way to stop the player). Returns * one of the FLI status constants, or the value returned by the callback * if this is non-zero. If you need to distinguish between the two, the * callback should return positive integers, since the FLI status values * are zero or negative. */ int play_fli(AL_CONST char *filename, BITMAP *bmp, int loop, int (*callback)(void)) { ASSERT(filename); ASSERT(bmp); if (open_fli(filename) != FLI_OK) return FLI_ERROR; return do_play_fli(bmp, loop, callback); } /* play_fli_pf: * Like play_fli(), but loads fli from the given packfile. * Automatic looping is currently not supported, because there is no way * to rewind packfile without knowing how to reopen it. */ int play_fli_pf(PACKFILE *fp, BITMAP *bmp, int (*callback)(void)) { ASSERT(fp); ASSERT(bmp); if (open_fli_pf(fp) != FLI_OK) return FLI_ERROR; return do_play_fli(bmp, 0, callback); } /* play_memory_fli: * Like play_fli(), but for files which have already been loaded into * memory. Pass a pointer to the memory containing the FLI data. */ int play_memory_fli(void *fli_data, BITMAP *bmp, int loop, int (*callback)(void)) { ASSERT(fli_data); ASSERT(bmp); if (open_memory_fli(fli_data) != FLI_OK) return FLI_ERROR; return do_play_fli(bmp, loop, callback); } /* do_open_fli: * Worker function used by open_fli() and open_memory_fli(). */ static int do_open_fli(void) { long speed; /* read the header */ if (_fli_read_header(&fli_header) != 0) { close_fli(); return FLI_ERROR; } /* check magic numbers */ if (((fli_header.bits_a_pixel != 8) && (fli_header.bits_a_pixel != 0)) || ((fli_header.type != FLI_MAGIC1) && (fli_header.type != FLI_MAGIC2))) { close_fli(); return FLI_ERROR; } if (fli_header.width == 0) fli_header.width = 320; if (fli_header.height == 0) fli_header.height = 200; /* create the frame bitmap */ fli_bitmap = create_bitmap_ex(8, fli_header.width, fli_header.height); if (!fli_bitmap) { close_fli(); return FLI_ERROR; } reset_fli_variables(); fli_frame = 0; fli_timer = 2; fli_status = FLI_OK; /* install the timer handler */ LOCK_VARIABLE(fli_timer); LOCK_FUNCTION(fli_timer_callback); if (fli_header.type == FLI_MAGIC1) speed = BPS_TO_TIMER(70) * (long)fli_header.speed; else speed = MSEC_TO_TIMER((long)fli_header.speed); if (speed == 0) speed = BPS_TO_TIMER(70); install_int_ex(fli_timer_callback, speed); return fli_status; } /* open_fli: * Opens an FLI file ready for playing. */ int open_fli(AL_CONST char *filename) { ASSERT(filename); if (fli_status != FLI_NOT_OPEN) return FLI_ERROR; if (fli_filename) { _AL_FREE(fli_filename); fli_filename = NULL; } fli_filename = _al_ustrdup(filename); if (!fli_filename) return FLI_ERROR; fli_file = pack_fopen(fli_filename, F_READ); if (!fli_file) return FLI_ERROR; return do_open_fli(); } /* open_fli_pf: * Opens an FLI from packfile stream ready for playing. */ int open_fli_pf(PACKFILE *fp) { ASSERT(fp); if (fli_status != FLI_NOT_OPEN) return FLI_ERROR; if (fli_filename) { _AL_FREE(fli_filename); fli_filename = NULL; } fli_file = fp; if (!fli_file) return FLI_ERROR; return do_open_fli(); } /* open_memory_fli: * Like open_fli(), but for files which have already been loaded into * memory. Pass a pointer to the memory containing the FLI data. */ int open_memory_fli(void *fli_data) { ASSERT(fli_data); if (fli_status != FLI_NOT_OPEN) return FLI_ERROR; fli_mem_data = fli_data; fli_mem_pos = 0; return do_open_fli(); } /* close_fli: * Shuts down the FLI player at the end of the file. */ void close_fli(void) { remove_int(fli_timer_callback); if (fli_file) { /* if fli_filename is NULL this means that the packfile was * provided by external program. */ if (fli_filename) pack_fclose(fli_file); fli_file = NULL; } if (fli_filename) { _AL_FREE(fli_filename); fli_filename = NULL; } if (fli_bitmap) { destroy_bitmap(fli_bitmap); fli_bitmap = NULL; } fli_mem_data = NULL; fli_mem_pos = 0; reset_fli_variables(); fli_status = FLI_NOT_OPEN; } /* next_fli_frame: * Advances to the next frame of the FLI, leaving the changes in the * fli_bitmap and fli_palette. If loop is non-zero, it will cycle if * it reaches the end of the animation. Returns one of the FLI status * constants. */ int next_fli_frame(int loop) { /* looping is not supported if fli is read from custom packfile, * because it cannot be rewinded. */ if (fli_file && fli_filename == NULL) loop = 0; if (fli_status != FLI_OK) return fli_status; fli_timer--; /* end of file? should we loop? */ if (fli_frame >= fli_header.frame_count) { if (loop) { fli_rewind(sizeof_FLI_HEADER); fli_frame = 0; } else { fli_status = FLI_EOF; return fli_status; } } /* read the next frame */ read_frame(); return fli_status; } /* reset_fli_variables: * Clears the information about which parts of the FLI bitmap and palette * are dirty, after the screen hardware has been updated. */ void reset_fli_variables(void) { fli_bmp_dirty_from = INT_MAX; fli_bmp_dirty_to = INT_MIN; fli_pal_dirty_from = INT_MAX; fli_pal_dirty_to = INT_MIN; } allegro-4.4.3.1/src/inline.c0000664000175000017500000000164213437077643014514 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Copies of the inline functions in allegro.h, in case anyone needs * to take the address of them, or is compiling without optimisation. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #define AL_INLINE(type, name, args, code) type name args code #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_INTERNAL_HEADER #include ALLEGRO_INTERNAL_HEADER #endif allegro-4.4.3.1/src/beos/0000775000175000017500000000000013437077643014017 5ustar siegesiegeallegro-4.4.3.1/src/beos/bmousapi.cpp0000664000175000017500000001463513437077643016353 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * Windowed mode modifications by Peter Wang. * * Cursor show/hide in windowed mode added by Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define MOUSE_THREAD_NAME "mouse driver" #define MOUSE_THREAD_PRIORITY 60 #define MOUSE_THREAD_PERIOD 20000 // microseconds, 1/50th of a second #define PREFIX_I "al-bmouse INFO: " #define PREFIX_W "al-bmouse WARNING: " #define PREFIX_E "al-bmouse ERROR: " static thread_id mouse_thread_id = -1; static volatile bool mouse_thread_running = false; sem_id _be_mouse_view_attached = -1; BWindow *_be_mouse_window = NULL; BView *_be_mouse_view = NULL; bool _be_mouse_window_mode = false; static int be_mouse_x = 0; static int be_mouse_y = 0; static int be_mouse_b = 0; static int be_mickey_x = 0; static int be_mickey_y = 0; static int limit_up = 0; static int limit_down = 0; static int limit_left = 0; static int limit_right = 0; static bool be_mouse_warped = false; int32 mouse_thread(void *mouse_started) { BPoint cursor(0, 0); uint32 buttons; if (!_be_mouse_window_mode) { set_mouse_position(320, 240); } release_sem(*(sem_id *)mouse_started); for (;;) { acquire_sem(_be_mouse_view_attached); if (mouse_thread_running == false) { release_sem(_be_mouse_view_attached); /* XXX commented out due to conflicting TRACE in Haiku TRACE(PREFIX_I "mouse thread exited\n"); */ return 0; } if ((_be_focus_count > 0) && _be_mouse_window->Lock()) { _be_mouse_view->GetMouse(&cursor, &buttons); if (!_be_mouse_window_mode) { int dx = (int)cursor.x - 320; int dy = (int)cursor.y - 240; if (be_mouse_warped) { dx = 0; dy = 0; be_mouse_warped = false; } be_mickey_x = dx; be_mickey_y = dy; be_mouse_x += dx; be_mouse_y += dy; if (dx != 0 || dy != 0) { set_mouse_position(320, 240); } } else { BRect bounds = _be_mouse_window->Bounds(); if (bounds.Contains(cursor)) { int old_x = be_mouse_x; int old_y = be_mouse_y; _mouse_on = TRUE; if (!be_app->IsCursorHidden()) { be_app->HideCursor(); } be_mouse_x = (int)(cursor.x - bounds.left); be_mouse_y = (int)(cursor.y - bounds.top); if (!be_mouse_warped) { be_mickey_x += (be_mouse_x - old_x); be_mickey_y += (be_mouse_y - old_y); } else { be_mouse_warped = false; be_mickey_x = 0; be_mickey_y = 0; } } else { buttons = 0; _mouse_on = FALSE; if (be_app->IsCursorHidden()) { be_app->ShowCursor(); } } } _be_mouse_window->Unlock(); be_mouse_x = CLAMP(limit_left, be_mouse_x, limit_right); be_mouse_y = CLAMP(limit_up, be_mouse_y, limit_down); be_mouse_b = 0; be_mouse_b |= (buttons & B_PRIMARY_MOUSE_BUTTON) ? 1 : 0; be_mouse_b |= (buttons & B_SECONDARY_MOUSE_BUTTON) ? 2 : 0; be_mouse_b |= (buttons & B_TERTIARY_MOUSE_BUTTON) ? 4 : 0; _mouse_x = be_mouse_x; _mouse_y = be_mouse_y; _mouse_z = _be_mouse_z; _mouse_b = be_mouse_b; _handle_mouse_input(); } release_sem(_be_mouse_view_attached); snooze(MOUSE_THREAD_PERIOD); } } extern "C" int be_mouse_init(void) { sem_id mouse_started; int32 num_buttons; mouse_started = create_sem(0, "starting mouse driver..."); if (mouse_started < 0) { goto cleanup; } mouse_thread_id = spawn_thread(mouse_thread, MOUSE_THREAD_NAME, MOUSE_THREAD_PRIORITY, &mouse_started); if (mouse_thread_id < 0) { goto cleanup; } mouse_thread_running = true; resume_thread(mouse_thread_id); acquire_sem(mouse_started); delete_sem(mouse_started); be_mickey_x = 0; be_mickey_y = 0; be_mouse_x = 0; be_mouse_y = 0; be_mouse_b = 0; limit_up = 0; limit_down = 0; limit_left = 0; limit_right = 0; get_mouse_type(&num_buttons); return num_buttons; cleanup: { if (mouse_started > 0) { delete_sem(mouse_started); } be_mouse_exit(); return 0; } } extern "C" void be_mouse_exit(void) { be_mickey_x = 0; be_mickey_y = 0; be_mouse_x = 0; be_mouse_y = 0; be_mouse_b = 0; limit_up = 0; limit_down = 0; limit_left = 0; limit_right = 0; mouse_thread_running = false; if (mouse_thread_id > 0) { release_sem(_be_mouse_view_attached); wait_for_thread(mouse_thread_id, &ignore_result); acquire_sem(_be_mouse_view_attached); mouse_thread_id = -1; } } extern "C" void be_mouse_position(int x, int y) { acquire_sem(_be_mouse_view_attached); _mouse_x = be_mouse_x = CLAMP(limit_left, x, limit_right); _mouse_y = be_mouse_y = CLAMP(limit_up, y, limit_down); be_mouse_warped = true; if (!_be_mouse_window_mode) set_mouse_position(320, 240); release_sem(_be_mouse_view_attached); } extern "C" void be_mouse_set_range(int x1, int y1, int x2, int y2) { acquire_sem(_be_mouse_view_attached); limit_up = y1; limit_down = y2; limit_left = x1; limit_right = x2; release_sem(_be_mouse_view_attached); } extern "C" void be_mouse_set_speed(int xspeed, int yspeed) { } extern "C" void be_mouse_get_mickeys(int *mickeyx, int *mickeyy) { acquire_sem(_be_mouse_view_attached); if (mickeyx != NULL) { *mickeyx = be_mickey_x; } if (mickeyy != NULL) { *mickeyy = be_mickey_y; } be_mickey_x = 0; be_mickey_y = 0; release_sem(_be_mouse_view_attached); } allegro-4.4.3.1/src/beos/bmidi.c0000664000175000017500000000501213437077643015245 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MIDI driver for BeOS. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif MIDI_DRIVER midi_beos = { MIDI_BEOS, /* driver ID code */ empty_string, /* driver name */ empty_string, /* description string */ "BeOS MIDI", /* ASCII format name string */ 16, /* available voices */ 0, /* voice number offset */ 28, /* maximum voices we can support */ 0, /* default number of voices to use */ 10, 10, /* reserved voice range */ be_midi_detect, /* AL_METHOD(int, detect, (int input)); */ be_midi_init, /* AL_METHOD(int, init, (int input, int voices)); */ be_midi_exit, /* AL_METHOD(void, exit, (int input)); */ be_midi_set_mixer_volume,/* AL_METHOD(int, set_mixer_volume, (int volume)); */ be_midi_get_mixer_volume,/* AL_METHOD(int, get_mixer_volume, (void)); */ NULL, /* AL_METHOD(void, raw_midi, (int data)); */ _dummy_load_patches, /* AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ _dummy_adjust_patches, /* AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); */ be_midi_key_on, /* AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); */ be_midi_key_off, /* AL_METHOD(void, key_off, (int voice)); */ be_midi_set_volume, /* AL_METHOD(void, set_volume, (int voice, int vol)); */ be_midi_set_pitch, /* AL_METHOD(void, set_pitch, (int voice, int note, int bend)); */ be_midi_set_pan, /* AL_METHOD(void, set_pan, (int voice, int pan)); */ _dummy_noop2, /* AL_METHOD(void, set_vibrato, (int voice, int amount)); */ }; allegro-4.4.3.1/src/beos/bkeydrv.c0000664000175000017500000000156013437077643015633 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif _DRIVER_INFO _keyboard_driver_list[] = { {KEYBOARD_BEOS, &keyboard_beos, TRUE}, {0, NULL, 0} }; allegro-4.4.3.1/src/beos/bsysapi.cpp0000664000175000017500000002745713437077643016214 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS system driver routines. * * By Jason Wilkins. * * desktop_color_depth() and yield_timeslice() support added by * Angelo Mottola. * * Synchronization functions added by Eric Botcazou. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #ifndef SCAN_DEPEND #include #endif #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define SYS_THREAD_PRIORITY B_NORMAL_PRIORITY #define SYS_THREAD_NAME "system driver" #define EXE_NAME_UNKNOWN "./UNKNOWN" #define PREFIX_I "al-bsys INFO: " #define PREFIX_W "al-bsys WARNING: " #define PREFIX_E "al-bsys ERROR: " status_t ignore_result = 0; volatile int _be_focus_count = 0; BeAllegroApp *_be_allegro_app = NULL; static thread_id system_thread_id = -1; static thread_id main_thread_id = -1; static sem_id system_started = -1; static char app_path[MAXPATHLEN] = "."; char wnd_title[WND_TITLE_SIZE]; static bool using_custom_allegro_app; /* BeAllegroApp::BeAllegroApp: */ BeAllegroApp::BeAllegroApp(const char *signature) : BApplication(signature) { } /* BeAllegroApp::QuitRequested: */ bool BeAllegroApp::QuitRequested(void) { return false; } /* BeAllegroApp::ReadyToRun: */ void BeAllegroApp::ReadyToRun() { release_sem(system_started); } /* _be_sys_get_executable_name: */ extern "C" void _be_sys_get_executable_name(char *output, int size) { image_info info; int32 cookie; cookie = 0; if (get_next_image_info(0, &cookie, &info) == B_NO_ERROR) { _al_sane_strncpy(output, info.name, size); } else { _al_sane_strncpy(output, EXE_NAME_UNKNOWN, size); } output[size-1] = '\0'; } /* system_thread: */ static int32 system_thread(void *data) { (void)data; if (_be_allegro_app == NULL) { char sig[MAXPATHLEN] = "application/x-vnd.Allegro-"; char exe[MAXPATHLEN]; char *term, *p; _be_sys_get_executable_name(exe, sizeof(exe)); strncat(sig, get_filename(exe), sizeof(sig)-1); sig[sizeof(sig)-1] = '\0'; _be_allegro_app = new BeAllegroApp(sig); using_custom_allegro_app = false; term = getenv("TERM"); if (!strcmp(term, "dumb")) { /* The TERM environmental variable is set to "dumb" if the app was * not started from a terminal. */ p = &exe[strlen(exe) - 1]; while (*p != '/') p--; *(p + 1) = '\0'; _al_sane_strncpy(app_path, exe, MAXPATHLEN); } } else { using_custom_allegro_app = true; } _be_allegro_app->Run(); /* XXX commented out due to conflicting TRACE in Haiku TRACE(PREFIX_I "system thread exited\n"); */ return 0; } /* be_sys_init: */ extern "C" int be_sys_init(void) { int32 cookie; thread_info info; struct utsname os_name; char path[MAXPATHLEN]; cookie = 0; if (get_next_thread_info(0, &cookie, &info) == B_OK) { main_thread_id = info.thread; } else { goto cleanup; } _be_mouse_view_attached = create_sem(0, "waiting for mouse view attach..."); if (_be_mouse_view_attached < 0) { goto cleanup; } _be_sound_stream_lock = create_sem(1, "audiostream lock"); if (_be_sound_stream_lock < 0) { goto cleanup; } system_started = create_sem(0, "starting system driver..."); if(system_started < 0) { goto cleanup; } system_thread_id = spawn_thread(system_thread, SYS_THREAD_NAME, SYS_THREAD_PRIORITY, NULL); if (system_thread_id < 0) { goto cleanup; } resume_thread(system_thread_id); acquire_sem(system_started); delete_sem(system_started); uname(&os_name); os_type = OSTYPE_BEOS; os_multitasking = TRUE; chdir(app_path); _be_sys_get_executable_name(path, sizeof(path)); path[sizeof(path)-1] = '\0'; do_uconvert(get_filename(path), U_CURRENT, wnd_title, U_UTF8, WND_TITLE_SIZE); return 0; cleanup: { be_sys_exit(); return 1; } } /* be_sys_exit: */ extern "C" void be_sys_exit(void) { if (main_thread_id > 0) { main_thread_id = -1; } if (system_started > 0) { delete_sem(system_started); system_started = -1; } if (system_thread_id > 0) { ASSERT(_be_allegro_app != NULL); _be_allegro_app->Lock(); _be_allegro_app->Quit(); _be_allegro_app->Unlock(); wait_for_thread(system_thread_id, &ignore_result); system_thread_id = -1; } if (_be_mouse_view_attached > 0) { delete_sem(_be_mouse_view_attached); _be_mouse_view_attached = -1; } if (_be_sound_stream_lock > 0) { delete_sem(_be_sound_stream_lock); _be_sound_stream_lock = -1; } if (!using_custom_allegro_app) { delete _be_allegro_app; _be_allegro_app = NULL; } } /* be_sys_get_executable_name: */ extern "C" void be_sys_get_executable_name(char *output, int size) { char *buffer; buffer = (char *)malloc(size); if (buffer != NULL) { _be_sys_get_executable_name(buffer, size); do_uconvert(buffer, U_UTF8, output, U_CURRENT, size); free(buffer); } else { do_uconvert(EXE_NAME_UNKNOWN, U_ASCII, output, U_CURRENT, size); } } /* be_sys_find_resource: * This is the same of the unix resource finder; it looks into the * home directory and in /etc. */ int be_sys_find_resource(char *dest, AL_CONST char *resource, int size) { char buf[256], tmp[256], *last; char *home = getenv("HOME"); if (home) { /* look for ~/file */ append_filename(buf, uconvert_ascii(home, tmp), resource, sizeof(buf)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } /* if it is a .cfg, look for ~/.filerc */ if (ustricmp(get_extension(resource), uconvert_ascii("cfg", tmp)) == 0) { ustrzcpy(buf, sizeof(buf) - ucwidth(OTHER_PATH_SEPARATOR), uconvert_ascii(home, tmp)); put_backslash(buf); ustrzcat(buf, sizeof(buf), uconvert_ascii(".", tmp)); ustrzcpy(tmp, sizeof(tmp), resource); ustrzcat(buf, sizeof(buf), ustrtok_r(tmp, ".", &last)); ustrzcat(buf, sizeof(buf), uconvert_ascii("rc", tmp)); if (file_exists(buf, FA_ARCH | FA_RDONLY | FA_HIDDEN, NULL)) { ustrzcpy(dest, size, buf); return 0; } } } /* look for /etc/file */ append_filename(buf, uconvert_ascii("/etc/", tmp), resource, sizeof(buf)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } /* if it is a .cfg, look for /etc/filerc */ if (ustricmp(get_extension(resource), uconvert_ascii("cfg", tmp)) == 0) { ustrzcpy(buf, sizeof(buf), uconvert_ascii("/etc/", tmp)); ustrzcpy(tmp, sizeof(tmp), resource); ustrzcat(buf, sizeof(buf), ustrtok_r(tmp, ".", &last)); ustrzcat(buf, sizeof(buf), uconvert_ascii("rc", tmp)); if (exists(buf)) { ustrzcpy(dest, size, buf); return 0; } } return -1; } extern "C" void be_sys_set_window_title(AL_CONST char *name) { do_uconvert(name, U_CURRENT, wnd_title, U_UTF8, WND_TITLE_SIZE); if (_be_window) _be_window->SetTitle(wnd_title); } extern "C" int be_sys_set_close_button_callback(void (*proc)(void)) { if (!_be_window) return -1; _be_window_close_hook = proc; if (proc) _be_window->SetFlags(_be_window->Flags() & ~B_NOT_CLOSABLE); else _be_window->SetFlags(_be_window->Flags() | B_NOT_CLOSABLE); return 0; } extern "C" void be_sys_message(AL_CONST char *msg) { char filename[MAXPATHLEN]; char *title; char tmp[ALLEGRO_MESSAGE_SIZE]; char tmp2[ALLEGRO_MESSAGE_SIZE]; get_executable_name(filename, sizeof(filename)); title = get_filename(filename); BAlert *alert = new BAlert(title, uconvert(msg, U_CURRENT, tmp, U_UTF8, ALLEGRO_MESSAGE_SIZE), uconvert(get_config_text("Ok"), U_CURRENT, tmp2, U_UTF8, ALLEGRO_MESSAGE_SIZE)); alert->SetShortcut(0, B_ESCAPE); be_app->ShowCursor(); alert->Go(); be_app->HideCursor(); } extern "C" int be_sys_desktop_color_depth(void) { display_mode current_mode; BScreen().GetMode(¤t_mode); switch(current_mode.space) { case B_CMAP8: return 8; case B_RGB15: case B_RGBA15: return 15; case B_RGB16: return 16; case B_RGB32: case B_RGBA32: return 32; } return -1; } extern "C" int be_sys_get_desktop_resolution(int *width, int *height) { BScreen screen(B_MAIN_SCREEN_ID); *width = screen.Frame().IntegerWidth() + 1; *height = screen.Frame().IntegerHeight() + 1; return 0; } extern "C" void be_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_BWINDOW; mode->width = 320; mode->height = 200; mode->bpp = 8; } extern "C" void be_sys_yield_timeslice(void) { snooze(0); } /* custom mutex that supports nested locking */ struct my_mutex { int lock_count; /* level of nested locking */ thread_id owner; /* thread which owns the mutex */ sem_id actual_mutex; /* underlying mutex object */ }; /* be_sys_create_mutex: * Creates a mutex and returns a pointer to it. */ extern "C" void *be_sys_create_mutex(void) { struct my_mutex *mx; mx = (struct my_mutex *)malloc(sizeof(struct my_mutex)); if (!mx) { *allegro_errno = ENOMEM; return NULL; } mx->lock_count = 0; mx->owner = (thread_id) 0; mx->actual_mutex = create_sem(1, "internal mutex"); if (mx->actual_mutex < 0) { free(mx); return NULL; } return (void *)mx; } /* be_sys_destroy_mutex: * Destroys a mutex. */ extern "C" void be_sys_destroy_mutex(void *handle) { struct my_mutex *mx = (struct my_mutex *)handle; delete_sem(mx->actual_mutex); free(mx); } /* be_sys_lock_mutex: * Locks a mutex. */ extern "C" void be_sys_lock_mutex(void *handle) { struct my_mutex *mx = (struct my_mutex *)handle; if (mx->owner != find_thread(NULL)) { acquire_sem(mx->actual_mutex); mx->owner = find_thread(NULL); } mx->lock_count++; } /* be_sys_unlock_mutex: * Unlocks a mutex. */ extern "C" void be_sys_unlock_mutex(void *handle) { struct my_mutex *mx = (struct my_mutex *)handle; mx->lock_count--; if (mx->lock_count == 0) { mx->owner = (thread_id) 0; release_sem(mx->actual_mutex); } } extern "C" void be_sys_suspend(void) { if (system_thread_id > 0) { suspend_thread(system_thread_id); } } extern "C" void be_sys_resume(void) { if (system_thread_id > 0) { resume_thread(system_thread_id); } } extern "C" void be_main_suspend(void) { if (main_thread_id > 0) { suspend_thread(main_thread_id); } } extern "C" void be_main_resume(void) { if (main_thread_id > 0) { resume_thread(main_thread_id); } } int32 killer_thread(void *data) { int32 cookie; team_info info; kill_thread(main_thread_id); allegro_exit(); cookie = 0; get_next_team_info(&cookie, &info); kill_team(info.team); return 1; } void _be_terminate(thread_id caller, bool exit_caller) { thread_id killer; killer = spawn_thread(killer_thread, "son of sam", 120, NULL); resume_thread(killer); if (exit_caller) exit_thread(1); } allegro-4.4.3.1/src/beos/btimeapi.cpp0000664000175000017500000000572513437077643016326 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define TIMER_THREAD_PRIORITY 120 thread_id timer_thread_id = -1; volatile bool timer_thread_running = false; /* timer_thread: */ static int32 timer_thread(void *timer_started) { unsigned long delay; delay = 0x8000; release_sem(*(sem_id *)timer_started); while(timer_thread_running) { snooze((bigtime_t)(delay / 1.193181)); acquire_sem(_be_sound_stream_lock); delay = _handle_timer_tick(delay); release_sem(_be_sound_stream_lock); } return 0; } /* be_time_init: */ extern "C" int be_time_init(void) { sem_id timer_started; timer_started = create_sem(0, "starting timer driver..."); if(timer_started < 0) { goto cleanup; } timer_thread_id = spawn_thread(timer_thread, "timer driver", TIMER_THREAD_PRIORITY, &timer_started); if(timer_thread_id < 0) { goto cleanup; } timer_thread_running = true; resume_thread(timer_thread_id); return 0; cleanup: { if (timer_started > 0) { delete_sem(timer_started); } be_time_exit(); return 1; } } /* be_time_exit: */ extern "C" void be_time_exit(void) { if (timer_thread_id > 0) { timer_thread_running = false; wait_for_thread(timer_thread_id, &ignore_result); timer_thread_id = -1; } } /* be_time_can_simulate_retrace: */ //extern "C" int be_time_can_simulate_retrace(void) //{ // return FALSE; //} /* be_time_simulate_retrace: */ // TODO: See if it will be possible to implement this. //extern "C" void be_time_simulate_retrace(int enable) //{ //} /* be_time_rest: */ extern "C" void be_time_rest(unsigned int time, AL_METHOD(void, callback, (void))) { time *= 1000; if(callback != NULL) { bigtime_t start; bigtime_t end; start = system_time(); end = start + time; while(system_time() < end) { callback(); } } else { snooze(time); } } /* be_time_suspend: */ extern "C" void be_time_suspend(void) { if (timer_thread_id > 0) { suspend_thread(timer_thread_id); } } extern "C" void be_time_resume(void) { if (timer_thread_id > 0) { resume_thread(timer_thread_id); } } allegro-4.4.3.1/src/beos/bmousdrv.c0000664000175000017500000000163713437077643016033 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif _DRIVER_INFO _mouse_driver_list[] = { {MOUSE_BEOS, &mouse_beos, TRUE}, // {MOUSEDRV_NONE, &mousedrv_none, TRUE}, {0, NULL, 0} }; allegro-4.4.3.1/src/beos/bjoydrv.c0000664000175000017500000000152513437077643015645 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif BEGIN_JOYSTICK_DRIVER_LIST JOYSTICK_DRIVER_BEOS END_JOYSTICK_DRIVER_LIST allegro-4.4.3.1/src/beos/bgfxapi.cpp0000664000175000017500000001461713437077643016154 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Common gfx subsystem routines. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define SUSPEND_ALL_THREADS() \ { \ be_key_suspend(); \ be_sound_suspend(); \ be_time_suspend(); \ be_sys_suspend(); \ be_main_suspend(); \ } #define RESUME_ALL_THREADS() \ { \ be_key_resume(); \ be_sound_resume(); \ be_time_resume(); \ be_sys_resume(); \ be_main_resume(); \ } AL_CONST BE_MODE_TABLE _be_mode_table[] = { { 8, 640, 400, B_8_BIT_640x400, B_CMAP8 }, { 8, 640, 480, B_8_BIT_640x480, B_CMAP8 }, { 8, 800, 600, B_8_BIT_800x600, B_CMAP8 }, { 8, 1024, 768, B_8_BIT_1024x768, B_CMAP8 }, { 8, 1152, 900, B_8_BIT_1152x900, B_CMAP8 }, { 8, 1280, 1024, B_8_BIT_1280x1024, B_CMAP8 }, { 8, 1600, 1200, B_8_BIT_1600x1200, B_CMAP8 }, { 15, 640, 480, B_15_BIT_640x480, B_RGB15 }, { 15, 800, 600, B_15_BIT_800x600, B_RGB15 }, { 15, 1024, 768, B_15_BIT_1024x768, B_RGB15 }, { 15, 1152, 900, B_15_BIT_1152x900, B_RGB15 }, { 15, 1280, 1024, B_15_BIT_1280x1024, B_RGB15 }, { 15, 1600, 1200, B_15_BIT_1600x1200, B_RGB15 }, { 16, 640, 480, B_16_BIT_640x480, B_RGB16 }, { 16, 800, 600, B_16_BIT_800x600, B_RGB16 }, { 16, 1024, 768, B_16_BIT_1024x768, B_RGB16 }, { 16, 1152, 900, B_16_BIT_1152x900, B_RGB16 }, { 16, 1280, 1024, B_16_BIT_1280x1024, B_RGB16 }, { 16, 1600, 1200, B_16_BIT_1600x1200, B_RGB16 }, { 32, 640, 480, B_32_BIT_640x480, B_RGB32 }, { 32, 800, 600, B_32_BIT_800x600, B_RGB32 }, { 32, 1024, 768, B_32_BIT_1024x768, B_RGB32 }, { 32, 1152, 900, B_32_BIT_1152x900, B_RGB32 }, { 32, 1280, 1024, B_32_BIT_1280x1024, B_RGB32 }, { 32, 1600, 1200, B_32_BIT_1600x1200, B_RGB32 }, { -1, 0, 0, 0, 0 } }; sem_id _be_fullscreen_lock = -1; sem_id _be_window_lock = -1; volatile int _be_lock_count = 0; int *_be_dirty_lines = NULL; int _be_mouse_z = 0; void (*_be_window_close_hook)() = NULL; volatile bool _be_gfx_initialized = false; BeAllegroView *_be_allegro_view = NULL; BeAllegroScreen *_be_allegro_screen = NULL; BeAllegroWindow *_be_allegro_window = NULL; BeAllegroDirectWindow *_be_allegro_direct_window = NULL; BeAllegroOverlay *_be_allegro_overlay = NULL; BWindow *_be_window = NULL; static int refresh_rate = 60; /* BeAllegroView::BeAllegroView: */ BeAllegroView::BeAllegroView(BRect frame, const char *name, uint32 resizingMode, uint32 flags, int f) : BView(frame, name, resizingMode, flags) { this->flags = f; } /* BeAllegroView::MessageReceived: */ void BeAllegroView::MessageReceived(BMessage *message) { switch (message->what) { case B_SIMPLE_DATA: break; default: BView::MessageReceived(message); break; } } void BeAllegroView::Draw(BRect update_rect) { if (flags & BE_ALLEGRO_VIEW_OVERLAY) { SetHighColor(_be_allegro_overlay->color_key); FillRect(update_rect); return; } if ((flags & BE_ALLEGRO_VIEW_DIRECT) || (!_be_allegro_window)) return; if ((!_be_focus_count) && ((_be_switch_mode == SWITCH_AMNESIA) || (_be_switch_mode == SWITCH_BACKAMNESIA))) return; if (_be_allegro_window->screen_depth == 8) DrawBitmap(_be_allegro_window->aux_buffer, update_rect, update_rect); else DrawBitmap(_be_allegro_window->buffer, update_rect, update_rect); } void _be_gfx_set_truecolor_shifts() { _rgb_r_shift_15 = 10; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 0; _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; _rgb_a_shift_32 = 24; _rgb_r_shift_32 = 16; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 0; } void _be_change_focus(bool active) { int i; if (_be_focus_count < 0) _be_focus_count = 0; if (active) { _be_focus_count++; if (_be_gfx_initialized) { switch (_be_switch_mode) { case SWITCH_AMNESIA: case SWITCH_BACKAMNESIA: if ((_be_allegro_direct_window) && (_be_allegro_direct_window->drawing_thread_id > 0)) { resume_thread(_be_allegro_direct_window->drawing_thread_id); } if (_be_switch_mode == SWITCH_BACKAMNESIA) break; case SWITCH_PAUSE: RESUME_ALL_THREADS(); break; } _switch_in(); } } else { _be_focus_count--; if (_be_gfx_initialized) { _switch_out(); switch (_be_switch_mode) { case SWITCH_AMNESIA: case SWITCH_BACKAMNESIA: if ((_be_allegro_direct_window) && (_be_allegro_direct_window->drawing_thread_id > 0)) { suspend_thread(_be_allegro_direct_window->drawing_thread_id); } if (_be_switch_mode == SWITCH_BACKAMNESIA) break; case SWITCH_PAUSE: if (_be_midisynth) _be_midisynth->AllNotesOff(false); SUSPEND_ALL_THREADS(); break; } } } } bool _be_handle_window_close(const char *title) { if (_be_window_close_hook) _be_window_close_hook(); return false; } extern "C" void be_gfx_vsync(void) { if(BScreen(_be_window).WaitForRetrace() != B_OK) { if (_timer_installed) { int start_count; start_count = retrace_count; while (start_count == retrace_count) { } } else { snooze (500000 / refresh_rate); } } } allegro-4.4.3.1/src/beos/bwscreen.cpp0000664000175000017500000003621713437077643016344 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Fullscreen BeOS gfx driver based on BScreen. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif static char driver_desc[256] = EMPTY_STRING; static thread_id palette_thread_id = -1; static sem_id palette_sem = -1; static rgb_color palette_colors[256]; /* BeAllegroScreen::BeAllegroScreen: * Constructor, switches gfx mode and initializes the screen. */ BeAllegroScreen::BeAllegroScreen(const char *title, uint32 space, status_t *error, bool debugging) : BWindowScreen(title, space, error, debugging) { } /* BeAllegroScreen::ScreenConnected: * Callback for when the user switches in or out of the workspace. */ void BeAllegroScreen::ScreenConnected(bool connected) { if(connected) { _be_change_focus(connected); release_sem(_be_fullscreen_lock); } else { acquire_sem(_be_fullscreen_lock); _be_change_focus(connected); } } /* BeAllegroScreen::QuitRequested: * User requested to close the program window. */ bool BeAllegroScreen::QuitRequested(void) { return _be_handle_window_close(Title()); } /* BeAllegroScreen::MessageReceived: * System messages handler. */ void BeAllegroScreen::MessageReceived(BMessage *message) { switch (message->what) { case B_SIMPLE_DATA: break; case B_MOUSE_WHEEL_CHANGED: float dy; message->FindFloat("be:wheel_delta_y", &dy); _be_mouse_z += ((int)dy > 0 ? -1 : 1); break; default: BWindowScreen::MessageReceived(message); break; } } /* find_gfx_mode: * Searches given mode and returns the corresponding entry in the modes * table. Returns -1 if mode is unavailable. */ static inline uint32 find_gfx_mode(int w, int h, int d) { int index = 0; while (_be_mode_table[index].d > 0) { if ((_be_mode_table[index].w == w) && (_be_mode_table[index].h == h) && (_be_mode_table[index].d == d)) return _be_mode_table[index].mode; index++; } return (uint32)-1; } /* be_sort_out_virtual_resolution: * Computes and initializes framebuffer layout for given virtual * resolution. */ static inline bool be_sort_out_virtual_resolution(int w, int h, int *v_w, int *v_h, int color_depth) { int32 try_v_w; int32 try_v_h; // Possible VRAM amounts. Are these always powers of 2? int ram_count[] = { 256, 128, 64, 32, 16, 8, 4, 2, 1, 0 }; int i; if (*v_w == 0) try_v_w = MIN(w, 32767); else try_v_w = MIN(*v_w, 32767); try_v_h = *v_h; if (*v_h == 0) { for (i = 0; ram_count[i]; i++) { try_v_h = (1024 * 1024 * ram_count[i]) / (try_v_w * BYTES_PER_PIXEL(color_depth)); /* Evil hack: under BeOS R5 SetFrameBuffer() should work with any * int32 width and height parameters, but actually it crashes if * one of them exceeds the boundaries of a signed short variable. */ try_v_h = MIN(try_v_h, 32767); if (_be_allegro_screen->SetFrameBuffer(try_v_w, try_v_h) == B_OK) { *v_w = try_v_w; *v_h = try_v_h; return true; } } try_v_h = h; } if (_be_allegro_screen->SetFrameBuffer(try_v_w, try_v_h) == B_OK) { *v_w = try_v_w; *v_h = try_v_h; return true; } else { return false; } } /* palette_updater_thread: * This small thread is used to update the palette in fullscreen mode. It may seem * unnecessary as a direct call to SetColorList would do it, but calling directly * this function from the main thread has proven to be a major bottleneck, so * calling it from a separated thread is a good thing. */ static int32 palette_updater_thread(void *data) { BeAllegroScreen *s = (BeAllegroScreen *)data; while (_be_gfx_initialized) { acquire_sem(palette_sem); s->SetColorList(palette_colors, 0, 255); } return B_OK; } /* be_gfx_bwindowscreen_fetch_mode_list: * Builds the list of available video modes. */ extern "C" struct GFX_MODE_LIST *be_gfx_bwindowscreen_fetch_mode_list(void) { int j, be_mode, num_modes = 0; uint32 i, count; display_mode *mode; GFX_MODE_LIST *mode_list; bool already_there; if (BScreen().GetModeList(&mode, &count) != B_OK) return NULL; mode_list = (GFX_MODE_LIST *)malloc(sizeof(GFX_MODE_LIST)); if (!mode_list) { free(mode); return NULL; } mode_list->mode = NULL; for (i=0; i 0) { if ((mode[i].virtual_width == _be_mode_table[be_mode].w) && (mode[i].virtual_height == _be_mode_table[be_mode].h) && (mode[i].space == _be_mode_table[be_mode].space)) break; be_mode++; } if (_be_mode_table[be_mode].d == -1) continue; already_there = false; for (j=0; jmode[j].width == _be_mode_table[be_mode].w) && (mode_list->mode[j].height == _be_mode_table[be_mode].h) && (mode_list->mode[j].bpp == _be_mode_table[be_mode].d)) { already_there = true; break; } } if (!already_there) { mode_list->mode = (GFX_MODE *)realloc(mode_list->mode, sizeof(GFX_MODE) * (num_modes + 1)); if (!mode_list->mode) { free(mode); return NULL; } mode_list->mode[num_modes].width = _be_mode_table[be_mode].w; mode_list->mode[num_modes].height = _be_mode_table[be_mode].h; mode_list->mode[num_modes].bpp = _be_mode_table[be_mode].d; num_modes++; } } mode_list->mode = (GFX_MODE *)realloc(mode_list->mode, sizeof(GFX_MODE) * (num_modes + 1)); if (!mode_list->mode) { free(mode); return NULL; } mode_list->mode[num_modes].width = 0; mode_list->mode[num_modes].height = 0; mode_list->mode[num_modes].bpp = 0; mode_list->num_modes = num_modes; free(mode); return mode_list; } /* _be_gfx_bwindowscreen_init: * Initializes the driver for given gfx mode. */ static struct BITMAP *_be_gfx_bwindowscreen_init(GFX_DRIVER *drv, int w, int h, int v_w, int v_h, int color_depth, bool accel) { BITMAP *bmp; status_t error; uint32 mode; graphics_card_info *gfx_card; frame_buffer_info *fbuffer; accelerant_device_info info; char tmp1[128], tmp2[128]; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (color_depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((w == 0) && (h == 0)) { w = 640; h = 480; } mode = find_gfx_mode(w, h, color_depth); if (mode == (uint32)-1) { goto cleanup; } _be_fullscreen_lock = create_sem(0, "screen lock"); if (_be_fullscreen_lock < 0) { goto cleanup; } _be_lock_count = 0; set_display_switch_mode(SWITCH_AMNESIA); _be_allegro_screen = new BeAllegroScreen(wnd_title, mode, &error, false); _be_window = _be_allegro_screen; if(error != B_OK) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto cleanup; } _be_mouse_view = new BView(_be_allegro_screen->Bounds(), "allegro mouse view", B_FOLLOW_ALL_SIDES, 0); _be_allegro_screen->Lock(); _be_allegro_screen->AddChild(_be_mouse_view); _be_allegro_screen->Unlock(); _be_mouse_window = _be_allegro_screen; _be_mouse_window_mode = false; _mouse_on = TRUE; release_sem(_be_mouse_view_attached); palette_sem = create_sem(0, "palette sem"); if (palette_sem < 0) { goto cleanup; } _be_gfx_initialized = false; _be_allegro_screen->Show(); acquire_sem(_be_fullscreen_lock); gfx_card = _be_allegro_screen->CardInfo(); if (!be_sort_out_virtual_resolution(w, h, &v_w, &v_h, color_depth)) { v_w = w; v_h = h; } /* BWindowScreen sets refresh rate at 60 Hz by default */ _set_current_refresh_rate(60); fbuffer = _be_allegro_screen->FrameBufferInfo(); drv->w = w; drv->h = h; drv->linear = TRUE; drv->vid_mem = v_w * v_h * BYTES_PER_PIXEL(color_depth); bmp = _make_bitmap(fbuffer->width, fbuffer->height, (unsigned long)gfx_card->frame_buffer, drv, color_depth, fbuffer->bytes_per_row); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } _be_sync_func = NULL; if (accel) { be_gfx_bwindowscreen_accelerate(color_depth); } #ifdef ALLEGRO_NO_ASM if (gfx_capabilities) { bmp->write_bank = (void *)be_gfx_bwindowscreen_read_write_bank; bmp->read_bank = (void *)be_gfx_bwindowscreen_read_write_bank; _screen_vtable.unwrite_bank = (void *)be_gfx_bwindowscreen_unwrite_bank; } #else if (gfx_capabilities) { bmp->write_bank = _be_gfx_bwindowscreen_read_write_bank_asm; bmp->read_bank = _be_gfx_bwindowscreen_read_write_bank_asm; _screen_vtable.unwrite_bank = _be_gfx_bwindowscreen_unwrite_bank_asm; } #endif gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; _screen_vtable.acquire = be_gfx_bwindowscreen_acquire; _screen_vtable.release = be_gfx_bwindowscreen_release; _be_gfx_set_truecolor_shifts(); if (BScreen().GetDeviceInfo(&info) == B_OK) uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("BWindowScreen object (%s)", tmp1), uconvert_ascii(info.name, tmp2)); else ustrzcpy(driver_desc, sizeof(driver_desc), uconvert_ascii("BWindowScreen object", tmp1)); drv->desc = driver_desc; _be_gfx_initialized = true; palette_thread_id = spawn_thread(palette_updater_thread, "palette updater", B_DISPLAY_PRIORITY, (void *)_be_allegro_screen); resume_thread(palette_thread_id); be_app->HideCursor(); release_sem(_be_fullscreen_lock); while (!_be_focus_count); return bmp; cleanup: { be_gfx_bwindowscreen_exit(NULL); return NULL; } } extern "C" struct BITMAP *be_gfx_bwindowscreen_accel_init(int w, int h, int v_w, int v_h, int color_depth) { return _be_gfx_bwindowscreen_init(&gfx_beos_bwindowscreen_accel, w, h, v_w, v_h, color_depth, true); } extern "C" struct BITMAP *be_gfx_bwindowscreen_init(int w, int h, int v_w, int v_h, int color_depth) { return _be_gfx_bwindowscreen_init(&gfx_beos_bwindowscreen, w, h, v_w, v_h, color_depth, false); } /* be_gfx_bwindowscreen_exit: * Shuts down the driver. */ extern "C" void be_gfx_bwindowscreen_exit(struct BITMAP *bmp) { status_t ret_value; (void)bmp; if (_be_fullscreen_lock > 0) { delete_sem(_be_fullscreen_lock); _be_fullscreen_lock = -1; } _be_gfx_initialized = false; if (palette_thread_id >= 0) { release_sem(palette_sem); wait_for_thread(palette_thread_id, &ret_value); palette_thread_id = -1; } if (palette_sem >= 0) { delete_sem(palette_sem); palette_sem = -1; } if (_be_allegro_screen != NULL) { if (_be_mouse_view_attached < 1) { acquire_sem(_be_mouse_view_attached); } _be_allegro_screen->Lock(); _be_allegro_screen->Quit(); _be_allegro_screen = NULL; _be_window = NULL; } be_app->ShowCursor(); _be_mouse_window = NULL; _be_mouse_view = NULL; _be_focus_count = 0; _be_lock_count = 0; } #ifdef ALLEGRO_NO_ASM /* be_gfx_bwindowscreen_read_write_bank: * Returns new line and synchronizes framebuffer if needed. */ extern "C" uintptr_t be_gfx_bwindowscreen_read_write_bank(BITMAP *bmp, int line) { if (!(bmp->id & BMP_ID_LOCKED)) { _be_sync_func(); bmp->id |= (BMP_ID_LOCKED | BMP_ID_AUTOLOCK); } return (unsigned long)(bmp->line[line]); } /* be_gfx_bwindowscreen_unwrite_bank: * Unlocks bitmap if necessary. */ extern "C" void be_gfx_bwindowscreen_unwrite_bank(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); } } #endif /* be_gfx_bwindowscreen_acquire: * Locks specified video bitmap. */ extern "C" void be_gfx_bwindowscreen_acquire(struct BITMAP *bmp) { if (_be_lock_count == 0) { acquire_sem(_be_fullscreen_lock); bmp->id |= BMP_ID_LOCKED; } if (_be_sync_func) _be_sync_func(); _be_lock_count++; } /* be_gfx_bwindowscreen_release: * Unlocks specified video bitmap. */ extern "C" void be_gfx_bwindowscreen_release(struct BITMAP *bmp) { _be_lock_count--; if (_be_lock_count == 0) { bmp->id &= ~BMP_ID_LOCKED; release_sem(_be_fullscreen_lock); } } /* be_gfx_bwindowscreen_set_palette: * Sets the palette colors and notices the palette updater thread * about the change. */ extern "C" void be_gfx_bwindowscreen_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { if (vsync) be_gfx_vsync(); for(int index = from; index <= to; index++) { palette_colors[index].red = _rgb_scale_6[p[index].r]; palette_colors[index].green = _rgb_scale_6[p[index].g]; palette_colors[index].blue = _rgb_scale_6[p[index].b]; palette_colors[index].alpha = 255; } /* Update palette! */ release_sem(palette_sem); } /* be_gfx_bwindowscreen_scroll: * Scrolls the visible viewport. */ extern "C" int be_gfx_bwindowscreen_scroll(int x, int y) { int rv; acquire_screen(); if (_be_allegro_screen->MoveDisplayArea(x, y) != B_ERROR) { rv = 0; } else { rv = 1; } release_screen(); if (_wait_for_vsync) be_gfx_vsync(); return rv; } /* be_gfx_bwindowscreen_poll_scroll: * Returns true if there are pending scrolling requests left. */ extern "C" int be_gfx_bwindowscreen_poll_scroll(void) { return (BScreen(_be_allegro_screen).WaitForRetrace(0) == B_ERROR ? TRUE : FALSE); } /* be_gfx_bwindowscreen_request_scroll: * Starts a screen scroll but doesn't wait for the retrace. */ extern "C" int be_gfx_bwindowscreen_request_scroll(int x, int y) { acquire_screen(); _be_allegro_screen->MoveDisplayArea(x, y); release_screen(); return 0; } /* be_gfx_bwindowscreen_request_video_bitmap: * Page flips to display specified bitmap, but doesn't wait for retrace. */ extern "C" int be_gfx_bwindowscreen_request_video_bitmap(struct BITMAP *bmp) { int rv; acquire_screen(); rv = _be_allegro_screen->MoveDisplayArea(bmp->x_ofs, bmp->y_ofs) == B_ERROR ? 1 : 0; release_screen(); return rv; } allegro-4.4.3.1/src/beos/bjoyapi.cpp0000664000175000017500000002165013437077643016164 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver routines for BeOS. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif static BJoystick *be_joy = NULL; static int32 num_devices, num_axes, num_hats, num_buttons; static int16 *axis_value = NULL; static int8 *hat_value = NULL; /* be_joy_init: * Initializes BeOS joystick driver. */ extern "C" int be_joy_init(void) { const char *device_config; char device_name[B_OS_NAME_LENGTH + 1]; static char desc[30]; static char name_x[10]; static char name_y[10]; static char name_stick[] = "stick"; static char name_hat[] = "hat"; static char name_throttle[] = "throttle"; static char name_hat_lr[] = "left/right"; static char name_hat_ud[] = "up/down"; static char *name_b[] = {"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"}; int32 i, j, stick; BString *temp; char *name; temp = new BString; be_joy = new BJoystick; num_devices = be_joy->CountDevices(); /* no joysticks available */ if (num_devices == 0) { goto cleanup; } /* Scans if the joystick_device config variable is set */ device_config = get_config_string("joystick", "joystick_device", ""); /* Let's try to open selected device */ if ((device_config[0] == '\0') || (be_joy->Open(device_config) < 0)) { /* ok, let's try to open first available device */ if (be_joy->GetDeviceName(0, device_name) != B_OK) { goto cleanup; } if (be_joy->Open(device_name) == B_ERROR) { goto cleanup; } } be_joy->GetControllerName(temp); name = temp->LockBuffer(0); _al_sane_strncpy(desc, name, sizeof(desc)); temp->UnlockBuffer(); joystick_beos.desc = desc; num_axes = be_joy->CountAxes(); num_hats = be_joy->CountHats(); num_buttons = be_joy->CountButtons(); if (num_axes) { axis_value = (int16 *)malloc(sizeof(int16) * num_axes); hat_value = (int8 *)malloc(sizeof(int8) * num_axes); } num_joysticks = be_joy->CountSticks(); for (i = 0; i < num_joysticks; i++) { joy[i].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE; stick = 0; if (num_axes >= 2) { joy[i].stick[0].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_SIGNED; joy[i].stick[0].num_axis = 2; joy[i].stick[0].name = name_stick; be_joy->GetAxisNameAt(0, temp); name = temp->LockBuffer(0); _al_sane_strncpy(name_x, name, sizeof(name_x)); temp->UnlockBuffer(); joy[i].stick[0].axis[0].name = name_x; be_joy->GetAxisNameAt(1, temp); name = temp->LockBuffer(0); _al_sane_strncpy(name_y, name, sizeof(name_y)); temp->UnlockBuffer(); joy[i].stick[0].axis[1].name = name_y; stick++; for (j = 2; j < num_axes; j++) { joy[i].stick[stick].flags = JOYFLAG_DIGITAL | JOYFLAG_ANALOGUE | JOYFLAG_UNSIGNED; joy[i].stick[stick].num_axis = 1; joy[i].stick[stick].axis[0].name = ""; joy[i].stick[stick].name = name_throttle; stick++; } for (j = 0; j < num_hats; j++) { joy[i].stick[stick].flags = JOYFLAG_DIGITAL | JOYFLAG_SIGNED; joy[i].stick[stick].num_axis = 2; joy[i].stick[stick].axis[0].name = name_hat_lr; joy[i].stick[stick].axis[1].name = name_hat_ud; joy[i].stick[stick].name = name_hat; stick++; } } joy[i].num_sticks = stick; joy[i].num_buttons = num_buttons; for (j = 0; j < num_buttons; j++) joy[i].button[j].name = name_b[j]; } delete temp; be_joy_poll(); return 0; cleanup: { delete temp; delete be_joy; return -1; } } /* be_joy_exit: * Closes joystick driver. */ extern "C" void be_joy_exit(void) { if (be_joy) { delete be_joy; be_joy = NULL; } if (axis_value) { free(axis_value); axis_value = NULL; } if (hat_value) { free(hat_value); hat_value = NULL; } } /* be_joy_poll: * Polls joysticks status. */ extern "C" int be_joy_poll(void) { int32 i, j, k; int32 axis, hat, stick, buttons; be_joy->Update(); for (i = 0; i < num_joysticks; i++) { axis = hat = stick = 0; be_joy->GetAxisValues(axis_value, i); for (j = 0; j < joy[i].num_sticks; j++) { for (k = 0; k < joy[i].stick[j].num_axis; k++) { axis_value[axis] /= 256; if (joy[i].stick[j].flags & JOYFLAG_SIGNED) joy[i].stick[j].axis[k].pos = axis_value[axis]; else joy[i].stick[j].axis[k].pos = axis_value[axis] + 128; joy[i].stick[j].axis[k].d1 = (axis_value[axis] < -64 ? 1 : 0); joy[i].stick[j].axis[k].d2 = (axis_value[axis] > 64 ? 1 : 0); axis++; } stick++; if (axis >= num_axes) break; } for (j = 0; j < num_hats; j++) { switch (hat_value[hat]) { case 0: /* centered */ joy[i].stick[stick].axis[0].pos = 0; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 0; joy[i].stick[stick].axis[1].pos = 0; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 0; break; case 1: /* up */ joy[i].stick[stick].axis[0].pos = 0; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 0; joy[i].stick[stick].axis[1].pos = 128; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 1; case 2: /* up and right */ joy[i].stick[stick].axis[0].pos = 128; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 1; joy[i].stick[stick].axis[1].pos = 128; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 1; case 3: /* right */ joy[i].stick[stick].axis[0].pos = 128; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 1; joy[i].stick[stick].axis[1].pos = 0; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 0; case 4: /* down and right */ joy[i].stick[stick].axis[0].pos = 128; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 1; joy[i].stick[stick].axis[1].pos = -128; joy[i].stick[stick].axis[1].d1 = 1; joy[i].stick[stick].axis[1].d2 = 0; case 5: /* down */ joy[i].stick[stick].axis[0].pos = 0; joy[i].stick[stick].axis[0].d1 = 0; joy[i].stick[stick].axis[0].d2 = 0; joy[i].stick[stick].axis[1].pos = -128; joy[i].stick[stick].axis[1].d1 = 1; joy[i].stick[stick].axis[1].d2 = 0; case 6: /* down and left */ joy[i].stick[stick].axis[0].pos = -128; joy[i].stick[stick].axis[0].d1 = 1; joy[i].stick[stick].axis[0].d2 = 0; joy[i].stick[stick].axis[1].pos = -128; joy[i].stick[stick].axis[1].d1 = 1; joy[i].stick[stick].axis[1].d2 = 0; case 7: /* left */ joy[i].stick[stick].axis[0].pos = -128; joy[i].stick[stick].axis[0].d1 = 1; joy[i].stick[stick].axis[0].d2 = 0; joy[i].stick[stick].axis[1].pos = 0; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 0; case 8: /* up and left */ joy[i].stick[stick].axis[0].pos = -128; joy[i].stick[stick].axis[0].d1 = 1; joy[i].stick[stick].axis[0].d2 = 0; joy[i].stick[stick].axis[1].pos = 128; joy[i].stick[stick].axis[1].d1 = 0; joy[i].stick[stick].axis[1].d2 = 1; } hat++; stick++; } buttons = be_joy->ButtonValues(i); for (j = 0; j < num_buttons; j++) { joy[i].button[j].b = buttons & 1; buttons >>= 1; } } return 0; } allegro-4.4.3.1/src/beos/bkey.c0000664000175000017500000000207113437077643015115 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif KEYBOARD_DRIVER keyboard_beos = { KEYBOARD_BEOS, empty_string, empty_string, "BeOS Keyboard", TRUE, be_key_init, be_key_exit, NULL, be_key_set_leds, be_key_set_rate, be_key_wait_for_input, be_key_stop_waiting_for_input, NULL, NULL }; allegro-4.4.3.1/src/beos/bmidiapi.cpp0000664000175000017500000001446013437077643016306 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MIDI driver routines for BeOS. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif BMidiSynth *_be_midisynth = NULL; static char be_midi_driver_desc[256] = EMPTY_STRING; static int cur_patch[17]; static int cur_note[17]; static int cur_vol[17]; /* be_midi_detect: * BeOS MIDI detection. */ extern "C" int be_midi_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } return TRUE; } /* be_midi_init: * Initializes the BeOS MIDI driver. */ extern "C" int be_midi_init(int input, int voices) { char tmp[256], tmp2[128], tmp3[128] = EMPTY_STRING; char *sound = uconvert_ascii("sound", tmp); int mode, freq, quality, reverb; synth_mode sm = B_BIG_SYNTH; interpolation_mode im = B_2_POINT_INTERPOLATION; char *reverb_name[] = { "no", "closet", "garage", "ballroom", "cavern", "dungeon" }; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } _be_midisynth = new BMidiSynth(); if (!_be_midisynth) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return -1; } /* Checks if instruments are available */ mode = CLAMP(0, get_config_int(sound, uconvert_ascii("be_midi_quality", tmp), 1), 1); if (mode) sm = B_BIG_SYNTH; else sm = B_LITTLE_SYNTH; if ((be_synth->LoadSynthData(sm) != B_OK) || (!be_synth->IsLoaded())) { delete _be_midisynth; _be_midisynth = NULL; ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not load MIDI instruments data file")); return -1; } /* Sets up synthetizer and loads instruments */ _be_midisynth->EnableInput(true, true); /* Prevents other apps from changing instruments on the fly */ _be_midisynth->FlushInstrumentCache(true); /* Reverberation is cool */ reverb = CLAMP(0, get_config_int(sound, uconvert_ascii("be_midi_reverb", tmp), 0), 5); if (reverb) { be_synth->SetReverb((reverb_mode)reverb); be_synth->EnableReverb(true); } else be_synth->EnableReverb(false); /* Sets sampling rate and sample interpolation method */ freq = get_config_int(sound, uconvert_ascii("be_midi_freq", tmp), 22050); quality = CLAMP(0, get_config_int(sound, uconvert_ascii("be_midi_interpolation", tmp), 1), 2); be_synth->SetSamplingRate(freq); switch (quality) { case 0: im = B_DROP_SAMPLE; break; case 1: im = B_2_POINT_INTERPOLATION; do_uconvert("fast", U_ASCII, tmp3, U_CURRENT, sizeof(tmp3)); break; case 2: im = B_LINEAR_INTERPOLATION; do_uconvert("linear", U_ASCII, tmp3, U_CURRENT, sizeof(tmp3)); break; } be_synth->SetInterpolation(im); /* Sets up driver description */ uszprintf(be_midi_driver_desc, sizeof(be_midi_driver_desc), uconvert_ascii("BeOS %s quality synth, %s %d kHz, %s reverberation", tmp), uconvert_ascii(mode ? "high" : "low", tmp2), tmp3, (be_synth->SamplingRate() / 1000), reverb_name[reverb]); midi_beos.desc = be_midi_driver_desc; return 0; } /* be_midi_exit: * Shuts down MIDI subsystem. */ extern "C" void be_midi_exit(int input) { if (_be_midisynth) { _be_midisynth->AllNotesOff(false); delete _be_midisynth; _be_midisynth = NULL; } } /* be_midi_set_mixer_volume: * Sets MIDI mixer output volume. */ extern "C" int be_midi_set_mixer_volume(int volume) { _be_midisynth->SetVolume((double)volume / 255.0); return 0; } /* be_midi_get_mixer_volume: * Returns MIDI mixer output volume. */ extern "C" int be_midi_get_mixer_volume(void) { return (int)(_be_midisynth->Volume() * 255); } /* be_midi_key_on: * Triggers a specified voice. */ extern "C" void be_midi_key_on(int inst, int note, int bend, int vol, int pan) { int voice; if (inst > 127) { /* percussion */ /* hack to use channel 10 only */ midi_beos.xmin = midi_beos.xmax = -1; voice = _midi_allocate_voice(10, 10); midi_beos.xmin = midi_beos.xmax = 10; if (voice < 0) return; cur_note[10] = inst - 128; cur_vol[10] = vol; be_midi_set_pan(voice, pan); _be_midisynth->NoteOn(10, inst - 128, vol, B_NOW); } else { /* normal instrument */ voice = _midi_allocate_voice(1, 16); if (voice < 0) return; if (inst != cur_patch[voice]) { _be_midisynth->ProgramChange(voice, inst); cur_patch[voice] = inst; } cur_note[voice] = note; cur_vol[voice] = vol; be_midi_set_pitch(voice, note, bend); be_midi_set_pan(voice, pan); _be_midisynth->NoteOn(voice, note, vol, B_NOW); } } /* be_midi_key_off: * Turns off specified voice. */ extern "C" void be_midi_key_off(int voice) { _be_midisynth->NoteOff(voice, cur_note[voice], cur_vol[voice], B_NOW); } /* be_midi_set_volume: * Sets volume for a specified voice. */ extern "C" void be_midi_set_volume(int voice, int vol) { /* This seems to work */ _be_midisynth->ChannelPressure(voice, vol, B_NOW); } /* be_midi_set_pitch: * Sets pitch of specified voice. */ extern "C" void be_midi_set_pitch(int voice, int note, int bend) { /* ?? Is this correct? */ _be_midisynth->PitchBend(voice, bend & 0x7F, bend >> 7, B_NOW); } /* be_midi_set_pan: * Sets pan value on specified voice. */ extern "C" void be_midi_set_pan(int voice, int pan) { _be_midisynth->ControlChange(voice, B_PAN, pan); } allegro-4.4.3.1/src/beos/bdispsw.cpp0000664000175000017500000000222213437077643016174 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS display switching routines. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif int _be_switch_mode = SWITCH_PAUSE; /* be_sys_set_display_switch_mode: * Initializes new display switching mode. */ extern "C" int be_sys_set_display_switch_mode(int mode) { /* Fullscreen only supports SWITCH_AMNESIA */ if ((_be_allegro_screen) && (mode != SWITCH_AMNESIA)) return -1; _be_switch_mode = mode; return 0; } allegro-4.4.3.1/src/beos/bsystem.c0000664000175000017500000000517313437077643015657 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif SYSTEM_DRIVER system_beos = { SYSTEM_BEOS, empty_string, empty_string, "System", be_sys_init, be_sys_exit, be_sys_get_executable_name, be_sys_find_resource, be_sys_set_window_title, be_sys_set_close_button_callback, be_sys_message, NULL, // AL_METHOD(void, assert, (char *msg)); NULL, // AL_METHOD(void, save_console_state, (void)); NULL, // AL_METHOD(void, restore_console_state, (void)); NULL, // AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); NULL, // AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); NULL, // AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); NULL, // AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); NULL, // AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(void, read_hardware_palette, (void)); NULL, // AL_METHOD(void, set_palette_range, (struct RGB *p, int from, int to, int vsync)); NULL, // AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); be_sys_set_display_switch_mode, NULL, // AL_METHOD(void, display_switch_lock, (int lock)); be_sys_desktop_color_depth, be_sys_get_desktop_resolution, be_sys_get_gfx_safe_mode, be_sys_yield_timeslice, be_sys_create_mutex, be_sys_destroy_mutex, be_sys_lock_mutex, be_sys_unlock_mutex, NULL, // AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); NULL, // AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); NULL, // AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); NULL, // AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); NULL, // AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); NULL, // AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); NULL // AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); }; allegro-4.4.3.1/src/beos/btimedrv.c0000664000175000017500000000155113437077643016001 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif _DRIVER_INFO _timer_driver_list[] = { {TIMER_BEOS, &timer_beos, TRUE}, {0, NULL, 0} }; allegro-4.4.3.1/src/beos/bsnd.c0000664000175000017500000000327013437077643015113 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif DIGI_DRIVER digi_beos = { DIGI_BEOS, empty_string, empty_string, "BeOS Sound", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, be_sound_detect, be_sound_init, be_sound_exit, be_sound_set_mixer_volume, be_sound_get_mixer_volume, be_sound_lock_voice, be_sound_unlock_voice, be_sound_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; allegro-4.4.3.1/src/beos/baccel.cpp0000664000175000017500000002556013437077643015744 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Accelerated gfx routines for BeOS. * * Based on similar functions for Windows/X, by Jason Wilkins * and Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif /* our hooks table */ HOOKS _be_hooks; /* the sync function pointer */ int32 (*_be_sync_func)() = NULL; /* software version pointers */ static void (*_orig_hline) (BITMAP *bmp, int x1, int y, int x2, int color); static void (*_orig_vline) (BITMAP *bmp, int x, int y1, int y2, int color); static void (*_orig_rectfill) (BITMAP *bmp, int x1, int y1, int x2, int y2, int color); #define MAKE_HLINE(bpp) \ static void be_gfx_accel_hline_##bpp(BITMAP *bmp, int x1, int y, int x2, int color) \ { \ if (_drawing_mode != DRAW_MODE_SOLID) { \ _orig_hline(bmp, x1, y, x2, color); \ return; \ } \ \ if (x1 > x2) { \ int tmp = x1; \ x1 = x2; \ x2 = tmp; \ } \ \ if (bmp->clip) { \ if ((y < bmp->ct) || (y >= bmp->cb)) \ return; \ \ if (x1 < bmp->cl) \ x1 = bmp->cl; \ \ if (x2 >= bmp->cr) \ x2 = bmp->cr-1; \ \ if (x2 < x1) \ return; \ } \ \ x1 += bmp->x_ofs; \ y += bmp->y_ofs; \ x2 += bmp->x_ofs; \ \ if (_be_lock_count) \ _be_hooks.draw_rect_##bpp(x1, y, x2, y, color); \ else { \ acquire_sem(_be_fullscreen_lock); \ _be_hooks.draw_rect_##bpp(x1, y, x2, y, color); \ release_sem(_be_fullscreen_lock); \ } \ bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); \ } #define MAKE_VLINE(bpp) \ static void be_gfx_accel_vline_##bpp(BITMAP *bmp, int x, int y1, int y2, int color) \ { \ if (_drawing_mode != DRAW_MODE_SOLID) { \ _orig_vline(bmp, x, y1, y2, color); \ return; \ } \ \ if (y1 > y2) { \ int tmp = y1; \ y1 = y2; \ y2 = tmp; \ } \ \ if (bmp->clip) { \ if ((x < bmp->cl) || (x >= bmp->cr)) \ return; \ \ if (y1 < bmp->ct) \ y1 = bmp->ct; \ \ if (y2 >= bmp->cb) \ y2 = bmp->cb-1; \ \ if (y2 < y1) \ return; \ } \ \ x += bmp->x_ofs; \ y1 += bmp->y_ofs; \ y2 += bmp->y_ofs; \ \ if (_be_lock_count) \ _be_hooks.draw_rect_##bpp(x, y1, x, y2, color); \ else { \ acquire_sem(_be_fullscreen_lock); \ _be_hooks.draw_rect_##bpp(x, y1, x, y2, color); \ release_sem(_be_fullscreen_lock); \ } \ bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); \ } #define MAKE_RECTFILL(bpp) \ static void be_gfx_accel_rectfill_##bpp(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) \ { \ if (_drawing_mode != DRAW_MODE_SOLID) { \ _orig_rectfill(bmp, x1, y1, x2, y2, color); \ return; \ } \ \ if (x2 < x1) { \ int tmp = x1; \ x1 = x2; \ x2 = tmp; \ } \ \ if (y2 < y1) { \ int tmp = y1; \ y1 = y2; \ y2 = tmp; \ } \ \ if (bmp->clip) { \ if (x1 < bmp->cl) \ x1 = bmp->cl; \ \ if (x2 >= bmp->cr) \ x2 = bmp->cr-1; \ \ if (x2 < x1) \ return; \ \ if (y1 < bmp->ct) \ y1 = bmp->ct; \ \ if (y2 >= bmp->cb) \ y2 = bmp->cb-1; \ \ if (y2 < y1) \ return; \ } \ \ x1 += bmp->x_ofs; \ y1 += bmp->y_ofs; \ x2 += bmp->x_ofs; \ y2 += bmp->y_ofs; \ \ if (_be_lock_count) \ _be_hooks.draw_rect_##bpp(x1, y1, x2, y2, color); \ else { \ acquire_sem(_be_fullscreen_lock); \ _be_hooks.draw_rect_##bpp(x1, y1, x2, y2, color); \ release_sem(_be_fullscreen_lock); \ } \ bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); \ } #define MAKE_CLEAR_TO_COLOR(bpp) \ static void be_gfx_accel_clear_to_color_##bpp(BITMAP *bmp, int color) \ { \ int x1, y1, x2, y2; \ \ x1 = bmp->cl + bmp->x_ofs; \ y1 = bmp->ct + bmp->y_ofs; \ x2 = bmp->cr + bmp->x_ofs - 1; \ y2 = bmp->cb + bmp->y_ofs - 1; \ \ if (_be_lock_count) \ _be_hooks.draw_rect_##bpp(x1, y1, x2, y2, color); \ else { \ acquire_sem(_be_fullscreen_lock); \ _be_hooks.draw_rect_##bpp(x1, y1, x2, y2, color); \ release_sem(_be_fullscreen_lock); \ } \ bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); \ } MAKE_HLINE(8); MAKE_HLINE(16); MAKE_HLINE(32); MAKE_VLINE(8); MAKE_VLINE(16); MAKE_VLINE(32); MAKE_RECTFILL(8); MAKE_RECTFILL(16); MAKE_RECTFILL(32); MAKE_CLEAR_TO_COLOR(8); MAKE_CLEAR_TO_COLOR(16); MAKE_CLEAR_TO_COLOR(32); /* be_gfx_accel_blit_to_self: * */ static void be_gfx_accel_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { source_x += source->x_ofs; source_y += source->y_ofs; dest_x += dest->x_ofs; dest_y += dest->y_ofs; if (_be_lock_count) _be_hooks.blit(source_x, source_y, dest_x, dest_y, width - 1, height - 1); else { acquire_sem(_be_fullscreen_lock); _be_hooks.blit(source_x, source_y, dest_x, dest_y, width - 1, height - 1); release_sem(_be_fullscreen_lock); } dest->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); } /* be_gfx_bwindowscreen_accelerate: * Detects and initializes hardware accelerated gfx functions. */ extern "C" void be_gfx_bwindowscreen_accelerate(int depth) { _be_hooks.draw_line_8 = (LINE8_HOOK) _be_allegro_screen->CardHookAt(LINE8_HOOK_NUM); _be_hooks.draw_line_16 = (LINE16_HOOK) _be_allegro_screen->CardHookAt(LINE16_HOOK_NUM); _be_hooks.draw_line_32 = (LINE32_HOOK) _be_allegro_screen->CardHookAt(LINE32_HOOK_NUM); _be_hooks.draw_array_8 = (ARRAY8_HOOK) _be_allegro_screen->CardHookAt(ARRAY8_HOOK_NUM); _be_hooks.draw_array_32 = (ARRAY32_HOOK)_be_allegro_screen->CardHookAt(ARRAY32_HOOK_NUM); _be_hooks.draw_rect_8 = (RECT8_HOOK) _be_allegro_screen->CardHookAt(RECT8_HOOK_NUM); _be_hooks.draw_rect_16 = (RECT16_HOOK) _be_allegro_screen->CardHookAt(RECT16_HOOK_NUM); _be_hooks.draw_rect_32 = (RECT32_HOOK) _be_allegro_screen->CardHookAt(RECT32_HOOK_NUM); _be_hooks.invert_rect = (INVERT_HOOK) _be_allegro_screen->CardHookAt(INVERT_HOOK_NUM); _be_hooks.blit = (BLIT_HOOK) _be_allegro_screen->CardHookAt(BLIT_HOOK_NUM); _be_hooks.sync = (SYNC_HOOK) _be_allegro_screen->CardHookAt(SYNC_HOOK_NUM); gfx_capabilities = 0; if (!_be_hooks.sync) return; _orig_hline = _screen_vtable.hline; _orig_vline = _screen_vtable.vline; _orig_rectfill = _screen_vtable.rectfill; switch (depth) { case 8: if ((_be_hooks.draw_line_8) || (_be_hooks.draw_rect_8)) { _screen_vtable.hline = be_gfx_accel_hline_8; _screen_vtable.vline = be_gfx_accel_vline_8; } if (_be_hooks.draw_line_8) { gfx_capabilities |= GFX_HW_LINE; } if (_be_hooks.draw_rect_8) { _screen_vtable.rectfill = be_gfx_accel_rectfill_8; _screen_vtable.clear_to_color = be_gfx_accel_clear_to_color_8; gfx_capabilities |= GFX_HW_FILL; } break; case 15: case 16: if ((_be_hooks.draw_line_16) || (_be_hooks.draw_rect_16)) { _screen_vtable.hline = be_gfx_accel_hline_16; _screen_vtable.vline = be_gfx_accel_vline_16; } if (_be_hooks.draw_line_16) { gfx_capabilities |= GFX_HW_LINE; } if (_be_hooks.draw_rect_16) { _screen_vtable.rectfill = be_gfx_accel_rectfill_16; _screen_vtable.clear_to_color = be_gfx_accel_clear_to_color_16; gfx_capabilities |= GFX_HW_FILL; } break; case 32: if ((_be_hooks.draw_line_32) || (_be_hooks.draw_rect_32)) { _screen_vtable.hline = be_gfx_accel_hline_32; _screen_vtable.vline = be_gfx_accel_vline_32; } if (_be_hooks.draw_line_32) { gfx_capabilities |= GFX_HW_LINE; } if (_be_hooks.draw_rect_32) { _screen_vtable.rectfill = be_gfx_accel_rectfill_32; _screen_vtable.clear_to_color = be_gfx_accel_clear_to_color_32; gfx_capabilities |= GFX_HW_FILL; } break; } if (_be_hooks.invert_rect) gfx_capabilities |= GFX_HW_FILL_XOR; if (_be_hooks.blit) { _screen_vtable.blit_to_self = be_gfx_accel_blit_to_self; _screen_vtable.blit_to_self_forward = be_gfx_accel_blit_to_self; _screen_vtable.blit_to_self_backward = be_gfx_accel_blit_to_self; gfx_capabilities |= GFX_HW_VRAM_BLIT; } _be_sync_func = _be_hooks.sync; } allegro-4.4.3.1/src/beos/bkeyapi.cpp0000664000175000017500000002407613437077643016160 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS keyboard driver. * * By Jason Wilkins, rewritten by Angelo Mottola to use the unified * pckeys API. * * See readme.txt for copyright information. */ #include #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define KEY_ID_PC101 0 // the docs say it should be 0x83ab, but they lie #define KEY_SEMAPHORE_NAME "keyboard driver waiting..." #define KEY_THREAD_PERIOD 33333 // microseconds, 1/30th of a second #define KEY_THREAD_NAME "keyboard driver" #define KEY_THREAD_PRIORITY 60 // above average #define BE_KEY_PAUSE 16 #define BE_KEY_NUMLOCK 34 #define BE_KEY_CAPSLOCK 59 #define BE_KEY_SCROLOCK 15 #define PREFIX_I "al-bkey INFO: " #define PREFIX_W "al-bkey WARNING: " #define PREFIX_E "al-bkey ERROR: " static uint16 keyboard_id = (uint16)(-1); static volatile int keyboard_thread_running = FALSE; static thread_id keyboard_thread_id = -1; static sem_id waiting_for_input = -1; static const int be_to_pc[128] = { // Scancode Be Key -1, // 0 (not used) 0x1, // 1 ESC 0x3b, // 2 F1 0x3c, // 3 F2 0x3d, // 4 F3 0x3e, // 5 F4 0x3f, // 6 F5 0x40, // 7 F6 0x41, // 8 F7 0x42, // 9 F8 0x43, // 10 F9 0x44, // 11 F10 0x57, // 12 F11 0x58, // 13 F12 0x54, // 14 Print Screen / SysRq 0x46, // 15 Scroll Lock 0, // 16 Pause / Break 0x29, // 17 Tilde 0x2, // 18 '1' 0x3, // 19 '2' 0x4, // 20 '3' 0x5, // 21 '4' 0x6, // 22 '5' 0x7, // 23 '6' 0x8, // 24 '7' 0x9, // 25 '8' 0xa, // 26 '9' 0xb, // 27 '0' 0xc, // 28 '-' 0xd, // 29 '=' 0xe, // 30 Backspace 0x5200, // 31 Insert 0x4700, // 32 Home 0x4900, // 33 Page Up 0x45, // 34 Num Lock 0x3500, // 35 Pad '/' 0x37, // 36 Pad '*' 0x4a, // 37 Pad '-' 0xf, // 38 Tab 0x10, // 39 'q' 0x11, // 40 'w' 0x12, // 41 'e' 0x13, // 42 'r' 0x14, // 43 't' 0x15, // 44 'y' 0x16, // 45 'u' 0x17, // 46 'i' 0x18, // 47 'o' 0x19, // 48 'p' 0x1a, // 49 '[' 0x1b, // 50 ']' 0x35, // 51 '\' 0x5300, // 52 Delete 0x4f00, // 53 End 0x5100, // 54 Page Down 0x47, // 55 Pad '7' 0x48, // 56 Pad '8' 0x49, // 57 Pad '9' 0x4e, // 58 Pad '+' 0x3a, // 59 Caps Lock 0x1e, // 60 'a' 0x1f, // 61 's' 0x20, // 62 'd' 0x21, // 63 'f' 0x22, // 64 'g' 0x23, // 65 'h' 0x24, // 66 'j' 0x25, // 67 'k' 0x26, // 68 'l' 0x27, // 69 ';' 0x28, // 70 ''' 0x1c, // 71 Enter 0x4b, // 72 Pad '4' 0x4c, // 73 Pad '5' 0x4d, // 74 Pad '6' 0x2a, // 75 Left Shift 0x2c, // 76 'z' 0x2d, // 77 'x' 0x2e, // 78 'c' 0x2f, // 79 'v' 0x30, // 80 'b' 0x31, // 81 'n' 0x32, // 82 'm' 0x33, // 83 ',' 0x34, // 84 '.' 0x35, // 85 '/' 0x36, // 86 Right Shift 0x4800, // 87 Up 0x4f, // 88 Pad '1' 0x50, // 89 Pad '2' 0x51, // 90 Pad '3' 0x1c00, // 91 Pad Enter 0x1d, // 92 Left Control 0x38, // 93 Left Alt 0x39, // 94 Space 0x3800, // 95 Right Alt 0x1d00, // 96 Right Control 0x4b00, // 97 Left 0x5000, // 98 Down 0x4d00, // 99 Right 0x52, // 100 Pad '0' 0x53, // 101 Pad Del 0x5b, // 102 Left Windows Key 0x5c, // 103 Right Windows Key 0x5d, // 104 Menu -1, // 105 (not used) -1, // 106 (not used) -1, // 107 (not used) -1, // 108 (not used) -1, // 109 (not used) -1, // 110 (not used) -1, // 111 (not used) -1, // 112 (not used) -1, // 113 (not used) -1, // 114 (not used) -1, // 115 (not used) -1, // 116 (not used) -1, // 117 (not used) -1, // 118 (not used) -1, // 119 (not used) -1, // 120 (not used) -1, // 121 (not used) -1, // 122 (not used) -1, // 123 (not used) -1, // 124 (not used) -1, // 125 (not used) -1, // 126 (not used) -1 // 127 (not used) }; /* keyboard_thread: */ static int32 keyboard_thread(void *keyboard_started) { key_info key_info_old; key_info key_info_new; get_key_info(&key_info_old); if (key_info_old.modifiers & B_CAPS_LOCK) _key_shifts |= KB_CAPSLOCK_FLAG; if (key_info_old.modifiers & B_SCROLL_LOCK) _key_shifts |= KB_SCROLOCK_FLAG; if (key_info_old.modifiers & B_NUM_LOCK) _key_shifts |= KB_NUMLOCK_FLAG; release_sem(*(sem_id *)keyboard_started); while(keyboard_thread_running) { int i; snooze(KEY_THREAD_PERIOD); if (!_be_focus_count) continue; get_key_info(&key_info_new); if (three_finger_flag && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG) && (key_info_new.key_states[52 / 8] & (52 % 8)) ) { _be_terminate(keyboard_thread_id, true); } for (i=0; i<128; i++) { int new_key_pressed; int old_key_pressed; int scancode; new_key_pressed = key_info_new.key_states[i >> 3] & (1 << (7 - (i % 8))); old_key_pressed = key_info_old.key_states[i >> 3] & (1 << (7 - (i % 8))); if (new_key_pressed != old_key_pressed) { scancode = be_to_pc[i]; if (scancode != -1) { if (i == BE_KEY_PAUSE) { /* pause key special case */ _handle_key_press(0, KEY_PAUSE); _handle_key_release(KEY_PAUSE); continue; } if ((i == BE_KEY_CAPSLOCK) || (i == BE_KEY_SCROLOCK) || (i == BE_KEY_NUMLOCK)) { /* caps lock, scroll lock, and num lock special cases */ _handle_pckey(scancode); _handle_pckey(scancode | 0x80); continue; } if (scancode & 0xff00) { /* extended code */ _handle_pckey(0xe0); scancode >>= 8; } /* handle normal key press/release */ if (!new_key_pressed) scancode |= 0x80; _handle_pckey(scancode); } } } key_info_old = key_info_new; } /* XXX commented out due to conflicting TRACE in Haiku TRACE(PREFIX_I "keyboard thread exited\n"); */ return 0; } /* set_default_key_repeat: */ static inline bool set_default_key_repeat(void) { int32 rate; bigtime_t delay; if (get_key_repeat_rate(&rate) != B_OK) { return false; } if (get_key_repeat_delay(&delay) != B_OK) { return false; } set_keyboard_rate((delay / 1000), (10000 / rate)); return true; } /* be_key_init: */ extern "C" int be_key_init(void) { sem_id keyboard_started; _pckeys_init(); if (get_keyboard_id(&keyboard_id) == B_ERROR) { goto cleanup; } if (keyboard_id != KEY_ID_PC101) { goto cleanup; } waiting_for_input = create_sem(0, "waiting for input..."); if (waiting_for_input < B_NO_ERROR) { goto cleanup; } keyboard_started = create_sem(0, "starting keyboard thread..."); if (keyboard_started < B_NO_ERROR) { goto cleanup; } keyboard_thread_id = spawn_thread(keyboard_thread, KEY_THREAD_NAME, KEY_THREAD_PRIORITY, &keyboard_started); if (keyboard_thread_id < 0) { goto cleanup; } keyboard_thread_running = TRUE; resume_thread(keyboard_thread_id); acquire_sem(keyboard_started); delete_sem(keyboard_started); if(!set_default_key_repeat()) { goto cleanup; } return 0; cleanup: { if (keyboard_started > 0) { delete_sem(keyboard_started); } be_key_exit(); return 1; } } /* be_key_exit: */ extern "C" void be_key_exit(void) { if (keyboard_thread_id > 0) { keyboard_thread_running = FALSE; wait_for_thread(keyboard_thread_id, &ignore_result); keyboard_thread_id = -1; } if (waiting_for_input > 0) { delete_sem(waiting_for_input); waiting_for_input = -1; } keyboard_id = (uint16)(-1); } /* be_key_set_leds: * Sets keyboard leds. */ extern "C" void be_key_set_leds(int leds) { uint32 modifiers; modifiers = 0; _key_shifts &= ~(KB_CAPSLOCK_FLAG | KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG); if (leds & KB_CAPSLOCK_FLAG) { modifiers |= B_CAPS_LOCK; _key_shifts |= KB_CAPSLOCK_FLAG; } if (leds & KB_SCROLOCK_FLAG) { modifiers |= B_SCROLL_LOCK; _key_shifts |= KB_SCROLOCK_FLAG; } if (leds & KB_NUMLOCK_FLAG) { modifiers |= B_NUM_LOCK; _key_shifts |= KB_NUMLOCK_FLAG; } set_keyboard_locks(modifiers); } /* be_key_set_rate: * Sets keyboard repeat rate and delay. */ extern "C" void be_key_set_rate(int delay, int repeat) { if (delay < 250) delay = 250; else if (delay < 500) delay = 500; else if (delay < 750) delay = 750; else delay = 1000; set_key_repeat_delay((bigtime_t)(delay * 1000)); if (repeat > 0) set_key_repeat_rate(10000 / repeat); } /* be_key_wait_for_input: */ extern "C" void be_key_wait_for_input(void) { acquire_sem(waiting_for_input); } /* be_key_stop_waiting_for_input: */ extern "C" void be_key_stop_waiting_for_input(void) { release_sem(waiting_for_input); } extern "C" void be_key_suspend(void) { suspend_thread(keyboard_thread_id); } extern "C" void be_key_resume(void) { resume_thread(keyboard_thread_id); } allegro-4.4.3.1/src/beos/bswitch.s0000664000175000017500000000527013437077643015652 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS gfx line switchers. * * By Jason Wilkins. * * Windowed mode support added by Angelo Mottola. * * See readme.txt for copyright information. */ #include "src/i386/asmdefs.inc" .text /* _be_gfx_bwindowscreen_read_write_bank_asm: * eax = line number * edx = bitmap */ FUNC(_be_gfx_bwindowscreen_read_write_bank_asm) /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked pushl %ecx pushl %eax pushl %edx call *GLOBL(_be_sync_func) popl %edx popl %eax popl %ecx /* set lock and autolock flags */ orl $(BMP_ID_LOCKED | BMP_ID_AUTOLOCK), BMP_ID(%edx) Locked: /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* _be_gfx_bwindowscreen_unwrite_bank_asm: * edx = bitmap */ FUNC(_be_gfx_bwindowscreen_unwrite_bank_asm) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock /* clear lock and autolock flags */ andl $~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK), BMP_ID(%edx) No_unlock: ret /* _be_gfx_bwindow_read_write_bank_asm: * eax = line number * edx = bitmap */ FUNC(_be_gfx_bwindow_read_write_bank_asm) /* clobber the line */ pushl %ecx pushl %eax movl GLOBL(_be_dirty_lines), %ecx addl BMP_YOFFSET(%edx), %eax movl $1, (%ecx, %eax, 4) /* _be_dirty_lines[line] = 1; (line has changed) */ popl %eax popl %ecx /* check whether bitmap is already locked */ testl $BMP_ID_LOCKED, BMP_ID(%edx) jnz Locked_win /* set lock and autolock flags */ orl $(BMP_ID_LOCKED | BMP_ID_AUTOLOCK), BMP_ID(%edx) Locked_win: /* get pointer to the video memory */ movl BMP_LINE(%edx,%eax,4), %eax ret /* _be_gfx_bwindow_unwrite_bank_asm: * edx = bitmap */ FUNC(_be_gfx_bwindow_unwrite_bank_asm) /* only unlock bitmaps that were autolocked */ testl $BMP_ID_AUTOLOCK, BMP_ID(%edx) jz No_unlock_win pushl %ecx pushl %eax pushl %edx pushl GLOBL(_be_window_lock) call GLOBL(release_sem) popl %edx /* throw away GLOBL(_be_window_lock) */ popl %edx popl %eax popl %ecx andl $~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK), BMP_ID(%edx) No_unlock_win: ret allegro-4.4.3.1/src/beos/bgfxdrv.c0000664000175000017500000000150713437077643015630 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif BEGIN_GFX_DRIVER_LIST GFX_DRIVER_BEOS END_GFX_DRIVER_LIST allegro-4.4.3.1/src/beos/boverlay.cpp0000664000175000017500000001716013437077643016353 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS fullscreen overlay gfx driver. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif static char driver_desc[256] = EMPTY_STRING; static display_mode old_display_mode; /* BeAllegroOverlay::BeAllegroOverlay: * Constructor, creates the window and the overlay bitmap to be used * as framebuffer. */ BeAllegroOverlay::BeAllegroOverlay(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspaces, uint32 v_w, uint32 v_h, uint32 color_depth) : BWindow(frame, title, look, feel, flags, workspaces) { BRect rect = Bounds(); color_space space = B_NO_COLOR_SPACE; _be_allegro_view = new BeAllegroView(rect, "Allegro", B_FOLLOW_ALL_SIDES, B_WILL_DRAW, BE_ALLEGRO_VIEW_OVERLAY); AddChild(_be_allegro_view); switch (color_depth) { case 15: space = B_RGB15; break; case 16: space = B_RGB16; break; case 32: space = B_RGB32; break; } buffer = new BBitmap(rect, B_BITMAP_IS_CONTIGUOUS | B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, space); } /* BeAllegroOverlay::BeAllegroOverlay: * Deletes the overlay bitmap. */ BeAllegroOverlay::~BeAllegroOverlay() { Hide(); _be_focus_count = 0; if (buffer) delete buffer; buffer = NULL; } /* BeAllegroOverlay::MessageReceived: * System messages handler. */ void BeAllegroOverlay::MessageReceived(BMessage *message) { switch (message->what) { case B_SIMPLE_DATA: break; case B_MOUSE_WHEEL_CHANGED: float dy; message->FindFloat("be:wheel_delta_y", &dy); _be_mouse_z += ((int)dy > 0 ? -1 : 1); break; default: BWindow::MessageReceived(message); break; } } /* BeAllegroOverlay::WindowActivated: * Callback for when the window gains/looses focus. */ void BeAllegroOverlay::WindowActivated(bool active) { _be_change_focus(active); BWindow::WindowActivated(active); } /* BeAllegroOverlay::QuitRequested: * User requested to close the program window. */ bool BeAllegroOverlay::QuitRequested(void) { return _be_handle_window_close(Title()); } /* is_overlay_supported: * Checks if the card can support hardware scaling from given * source to dest rectangles. */ static bool is_overlay_supported(BRect *src, BRect *dest) { overlay_restrictions restrictions; float src_w, src_h, dest_w, dest_h; if (_be_allegro_overlay->buffer->GetOverlayRestrictions(&restrictions) != B_OK) return false; src_w = src->right - src->left + 1; src_h = src->bottom - src->top + 1; dest_w = dest->right - dest->left + 1; dest_h = dest->bottom - dest->top + 1; return ((src_w * restrictions.min_width_scale <= dest_w) && (src_w * restrictions.max_width_scale >= dest_w) && (src_h * restrictions.min_height_scale <= dest_h) && (src_h * restrictions.max_height_scale >= dest_h)); } /* be_gfx_overlay_init: * Sets up overlay video mode. */ extern "C" struct BITMAP *be_gfx_overlay_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; BRect src, dest; int i; if (1 #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((!v_w) && (!v_h)) { v_w = w; v_h = h; } if ((w != v_w) || (h != v_h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } set_display_switch_mode(SWITCH_PAUSE); BScreen().GetMode(&old_display_mode); for (i=0; _be_mode_table[i].d > 0; i++) { if ((_be_mode_table[i].d == color_depth) && (_be_mode_table[i].w >= w) && (_be_mode_table[i].h >= h)) break; } if ((_be_mode_table[i].d <= 0) || (set_screen_space(0, _be_mode_table[i].mode, false) != B_OK)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto cleanup; } src = BRect(0, 0, w - 1, h - 1); dest = BScreen().Frame(); _be_allegro_overlay = new BeAllegroOverlay(src, wnd_title, B_NO_BORDER_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_CURRENT_WORKSPACE, v_w, v_h, color_depth); _be_window = _be_allegro_overlay; if (!_be_allegro_overlay->buffer) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } if ((_be_allegro_overlay->buffer->InitCheck() != B_OK) || (!_be_allegro_overlay->buffer->IsValid()) || (!is_overlay_supported(&src, &dest))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Overlays not supported")); goto cleanup; } _be_mouse_view = new BView(_be_allegro_overlay->Bounds(), "allegro mouse view", B_FOLLOW_ALL_SIDES, 0); _be_allegro_overlay->Lock(); _be_allegro_overlay->AddChild(_be_mouse_view); _be_allegro_overlay->Unlock(); _be_mouse_window = _be_allegro_overlay; _be_mouse_window_mode = true; release_sem(_be_mouse_view_attached); _be_allegro_view->SetViewOverlay(_be_allegro_overlay->buffer, src, dest, &_be_allegro_overlay->color_key, B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL); _be_allegro_view->ClearViewOverlay(); _be_allegro_overlay->ResizeTo(dest.right + 1, dest.bottom + 1); _be_allegro_overlay->MoveTo(0, 0); _be_allegro_overlay->Show(); gfx_beos_overlay.w = w; gfx_beos_overlay.h = h; gfx_beos_overlay.linear = TRUE; gfx_beos_overlay.vid_mem = _be_allegro_overlay->buffer->BitsLength(); bmp = _make_bitmap(v_w, v_h, (unsigned long)_be_allegro_overlay->buffer->Bits(), &gfx_beos_overlay, color_depth, _be_allegro_overlay->buffer->BytesPerRow()); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } _be_gfx_set_truecolor_shifts(); uszprintf(driver_desc, sizeof(driver_desc), get_config_text("BWindow object, %d bit BBitmap framebuffer (overlay)"), color_depth); gfx_beos_overlay.desc = driver_desc; _be_gfx_initialized = true; return bmp; cleanup: be_gfx_overlay_exit(NULL); return NULL; } /* be_gfx_overlay_exit: * Shuts down the driver. */ extern "C" void be_gfx_overlay_exit(struct BITMAP *bmp) { _be_gfx_initialized = false; if (_be_allegro_overlay) { if (_be_mouse_view_attached < 1) { acquire_sem(_be_mouse_view_attached); } _be_allegro_overlay->Lock(); _be_allegro_overlay->Quit(); _be_allegro_overlay = NULL; _be_window = NULL; } _be_mouse_window = NULL; _be_mouse_view = NULL; BScreen().SetMode(&old_display_mode); } allegro-4.4.3.1/src/beos/bjoy.c0000664000175000017500000000272313437077643015132 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver for BeOS. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif JOYSTICK_DRIVER joystick_beos = { JOYSTICK_BEOS, // int id; empty_string, // AL_CONST char *name; empty_string, // AL_CONST char *desc; "BeOS joystick", // AL_CONST char *ascii_name; be_joy_init, // AL_METHOD(int, init, (void)); be_joy_exit, // AL_METHOD(void, exit, (void)); be_joy_poll, // AL_METHOD(int, poll, (void)); NULL, // AL_METHOD(int, save_data, (void)); NULL, // AL_METHOD(int, load_data, (void)); NULL, // AL_METHOD(AL_CONST char *, calibrate_name, (int n)); NULL // AL_METHOD(int, calibrate, (int n)); }; allegro-4.4.3.1/src/beos/bsysdrv.c0000664000175000017500000000160313437077643015657 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif _DRIVER_INFO _system_driver_list[] = { {SYSTEM_BEOS, &system_beos, TRUE}, {SYSTEM_NONE, &system_none, FALSE}, {0, NULL, 0} }; allegro-4.4.3.1/src/beos/btimer.c0000664000175000017500000000316313437077643015450 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif TIMER_DRIVER timer_beos = { TIMER_BEOS, // int id; empty_string, // char *name; empty_string, // char *desc; "Timer", // char *ascii_name; be_time_init, // AL_METHOD(int, init, (void)); be_time_exit, // AL_METHOD(void, exit, (void)); NULL, // AL_METHOD(int, install_int, (AL_METHOD(void, proc, (void)), long speed)); NULL, // AL_METHOD(void, remove_int, (AL_METHOD(void, proc, (void)))); NULL, // AL_METHOD(int, install_param_int, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); NULL, // AL_METHOD(void, remove_param_int, (AL_METHOD(void, proc, (void *param)), void *param)); NULL, // AL_METHOD(int, can_simulate_retrace, (void)); NULL, // AL_METHOD(void, simulate_retrace, (int enable)); be_time_rest, // AL_METHOD(void, rest, (long time, AL_METHOD(void, callback, (void)))); }; allegro-4.4.3.1/src/beos/bsndapi.cpp0000664000175000017500000001453213437077643016150 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS sound driver implementation. * * Originally by Peter Wang, rewritten to use the BSoundPlayer * class by Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #ifndef SCAN_DEPEND #include #endif #ifdef ALLEGRO_BIG_ENDIAN #define BE_SOUND_ENDIAN B_MEDIA_BIG_ENDIAN #else #define BE_SOUND_ENDIAN B_MEDIA_LITTLE_ENDIAN #endif sem_id _be_sound_stream_lock = -1; static bool be_sound_active = false; static bool be_sound_stream_locked = false; static BLocker *locker = NULL; static BSoundPlayer *be_sound = NULL; static int be_sound_bufsize; static int be_sound_signed; static char be_sound_desc[256] = EMPTY_STRING; /* be_sound_handler: * Update data. */ static void be_sound_handler(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format) { locker->Lock(); acquire_sem(_be_sound_stream_lock); if (be_sound_active) { _mix_some_samples((unsigned long)buffer, 0, be_sound_signed); } else { memset(buffer, 0, size); } release_sem(_be_sound_stream_lock); locker->Unlock(); } /* be_sound_detect. * Return TRUE if sound available. */ extern "C" int be_sound_detect(int input) { BSoundPlayer *sound; media_raw_audio_format format; status_t status; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } format.frame_rate = 11025; format.channel_count = 1; format.format = media_raw_audio_format::B_AUDIO_UCHAR; format.byte_order = BE_SOUND_ENDIAN; format.buffer_size = 0; sound = new BSoundPlayer(&format); status = sound->InitCheck(); delete sound; return (status == B_OK) ? TRUE : FALSE; } /* be_sound_init: * Init sound driver. */ extern "C" int be_sound_init(int input, int voices) { media_raw_audio_format format; char tmp1[128], tmp2[128]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } be_sound_active = false; /* create BPushGameSound instance */ format.frame_rate = (_sound_freq > 0) ? _sound_freq : 44100; format.channel_count = (_sound_stereo) ? 2 : 1; format.format = (_sound_bits == 8) ? (media_raw_audio_format::B_AUDIO_UCHAR) : (media_raw_audio_format::B_AUDIO_SHORT); format.byte_order = BE_SOUND_ENDIAN; format.buffer_size = 0; be_sound = new BSoundPlayer(&format, "Sound player", be_sound_handler); if (be_sound->InitCheck() != B_OK) { goto cleanup; } /* read the sound format back */ format = be_sound->Format(); switch (format.format) { case media_raw_audio_format::B_AUDIO_UCHAR: _sound_bits = 8; be_sound_signed = FALSE; break; case media_raw_audio_format::B_AUDIO_SHORT: _sound_bits = 16; be_sound_signed = TRUE; break; default: goto cleanup; } _sound_stereo = (format.channel_count == 2) ? 1 : 0; _sound_freq = (int)format.frame_rate; /* start internal mixer */ be_sound_bufsize = format.buffer_size; digi_beos.voices = voices; if (_mixer_init(be_sound_bufsize / (_sound_bits / 8), _sound_freq, _sound_stereo, ((_sound_bits == 16) ? 1 : 0), &digi_beos.voices) != 0) { goto cleanup; } /* start audio output */ locker = new BLocker(); if (!locker) goto cleanup; be_sound->Start(); be_sound->SetHasData(true); uszprintf(be_sound_desc, sizeof(be_sound_desc), get_config_text("%d bits, %s, %d bps, %s"), _sound_bits, uconvert_ascii(be_sound_signed ? "signed" : "unsigned", tmp1), _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp2)); digi_driver->desc = be_sound_desc; be_sound_active = true; return 0; cleanup: { be_sound_exit(input); return -1; } } /* be_sound_exit: * Shutdown sound driver. */ extern "C" void be_sound_exit(int input) { if (input) { return; } be_sound_active = false; be_sound->Stop(); acquire_sem(_be_sound_stream_lock); _mixer_exit(); release_sem(_be_sound_stream_lock); delete be_sound; delete locker; be_sound = NULL; locker = NULL; } /* be_sound_lock_voice: * Locks audio stream for exclusive access. */ extern "C" void *be_sound_lock_voice(int voice, int start, int end) { if (!be_sound_stream_locked) { be_sound_stream_locked = true; acquire_sem(_be_sound_stream_lock); } return NULL; } /* be_sound_unlock_voice: * Unlocks audio stream. */ void be_sound_unlock_voice(int voice) { if (be_sound_stream_locked) { be_sound_stream_locked = false; release_sem(_be_sound_stream_lock); } } /* be_sound_buffer_size: * Returns the current buffer size, for use by the audiostream code. */ extern "C" int be_sound_buffer_size() { return be_sound_bufsize / (_sound_bits / 8) / (_sound_stereo ? 2 : 1); } /* be_sound_set_mixer_volume: * Set mixer volume. */ extern "C" int be_sound_set_mixer_volume(int volume) { if (!be_sound) return -1; be_sound->SetVolume((float)volume / 255.0); return 0; } /* be_sound_get_mixer_volume: * Set mixer volume. */ extern "C" int be_sound_get_mixer_volume(void) { if (!be_sound) return -1; return (int)(be_sound->Volume() * 255.0); } /* be_sound_suspend: * Pauses the sound output. */ extern "C" void be_sound_suspend(void) { if (!be_sound) return; locker->Lock(); be_sound_active = false; locker->Unlock(); } /* be_sound_resume: * Resumes the sound output. */ extern "C" void be_sound_resume(void) { if (!be_sound) return; locker->Lock(); be_sound_active = true; locker->Unlock(); } allegro-4.4.3.1/src/beos/bsnddrv.c0000664000175000017500000000151313437077643015625 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif BEGIN_DIGI_DRIVER_LIST DIGI_DRIVER_BEOS END_DIGI_DRIVER_LIST allegro-4.4.3.1/src/beos/bmouse.c0000664000175000017500000000334613437077643015463 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif MOUSE_DRIVER mouse_beos = { MOUSE_BEOS, // int id; empty_string, // char *name; empty_string, // char *desc; "Mouse", // char *ascii_name; be_mouse_init, // AL_METHOD(int, init, (void)); be_mouse_exit, // AL_METHOD(void, exit, (void)); NULL, // AL_METHOD(void, poll, (void)); NULL, // AL_METHOD(void, timer_poll, (void)); be_mouse_position, // AL_METHOD(void, position, (int x, int y)); be_mouse_set_range, // AL_METHOD(void, set_range, (int x1, int y1, int x2, int y2)); be_mouse_set_speed, // AL_METHOD(void, set_speed, (int xspeed, int yspeed)); be_mouse_get_mickeys,// AL_METHOD(void, get_mickeys, (int *mickeyx, int *mickeyy)); NULL, // AL_METHOD(int, analyse_data, (const char *buffer, int size)); NULL, // AL_METHOD(void, enable_hardware_cursor, (AL_CONST int mode)); NULL // AL_METHOD(int, select_system_cursor, (AL_CONST int cursor)); }; allegro-4.4.3.1/src/beos/bmididrv.c0000664000175000017500000000155013437077643015764 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * MIDI drivers list for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif BEGIN_MIDI_DRIVER_LIST MIDI_DRIVER_BEOS MIDI_DRIVER_DIGMID END_MIDI_DRIVER_LIST allegro-4.4.3.1/src/beos/bgfx.c0000664000175000017500000003777613437077643015135 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif GFX_DRIVER gfx_beos_bwindowscreen_accel = { GFX_BWINDOWSCREEN_ACCEL, // int id; empty_string, // char *name; empty_string, // char *desc; "BWindowScreen accel", // char *ascii_name; be_gfx_bwindowscreen_accel_init, // AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); be_gfx_bwindowscreen_exit, // AL_METHOD(void, exit, (struct BITMAP *b)); be_gfx_bwindowscreen_scroll, // AL_METHOD(int, scroll, (int x, int y)); be_gfx_vsync, // AL_METHOD(void, vsync, (void)); be_gfx_bwindowscreen_set_palette, // AL_METHOD(void, set_palette, (struct RGB *p, int from, int to, int vsync)); be_gfx_bwindowscreen_request_scroll,// AL_METHOD(int, request_scroll, (int x, int y)); be_gfx_bwindowscreen_poll_scroll, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, // AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); be_gfx_bwindowscreen_request_video_bitmap,// AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_state, (void)); NULL, // AL_METHOD(void, restore_state, (void)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); be_gfx_bwindowscreen_fetch_mode_list,// AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; /* physical (not virtual!) screen size */ TRUE, // int linear; /* true if video memory is linear */ 0, // long bank_size; /* bank size, in bytes */ 0, // long bank_gran; /* bank granularity, in bytes */ 0, // long vid_mem; /* video memory size, in bytes */ 0, // long vid_phys_base; /* physical address of video memory */ FALSE // int windowed; /* true if driver runs windowed */ }; GFX_DRIVER gfx_beos_bwindowscreen = { GFX_BWINDOWSCREEN, // int id; empty_string, // char *name; empty_string, // char *desc; "BWindowScreen", // char *ascii_name; be_gfx_bwindowscreen_init, // AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); be_gfx_bwindowscreen_exit, // AL_METHOD(void, exit, (struct BITMAP *b)); be_gfx_bwindowscreen_scroll, // AL_METHOD(int, scroll, (int x, int y)); be_gfx_vsync, // AL_METHOD(void, vsync, (void)); be_gfx_bwindowscreen_set_palette, // AL_METHOD(void, set_palette, (struct RGB *p, int from, int to, int vsync)); be_gfx_bwindowscreen_request_scroll,// AL_METHOD(int, request_scroll, (int x, int y)); be_gfx_bwindowscreen_poll_scroll, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, // AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); be_gfx_bwindowscreen_request_video_bitmap,// AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_state, (void)); NULL, // AL_METHOD(void, restore_state, (void)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); be_gfx_bwindowscreen_fetch_mode_list,// AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; /* physical (not virtual!) screen size */ TRUE, // int linear; /* true if video memory is linear */ 0, // long bank_size; /* bank size, in bytes */ 0, // long bank_gran; /* bank granularity, in bytes */ 0, // long vid_mem; /* video memory size, in bytes */ 0, // long vid_phys_base; /* physical address of video memory */ FALSE // int windowed; /* true if driver runs windowed */ }; GFX_DRIVER gfx_beos_bdirectwindow = { GFX_BDIRECTWINDOW, // int id; empty_string, // char *name; empty_string, // char *desc; "BDirectWindow", // char *ascii_name; be_gfx_bdirectwindow_init, // AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); be_gfx_bdirectwindow_exit, // AL_METHOD(void, exit, (struct BITMAP *b)); NULL, // AL_METHOD(int, scroll, (int x, int y)); be_gfx_vsync, // AL_METHOD(void, vsync, (void)); be_gfx_bdirectwindow_set_palette, // AL_METHOD(void, set_palette, (struct RGB *p, int from, int to, int vsync)); NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, // AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_state, (void)); NULL, // AL_METHOD(void, restore_state, (void)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, // AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; /* physical (not virtual!) screen size */ TRUE, // int linear; /* true if video memory is linear */ 0, // long bank_size; /* bank size, in bytes */ 0, // long bank_gran; /* bank granularity, in bytes */ 0, // long vid_mem; /* video memory size, in bytes */ 0, // long vid_phys_base; /* physical address of video memory */ TRUE // int windowed; /* true if driver runs windowed */ }; GFX_DRIVER gfx_beos_bwindow = { GFX_BWINDOW, // int id; empty_string, // char *name; empty_string, // char *desc; "BWindow", // char *ascii_name; be_gfx_bwindow_init, // AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); be_gfx_bwindow_exit, // AL_METHOD(void, exit, (struct BITMAP *b)); NULL, // AL_METHOD(int, scroll, (int x, int y)); be_gfx_vsync, // AL_METHOD(void, vsync, (void)); be_gfx_bwindow_set_palette, // AL_METHOD(void, set_palette, (struct RGB *p, int from, int to, int vsync)); NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, // AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_state, (void)); NULL, // AL_METHOD(void, restore_state, (void)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, // AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; /* physical (not virtual!) screen size */ TRUE, // int linear; /* true if video memory is linear */ 0, // long bank_size; /* bank size, in bytes */ 0, // long bank_gran; /* bank granularity, in bytes */ 0, // long vid_mem; /* video memory size, in bytes */ 0, // long vid_phys_base; /* physical address of video memory */ TRUE // int windowed; /* true if driver runs windowed */ }; GFX_DRIVER gfx_beos_overlay = { GFX_BWINDOW_OVERLAY, // int id; empty_string, // char *name; empty_string, // char *desc; "BWindow (overlay)", // char *ascii_name; be_gfx_overlay_init, // AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); be_gfx_overlay_exit, // AL_METHOD(void, exit, (struct BITMAP *b)); NULL, // AL_METHOD(int, scroll, (int x, int y)); be_gfx_vsync, // AL_METHOD(void, vsync, (void)); NULL, // AL_METHOD(void, set_palette, (struct RGB *p, int from, int to, int vsync)); NULL, // AL_METHOD(int, request_scroll, (int x, int y)); NULL, // AL_METHOD(int, poll_scroll, (void)); NULL, // AL_METHOD(void, enable_triple_buffer, (void)); NULL, // AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); NULL, // AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); NULL, // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); NULL, // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); NULL, // AL_METHOD(void, hide_mouse, (void)); NULL, // AL_METHOD(void, move_mouse, (int x, int y)); NULL, // AL_METHOD(void, drawing_mode, (void)); NULL, // AL_METHOD(void, save_state, (void)); NULL, // AL_METHOD(void, restore_state, (void)); NULL, // AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); NULL, // AL_METHOD(int, fetch_mode_list, (void)); 0, 0, // int w, h; /* physical (not virtual!) screen size */ TRUE, // int linear; /* true if video memory is linear */ 0, // long bank_size; /* bank size, in bytes */ 0, // long bank_gran; /* bank granularity, in bytes */ 0, // long vid_mem; /* video memory size, in bytes */ 0, // long vid_phys_base; /* physical address of video memory */ FALSE // int windowed; /* true if driver runs windowed */ }; allegro-4.4.3.1/src/beos/bdwindow.cpp0000664000175000017500000003430113437077643016341 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windowed BeOS gfx driver based on BDirectWindow. * * By Peter Wang. * * Optimizations and bugfixes by Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define BE_DRAWING_THREAD_PERIOD 16000 #define BE_DRAWING_THREAD_NAME "drawing thread" #define BE_DRAWING_THREAD_PRIORITY B_REAL_TIME_DISPLAY_PRIORITY #define PREFIX_I "al-bdwin INFO: " #define PREFIX_W "al-bdwin WARNING: " #define PREFIX_E "al-bdwin ERROR: " static char driver_desc[256] = EMPTY_STRING; static rgb_color palette_colors[256]; static unsigned char *cmap = NULL; /* _be_gfx_direct_window_drawing_thread: * This thread keeps on updating dirty rectangles on the program * window. */ static int32 _be_gfx_direct_window_drawing_thread(void *data) { BeAllegroDirectWindow *w = (BeAllegroDirectWindow *)data; GRAPHICS_RECT src_gfx_rect, dest_gfx_rect; src_gfx_rect.pitch = w->screen_pitch; src_gfx_rect.height = 1; while (!w->dying) { if (w->connected && w->blitter) { clipping_rect *rect; uint32 i, j; acquire_sem(_be_window_lock); w->locker->Lock(); for (i=0; iscreen_height; i++) { if (_be_dirty_lines[i]) { rect = w->rects; for (j=0; jnum_rects; j++, rect++) if (((int32)i >= rect->top - w->window.top) && ((int32)i <= rect->bottom - w->window.top)) { src_gfx_rect.width = rect->right - rect->left + 1; src_gfx_rect.data = (void *)((unsigned long)w->screen_data + (i * w->screen_pitch) + ((rect->left - w->window.left) * BYTES_PER_PIXEL(w->screen_depth))); dest_gfx_rect.data = (void *)((unsigned long)w->display_data + (i * w->display_pitch) + (rect->left * BYTES_PER_PIXEL(w->display_depth))); dest_gfx_rect.pitch = w->display_pitch; w->blitter(&src_gfx_rect, &dest_gfx_rect); } _be_dirty_lines[i] = 0; } } w->locker->Unlock(); } snooze(BE_DRAWING_THREAD_PERIOD); } return B_OK; } /* BeAllegroDirectWindow::BeAllegroDirectWindow: * Constructor, creates program window and framebuffer, and starts * the drawing thread. */ BeAllegroDirectWindow::BeAllegroDirectWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspaces, uint32 v_w, uint32 v_h, uint32 color_depth) : BDirectWindow(frame, title, look, feel, flags, workspaces) { BRect rect = Bounds(); uint32 i; _be_allegro_view = new BeAllegroView(rect, "Allegro", B_FOLLOW_ALL_SIDES, B_WILL_DRAW, BE_ALLEGRO_VIEW_DIRECT); rgb_color color = {0, 0, 0, 0}; _be_allegro_view->SetViewColor(color); AddChild(_be_allegro_view); screen_pitch = v_w * BYTES_PER_PIXEL(color_depth); screen_data = malloc(v_h * screen_pitch); screen_depth = color_depth; display_depth = 0; num_rects = 0; rects = NULL; connected = false; dying = false; locker = new BLocker(); blitter = NULL; _be_dirty_lines = (int *)malloc(v_h * sizeof(int)); _be_window_lock = create_sem(0, "window lock"); drawing_thread_id = spawn_thread(_be_gfx_direct_window_drawing_thread, BE_DRAWING_THREAD_NAME, BE_DRAWING_THREAD_PRIORITY, (void *)this); resume_thread(drawing_thread_id); } /* BeAllegroDirectWindow::~BeAllegroDirectWindow: * Stops drawing thread and frees used memory. */ BeAllegroDirectWindow::~BeAllegroDirectWindow() { int32 result; dying = true; release_sem(_be_window_lock); locker->Unlock(); Sync(); wait_for_thread(drawing_thread_id, &result); drawing_thread_id = -1; Hide(); delete locker; delete_sem(_be_window_lock); _release_colorconv_blitter(blitter); blitter = NULL; connected = false; _be_focus_count = 0; if (rects) { free(rects); rects = NULL; } if (_be_dirty_lines) { free(_be_dirty_lines); _be_dirty_lines = NULL; } if (screen_data) { free(screen_data); screen_data = NULL; } } /* BeAllegroDirectWindow::MessageReceived: * System messages handler. */ void BeAllegroDirectWindow::MessageReceived(BMessage *message) { switch (message->what) { case B_SIMPLE_DATA: break; case B_MOUSE_WHEEL_CHANGED: float dy; message->FindFloat("be:wheel_delta_y", &dy); _be_mouse_z += ((int)dy > 0 ? -1 : 1); break; default: BDirectWindow::MessageReceived(message); break; } } /* BeAllegroDirectWindow::DirectConnected: * Callback for when there are changes the program window must deal * with; this includes first window exposure, system color depth * changes and visible window portions updates. */ void BeAllegroDirectWindow::DirectConnected(direct_buffer_info *info) { size_t size; char tmp[128]; if (dying) { return; } locker->Lock(); connected = false; switch (info->buffer_state & B_DIRECT_MODE_MASK) { case B_DIRECT_START: /* fallthrough */ case B_DIRECT_MODIFY: { uint8 old_display_depth = display_depth; uint32 i; switch (info->pixel_format) { case B_CMAP8: display_depth = 8; break; case B_RGB15: case B_RGBA15: display_depth = 15; break; case B_RGB16: display_depth = 16; break; case B_RGB32: case B_RGBA32: display_depth = 32; break; default: display_depth = 0; break; } if (!display_depth) { break; } if (old_display_depth != display_depth) { int i; _release_colorconv_blitter(blitter); blitter = _get_colorconv_blitter(screen_depth, display_depth); if (display_depth == 8) { cmap = _get_colorconv_map(); if (screen_depth == 8) { for (i=0; i<256; i++) cmap[i] = BScreen().IndexForColor(palette_colors[i]); } else { for (i=0; i<4096; i++) cmap[i] = BScreen().IndexForColor(((i >> 4) & 0xF0) | (i >> 8), (i & 0xF0) | ((i >> 4) & 0xF), (i & 0xF) | ((i & 0xF) << 4)); } } /* XXX commented out due to conflicting TRACE in Haiku TRACE(PREFIX_I "Color conversion mode set: %d->%d\n", (int)screen_depth, (int)display_depth); */ } if (rects) { free(rects); } num_rects = info->clip_list_count; size = num_rects * (sizeof *rects); rects = (clipping_rect *)malloc(num_rects * size); if (rects) { memcpy(rects, info->clip_list, size); } window = info->window_bounds; screen_height = window.bottom - window.top + 1; display_pitch = info->bytes_per_row; display_data = (void *)((unsigned long)info->bits + (window.top * display_pitch)); for (i=0; iUnlock(); } /* BeAllegroDirectWindow::WindowActivated: * Callback for when the window gains/looses focus. */ void BeAllegroDirectWindow::WindowActivated(bool active) { _be_change_focus(active); BDirectWindow::WindowActivated(active); } /* BeAllegroDirectWindow::QuitRequested: * User requested to close the program window. */ bool BeAllegroDirectWindow::QuitRequested(void) { return _be_handle_window_close(Title()); } /* _be_gfx_bdirectwindow_init: * Initializes specified video mode. */ static struct BITMAP *_be_gfx_bdirectwindow_init(GFX_DRIVER *drv, int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; int bpp; char tmp[128]; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR24 && (color_depth != 24) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((!v_w) && (!v_h)) { v_w = w; v_h = h; } if ((w != v_w) || (h != v_h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } set_display_switch_mode(SWITCH_PAUSE); _be_allegro_direct_window = new BeAllegroDirectWindow(BRect(0, 0, w-1, h-1), wnd_title, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_CURRENT_WORKSPACE, v_w, v_h, color_depth); _be_window = _be_allegro_direct_window; if (!_be_allegro_direct_window->SupportsWindowMode()) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Windowed mode not supported")); goto cleanup; } _be_mouse_view = new BView(_be_allegro_direct_window->Bounds(), "allegro mouse view", B_FOLLOW_ALL_SIDES, 0); _be_allegro_direct_window->Lock(); _be_allegro_direct_window->AddChild(_be_mouse_view); _be_allegro_direct_window->Unlock(); _be_mouse_window = _be_allegro_direct_window; _be_mouse_window_mode = true; release_sem(_be_mouse_view_attached); _be_gfx_initialized = false; _be_allegro_direct_window->MoveTo(6, 25); _be_allegro_direct_window->Show(); bpp = (color_depth + 7) / 8; drv->w = w; drv->h = h; drv->linear = TRUE; drv->vid_mem = bpp * v_w * v_h; bmp = _make_bitmap(v_w, v_h, (unsigned long)_be_allegro_direct_window->screen_data, drv, color_depth, v_w * bpp); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } #ifdef ALLEGRO_NO_ASM bmp->read_bank = (void *)_be_gfx_bwindow_read_write_bank; bmp->write_bank = (void *)_be_gfx_bwindow_read_write_bank; _screen_vtable.unwrite_bank = (void *)_be_gfx_bwindow_unwrite_bank; #else bmp->read_bank = _be_gfx_bwindow_read_write_bank_asm; bmp->write_bank = _be_gfx_bwindow_read_write_bank_asm; _screen_vtable.unwrite_bank = _be_gfx_bwindow_unwrite_bank_asm; #endif _screen_vtable.acquire = be_gfx_bdirectwindow_acquire; _screen_vtable.release = be_gfx_bdirectwindow_release; _be_gfx_set_truecolor_shifts(); /* Give time to connect the screen and do the first update */ snooze(50000); while (!_be_gfx_initialized); uszprintf(driver_desc, sizeof(driver_desc), get_config_text("BDirectWindow object, %d bit in %s"), _be_allegro_direct_window->screen_depth, uconvert_ascii(_be_allegro_direct_window->screen_depth == _be_allegro_direct_window->display_depth ? "matching" : "fast emulation", tmp)); drv->desc = driver_desc; return bmp; cleanup: { be_gfx_bdirectwindow_exit(NULL); return NULL; } } extern "C" struct BITMAP *be_gfx_bdirectwindow_init(int w, int h, int v_w, int v_h, int color_depth) { return _be_gfx_bdirectwindow_init(&gfx_beos_bdirectwindow, w, h, v_w, v_h, color_depth); } /* be_gfx_bdirectwindow_exit: * Shuts down driver. */ extern "C" void be_gfx_bdirectwindow_exit(struct BITMAP *bmp) { (void)bmp; _be_gfx_initialized = false; if (_be_allegro_direct_window) { if (_be_mouse_view_attached < 1) { acquire_sem(_be_mouse_view_attached); } _be_allegro_direct_window->Lock(); _be_allegro_direct_window->Quit(); _be_allegro_direct_window = NULL; _be_window = NULL; } _be_mouse_window = NULL; _be_mouse_view = NULL; } /* be_gfx_bdirectwindow_acquire: * Locks the screen bitmap. */ extern "C" void be_gfx_bdirectwindow_acquire(struct BITMAP *bmp) { if (!(bmp->id & BMP_ID_LOCKED)) { _be_allegro_direct_window->locker->Lock(); bmp->id |= BMP_ID_LOCKED; } } /* be_gfx_bdirectwindow_release: * Unlocks the screen bitmap. */ extern "C" void be_gfx_bdirectwindow_release(struct BITMAP *bmp) { if (bmp->id & BMP_ID_LOCKED) { bmp->id &= ~BMP_ID_LOCKED; _be_allegro_direct_window->locker->Unlock(); release_sem(_be_window_lock); } } /* be_gfx_bdirectwindow_set_palette: * Changes the internal palette and warns the drawing thread to * reflect the change. */ extern "C" void be_gfx_bdirectwindow_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { int i; if (!_be_allegro_direct_window->blitter) return; if (vsync) { be_gfx_vsync(); } _be_allegro_direct_window->locker->Lock(); _set_colorconv_palette(p, from, to); if ((_be_allegro_direct_window->display_depth == 8) && (_be_allegro_direct_window->screen_depth == 8)) { for (i=from; i<=to; i++) { palette_colors[i].red = _rgb_scale_6[p[i].r]; palette_colors[i].green = _rgb_scale_6[p[i].g]; palette_colors[i].blue = _rgb_scale_6[p[i].b]; } for (i=0; i<256; i++) cmap[i] = BScreen().IndexForColor(palette_colors[i]); } for (i=0; i<(int)_be_allegro_direct_window->screen_height; i++) _be_dirty_lines[i] = 1; release_sem(_be_window_lock); _be_allegro_direct_window->locker->Unlock(); } allegro-4.4.3.1/src/beos/bwindow.cpp0000664000175000017500000002545313437077643016205 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS BWindow/BBitmap windowed driver. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU #error something is wrong with the makefile #endif #define UPDATER_PERIOD 16000 static unsigned char cmap[256]; static char driver_desc[256] = EMPTY_STRING; /* window_updater: * Thread doing the dirty work: keeps updating dirty lines on the window. */ static int32 window_updater(void *data) { BeAllegroWindow *w = (BeAllegroWindow *)data; BRect bounds, update_rect; int line, start, end, h, i, j; unsigned char *src, *dest; bounds = w->Bounds(); h = (int)bounds.bottom + 1; update_rect.left = 0; update_rect.right = bounds.right; while (!w->dying) { acquire_sem(_be_window_lock); w->Lock(); line = 0; while (line < h) { while ((line < h) && (!_be_dirty_lines[line])) line++; if (line >= h) break; start = line; while ((line < h) && (_be_dirty_lines[line])) { _be_dirty_lines[line] = 0; line++; } update_rect.top = start; update_rect.bottom = line - 1; if (_be_allegro_window->screen_depth == 8) { src = (uint8 *)w->buffer->Bits() + (start * w->buffer->BytesPerRow()); dest = (uint8 *)w->aux_buffer->Bits() + (start * w->aux_buffer->BytesPerRow()); for (i=start; iscreen_width; j++) dest[j] = cmap[src[j]]; src += w->buffer->BytesPerRow(); dest += w->aux_buffer->BytesPerRow(); } _be_allegro_view->DrawBitmapAsync(w->aux_buffer, update_rect, update_rect); } else _be_allegro_view->DrawBitmapAsync(w->buffer, update_rect, update_rect); } _be_allegro_view->Sync(); w->Unlock(); snooze(UPDATER_PERIOD); } return B_OK; } /* be_gfx_bwindow_acquire: * Locks the screen bitmap. */ extern "C" void be_gfx_bwindow_acquire(struct BITMAP *bmp) { if (!(bmp->id & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; } } /* be_gfx_bwindow_release: * Unlocks the screen bitmap. */ extern "C" void be_gfx_bwindow_release(struct BITMAP *bmp) { if (bmp->id & BMP_ID_LOCKED) { bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); release_sem(_be_window_lock); } } #ifdef ALLEGRO_NO_ASM /* _be_gfx_bwindow_read_write_bank: * Returns new line and marks it as dirty. */ extern "C" uintptr_t _be_gfx_bwindow_read_write_bank(BITMAP *bmp, int line) { if (!bmp->id & BMP_ID_LOCKED) { bmp->id |= (BMP_ID_LOCKED | BMP_ID_AUTOLOCK); } _be_dirty_lines[bmp->y_ofs + line] = 1; return (unsigned long)(bmp->line[line]); } /* _be_gfx_bwindow_unwrite_bank: * If necessary, unlocks bitmap and makes the drawing thread * to update. */ extern "C" void _be_gfx_bwindow_unwrite_bank(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); release_sem(_be_window_lock); } } #endif /* BeAllegroWindow::BeAllegroWindow: * Constructor, creates the window and the BBitmap framebuffer, * and starts the drawing thread. */ BeAllegroWindow::BeAllegroWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspaces, uint32 v_w, uint32 v_h, uint32 color_depth) : BWindow(frame, title, look, feel, flags, workspaces) { BRect rect = Bounds(); uint32 i; color_space space = B_NO_COLOR_SPACE; _be_allegro_view = new BeAllegroView(rect, "Allegro", B_FOLLOW_ALL_SIDES, B_WILL_DRAW, 0); rgb_color color = {0, 0, 0, 0}; _be_allegro_view->SetViewColor(color); AddChild(_be_allegro_view); switch (color_depth) { case 8: space = B_CMAP8; break; case 15: space = B_RGB15; break; case 16: space = B_RGB16; break; case 32: space = B_RGB32; break; } buffer = new BBitmap(rect, space); if (color_depth == 8) aux_buffer = new BBitmap(rect, B_CMAP8); else aux_buffer = NULL; dying = false; screen_width = (int)rect.right + 1; screen_height = (int)rect.bottom + 1; screen_depth = color_depth; _be_dirty_lines = (int *)calloc(v_h, sizeof(int)); _be_window_lock = create_sem(0, "window lock"); drawing_thread_id = spawn_thread(window_updater, "window updater", B_REAL_TIME_DISPLAY_PRIORITY, (void *)this); resume_thread(drawing_thread_id); } /* BeAllegroWindow::~BeAllegroWindow: * Stops the drawing thread and frees used memory. */ BeAllegroWindow::~BeAllegroWindow() { int32 result; dying = true; delete_sem(_be_window_lock); Unlock(); wait_for_thread(drawing_thread_id, &result); drawing_thread_id = -1; Hide(); _be_focus_count = 0; if (buffer) delete buffer; buffer = NULL; if (aux_buffer) delete aux_buffer; aux_buffer = NULL; if (_be_dirty_lines) { free(_be_dirty_lines); _be_dirty_lines = NULL; } } /* BeAllegroWindow::MessageReceived: * System messages handler. */ void BeAllegroWindow::MessageReceived(BMessage *message) { switch (message->what) { case B_SIMPLE_DATA: break; case B_MOUSE_WHEEL_CHANGED: float dy; message->FindFloat("be:wheel_delta_y", &dy); _be_mouse_z += ((int)dy > 0 ? -1 : 1); break; default: BWindow::MessageReceived(message); break; } } /* BeAllegroWindow::WindowActivated: * Callback for when the window gains/looses focus. */ void BeAllegroWindow::WindowActivated(bool active) { _be_change_focus(active); if (active) { _be_allegro_window->Lock(); for (int i=0; i<_be_allegro_window->screen_height; i++) _be_dirty_lines[i] = 1; _be_allegro_window->Unlock(); release_sem(_be_window_lock); } BWindow::WindowActivated(active); } /* BeAllegroWindow::QuitRequested: * User requested to close the program window. */ bool BeAllegroWindow::QuitRequested(void) { return _be_handle_window_close(Title()); } /* be_gfx_bwindow_init: * Initializes specified video mode. */ extern "C" struct BITMAP *be_gfx_bwindow_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; if (1 #ifdef ALLEGRO_COLOR8 && (color_depth != 8) #endif #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((!v_w) && (!v_h)) { v_w = w; v_h = h; } if ((w != v_w) || (h != v_h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } set_display_switch_mode(SWITCH_PAUSE); _be_allegro_window = new BeAllegroWindow(BRect(0, 0, w-1, h-1), wnd_title, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_CURRENT_WORKSPACE, v_w, v_h, color_depth); _be_window = _be_allegro_window; if (!_be_allegro_window->buffer->IsValid() || ((color_depth == 8) && (!_be_allegro_window->aux_buffer->IsValid()))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } _be_mouse_view = new BView(_be_allegro_window->Bounds(), "allegro mouse view", B_FOLLOW_ALL_SIDES, 0); _be_allegro_window->Lock(); _be_allegro_window->AddChild(_be_mouse_view); _be_allegro_window->Unlock(); _be_mouse_window = _be_allegro_window; _be_mouse_window_mode = true; release_sem(_be_mouse_view_attached); _be_allegro_window->MoveTo(6, 25); _be_allegro_window->Show(); gfx_beos_bwindow.w = w; gfx_beos_bwindow.h = h; gfx_beos_bwindow.linear = TRUE; gfx_beos_bwindow.vid_mem = _be_allegro_window->buffer->BitsLength(); bmp = _make_bitmap(v_w, v_h, (unsigned long)_be_allegro_window->buffer->Bits(), &gfx_beos_bwindow, color_depth, _be_allegro_window->buffer->BytesPerRow()); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } #ifdef ALLEGRO_NO_ASM bmp->read_bank = (void *)_be_gfx_bwindow_read_write_bank; bmp->write_bank = (void *)_be_gfx_bwindow_read_write_bank; _screen_vtable.unwrite_bank = (void *)_be_gfx_bwindow_unwrite_bank; #else bmp->read_bank = _be_gfx_bwindow_read_write_bank_asm; bmp->write_bank = _be_gfx_bwindow_read_write_bank_asm; _screen_vtable.unwrite_bank = _be_gfx_bwindow_unwrite_bank_asm; #endif _screen_vtable.acquire = be_gfx_bwindow_acquire; _screen_vtable.release = be_gfx_bwindow_release; _be_gfx_set_truecolor_shifts(); uszprintf(driver_desc, sizeof(driver_desc), get_config_text("BWindow object, %d bit BBitmap framebuffer"), color_depth); gfx_beos_bwindow.desc = driver_desc; snooze(50000); _be_gfx_initialized = true; return bmp; cleanup: be_gfx_bwindow_exit(NULL); return NULL; } /* be_gfx_bwindow_exit: * Shuts down the driver. */ extern "C" void be_gfx_bwindow_exit(struct BITMAP *bmp) { _be_gfx_initialized = false; if (_be_allegro_window) { if (_be_mouse_view_attached < 1) { acquire_sem(_be_mouse_view_attached); } _be_allegro_window->Lock(); _be_allegro_window->Quit(); _be_allegro_window = NULL; _be_window = NULL; } _be_mouse_window = NULL; _be_mouse_view = NULL; } /* be_gfx_bwindow_set_palette: * Sets the internal color map to reflect the given palette, and * makes the drawing thread to update the window. */ extern "C" void be_gfx_bwindow_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync) { int i; if (vsync) be_gfx_vsync(); if (_be_allegro_window->screen_depth != 8) return; _be_allegro_window->Lock(); for (i=from; i<=to; i++) cmap[i] = BScreen().IndexForColor(p[i].r << 2, p[i].g << 2, p[i].b << 2); for (i=0; i<_be_allegro_window->screen_height; i++) _be_dirty_lines[i] = 1; _be_allegro_window->Unlock(); release_sem(_be_window_lock); } allegro-4.4.3.1/src/midi.c0000664000175000017500000012225313437077643014162 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The core MIDI file player. * * By Shawn Hargreaves. * * Pause and seek functions by George Foot. * * get_midi_length by Elias Pschernig. * * See readme.txt for copyright information. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" /* maximum number of layers in a single voice */ #define MIDI_LAYERS 4 /* how often the midi callback gets called maximally / second */ #define MIDI_TIMER_FREQUENCY 40 typedef struct MIDI_TRACK /* a track in the MIDI file */ { unsigned char *pos; /* position in track data */ long timer; /* time until next event */ unsigned char running_status; /* last MIDI event */ } MIDI_TRACK; typedef struct MIDI_CHANNEL /* a MIDI channel */ { int patch; /* current sound */ int volume; /* volume controller */ int pan; /* pan position */ int pitch_bend; /* pitch bend position */ int new_volume; /* cached volume change */ int new_pitch_bend; /* cached pitch bend */ int note[128][MIDI_LAYERS]; /* status of each note */ } MIDI_CHANNEL; typedef struct MIDI_VOICE /* a voice on the soundcard */ { int channel; /* MIDI channel */ int note; /* note (-1 = off) */ int volume; /* note velocity */ long time; /* when note was triggered */ } MIDI_VOICE; typedef struct WAITING_NOTE /* a stored note-on request */ { int channel; int note; int volume; } WAITING_NOTE; typedef struct PATCH_TABLE /* GM -> external synth */ { int bank1; /* controller #0 */ int bank2; /* controller #32 */ int prog; /* program change */ int pitch; /* pitch shift */ } PATCH_TABLE; volatile long midi_pos = -1; /* current position in MIDI file */ volatile long midi_time = 0; /* current position in seconds */ static volatile long midi_timers; /* current position in allegro-timer-ticks */ static long midi_pos_counter; /* delta for midi_pos */ volatile long _midi_tick = 0; /* counter for killing notes */ static void midi_player(void); /* core MIDI player routine */ static void prepare_to_play(MIDI *midi); static void midi_lock_mem(void); static MIDI *midifile = NULL; /* the file that is playing */ static int midi_loop = 0; /* repeat at eof? */ long midi_loop_start = -1; /* where to loop back to */ long midi_loop_end = -1; /* loop at this position */ static int midi_semaphore = 0; /* reentrancy flag */ static int midi_loaded_patches = FALSE; /* loaded entire patch set? */ static long midi_timer_speed; /* midi_player's timer speed */ static int midi_pos_speed; /* MIDI delta -> midi_pos */ static int midi_speed; /* MIDI delta -> timer */ static int midi_new_speed; /* for tempo change events */ static int old_midi_volume = -1; /* stored global volume */ static int midi_alloc_channel; /* so _midi_allocate_voice */ static int midi_alloc_note; /* knows which note the */ static int midi_alloc_vol; /* sound is associated with */ static MIDI_TRACK midi_track[MIDI_TRACKS]; /* the active tracks */ static MIDI_VOICE midi_voice[MIDI_VOICES]; /* synth voice status */ static MIDI_CHANNEL midi_channel[16]; /* MIDI channel info */ static WAITING_NOTE midi_waiting[MIDI_VOICES]; /* notes still to be played */ static PATCH_TABLE patch_table[128]; /* GM -> external synth */ static int midi_seeking; /* set during seeks */ static int midi_looping; /* set during loops */ /* hook functions */ void (*midi_msg_callback)(int msg, int byte1, int byte2) = NULL; void (*midi_meta_callback)(int type, AL_CONST unsigned char *data, int length) = NULL; void (*midi_sysex_callback)(AL_CONST unsigned char *data, int length) = NULL; /* lock_midi: * Locks a MIDI file into physical memory. Pretty important, since they * are mostly accessed inside interrupt handlers. */ void lock_midi(MIDI *midi) { int c; ASSERT(midi); LOCK_DATA(midi, sizeof(MIDI)); for (c=0; ctrack[c].data) { LOCK_DATA(midi->track[c].data, midi->track[c].len); } } } /* load_midi: * Loads a standard MIDI file, returning a pointer to a MIDI structure, * or NULL on error. */ MIDI *load_midi(AL_CONST char *filename) { PACKFILE *f; MIDI *midi; ASSERT(filename); f = pack_fopen(filename, F_READ); if (!f) return NULL; midi = load_midi_pf(f); pack_fclose(f); return midi; } /* load_midi_pf: * Reads a standard MIDI file from the packfile given, returning a MIDI * structure, or NULL on error. * * If unsuccessful the offset into the file is unspecified, i.e. you must * either reset the offset to some known place or close the packfile. The * packfile is not closed by this function. */ MIDI *load_midi_pf(PACKFILE *fp) { int c; char buf[4]; long data; MIDI *midi; int num_tracks; ASSERT(fp); midi = _AL_MALLOC(sizeof(MIDI)); /* get some memory */ if (!midi) return NULL; for (c=0; ctrack[c].data = NULL; midi->track[c].len = 0; } pack_fread(buf, 4, fp); /* read midi header */ /* Is the midi inside a .rmi file? */ if (memcmp(buf, "RIFF", 4) == 0) { /* check for RIFF header */ pack_mgetl(fp); while (!pack_feof(fp)) { pack_fread(buf, 4, fp); /* RMID chunk? */ if (memcmp(buf, "RMID", 4) == 0) break; pack_fseek(fp, pack_igetl(fp)); /* skip to next chunk */ } if (pack_feof(fp)) goto err; pack_mgetl(fp); pack_mgetl(fp); pack_fread(buf, 4, fp); /* read midi header */ } if (memcmp(buf, "MThd", 4)) goto err; pack_mgetl(fp); /* skip header chunk length */ data = pack_mgetw(fp); /* MIDI file type */ if ((data != 0) && (data != 1)) goto err; num_tracks = pack_mgetw(fp); /* number of tracks */ if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS)) goto err; data = pack_mgetw(fp); /* beat divisions */ midi->divisions = ABS(data); for (c=0; ctrack[c].len = data; midi->track[c].data = _AL_MALLOC_ATOMIC(data); /* allocate memory */ if (!midi->track[c].data) goto err; /* finally, read track data */ if (pack_fread(midi->track[c].data, data, fp) != data) goto err; } lock_midi(midi); return midi; /* oh dear... */ err: destroy_midi(midi); return NULL; } /* destroy_midi: * Frees the memory being used by a MIDI file. */ void destroy_midi(MIDI *midi) { int c; if (midi == midifile) stop_midi(); if (midi) { for (c=0; ctrack[c].data) { UNLOCK_DATA(midi->track[c].data, midi->track[c].len); _AL_FREE(midi->track[c].data); } } UNLOCK_DATA(midi, sizeof(MIDI)); _AL_FREE(midi); } } /* parse_var_len: * The MIDI file format is a strange thing. Time offsets are only 32 bits, * yet they are compressed in a weird variable length format. This routine * reads a variable length integer from a MIDI data stream. It returns the * number read, and alters the data pointer according to the number of * bytes it used. */ static unsigned long parse_var_len(AL_CONST unsigned char **data) { unsigned long val = **data & 0x7F; while (**data & 0x80) { (*data)++; val <<= 7; val += (**data & 0x7F); } (*data)++; return val; } END_OF_STATIC_FUNCTION(parse_var_len); /* global_volume_fix: * Converts a note volume, adjusting it according to the global * _midi_volume variable. */ static INLINE int global_volume_fix(int vol) { if (_midi_volume >= 0) return (vol * _midi_volume) / 256; return vol; } /* sort_out_volume: * Converts a note volume, adjusting it according to the channel volume * and the global _midi_volume variable. */ static INLINE int sort_out_volume(int c, int vol) { return global_volume_fix((vol * midi_channel[c].volume) / 128); } /* raw_program_change: * Sends a program change message to a device capable of handling raw * MIDI data, using patch mapping tables. Assumes that midi_driver->raw_midi * isn't NULL, so check before calling it! */ static void raw_program_change(int channel, int patch) { if (channel != 9) { /* bank change #1 */ if (patch_table[patch].bank1 >= 0) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(0); midi_driver->raw_midi(patch_table[patch].bank1); } /* bank change #2 */ if (patch_table[patch].bank2 >= 0) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(32); midi_driver->raw_midi(patch_table[patch].bank2); } /* program change */ midi_driver->raw_midi(0xC0+channel); midi_driver->raw_midi(patch_table[patch].prog); /* update volume */ midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(7); midi_driver->raw_midi(global_volume_fix(midi_channel[channel].volume-1)); } } END_OF_STATIC_FUNCTION(raw_program_change); /* midi_note_off: * Processes a MIDI note-off event. */ static void midi_note_off(int channel, int note) { int done = FALSE; int voice, layer; int c; /* can we send raw MIDI data? */ if (midi_driver->raw_midi) { if (channel != 9) note += patch_table[midi_channel[channel].patch].pitch; midi_driver->raw_midi(0x80+channel); midi_driver->raw_midi(note); midi_driver->raw_midi(0); return; } /* oh well, have to do it the long way... */ for (layer=0; layer= 0) { midi_driver->key_off(voice + midi_driver->basevoice); midi_voice[voice].note = -1; midi_voice[voice].time = _midi_tick; midi_channel[channel].note[note][layer] = -1; done = TRUE; } } /* if the note isn't playing, it must still be in the waiting room */ if (!done) { for (c=0; c= 0x1000) { (*note)++; (*bend) -= 0x1000; } } /* _midi_allocate_voice: * Allocates a MIDI voice in the range min-max (inclusive). This is * intended to be called by the key_on() handlers in the MIDI driver, * and shouldn't be used by any other code. */ int _midi_allocate_voice(int min, int max) { int c; int layer; int voice = -1; long best_time = LONG_MAX; if (min < 0) min = 0; if (max < 0) max = midi_driver->voices-1; /* which layer can we use? */ for (layer=0; layer= MIDI_LAYERS) return -1; /* find a free voice */ for (c=min; c<=max; c++) { if ((midi_voice[c].note < 0) && (midi_voice[c].time < best_time) && ((c < midi_driver->xmin) || (c > midi_driver->xmax))) { voice = c; best_time = midi_voice[c].time; } } /* if there are no free voices, kill a note to make room */ if (voice < 0) { voice = -1; best_time = LONG_MAX; for (c=min; c<=max; c++) { if ((midi_voice[c].time < best_time) && ((c < midi_driver->xmin) || (c > midi_driver->xmax))) { voice = c; best_time = midi_voice[c].time; } } if (voice >= 0) midi_note_off(midi_voice[voice].channel, midi_voice[voice].note); else return -1; } /* ok, we got it... */ midi_voice[voice].channel = midi_alloc_channel; midi_voice[voice].note = midi_alloc_note; midi_voice[voice].volume = midi_alloc_vol; midi_voice[voice].time = _midi_tick; midi_channel[midi_alloc_channel].note[midi_alloc_note][layer] = voice; return voice + midi_driver->basevoice; } END_OF_FUNCTION(_midi_allocate_voice); /* midi_note_on: * Processes a MIDI note-on event. Tries to find a free soundcard voice, * and if it can't either cuts off an existing note, or if 'polite' is * set, just stores the channel, note and volume in the waiting list. */ static void midi_note_on(int channel, int note, int vol, int polite) { int c, layer, inst, bend, corrected_note; /* it's easy if the driver can handle raw MIDI data */ if (midi_driver->raw_midi) { if (channel != 9) note += patch_table[midi_channel[channel].patch].pitch; midi_driver->raw_midi(0x90+channel); midi_driver->raw_midi(note); midi_driver->raw_midi(vol); return; } /* if the note is already on, turn it off */ for (layer=0; layer= 0) { midi_note_off(channel, note); return; } } /* if zero volume and the note isn't playing, we can just ignore it */ if (vol == 0) return; if (channel != 9) { /* are there any free voices? */ for (c=0; cvoices; c++) if ((midi_voice[c].note < 0) && ((c < midi_driver->xmin) || (c > midi_driver->xmax))) break; /* if there are no free voices, remember the note for later */ if ((c >= midi_driver->voices) && (polite)) { for (c=0; ckey_on(inst, corrected_note, bend, sort_out_volume(channel, vol), midi_channel[channel].pan); } END_OF_STATIC_FUNCTION(midi_note_on); /* all_notes_off: * Turns off all active notes. */ static void all_notes_off(int channel) { if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(123); midi_driver->raw_midi(0); return; } else { int note, layer; for (note=0; note<128; note++) for (layer=0; layer= 0) midi_note_off(channel, note); } } END_OF_STATIC_FUNCTION(all_notes_off); /* all_sound_off: * Turns off sound. */ static void all_sound_off(int channel) { if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(120); midi_driver->raw_midi(0); return; } } END_OF_STATIC_FUNCTION(all_sound_off); /* reset_controllers: * Resets volume, pan, pitch bend, etc, to default positions. */ static void reset_controllers(int channel) { midi_channel[channel].new_volume = 128; midi_channel[channel].new_pitch_bend = 0x2000; if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(121); midi_driver->raw_midi(0); } switch (channel % 3) { case 0: midi_channel[channel].pan = ((channel/3) & 1) ? 60 : 68; break; case 1: midi_channel[channel].pan = 104; break; case 2: midi_channel[channel].pan = 24; break; } if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(10); midi_driver->raw_midi(midi_channel[channel].pan); } } END_OF_STATIC_FUNCTION(reset_controllers); /* update_controllers: * Checks cached controller information and updates active voices. */ static void update_controllers(void) { int c, c2, vol, bend, note; for (c=0; c<16; c++) { /* check for volume controller change */ if ((midi_channel[c].volume != midi_channel[c].new_volume) || (old_midi_volume != _midi_volume)) { midi_channel[c].volume = midi_channel[c].new_volume; if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+c); midi_driver->raw_midi(7); midi_driver->raw_midi(global_volume_fix(midi_channel[c].volume-1)); } else { for (c2=0; c2= 0)) { vol = sort_out_volume(c, midi_voice[c2].volume); midi_driver->set_volume(c2 + midi_driver->basevoice, vol); } } } } /* check for pitch bend change */ if (midi_channel[c].pitch_bend != midi_channel[c].new_pitch_bend) { midi_channel[c].pitch_bend = midi_channel[c].new_pitch_bend; if (midi_driver->raw_midi) { midi_driver->raw_midi(0xE0+c); midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F); midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7); } else { for (c2=0; c2= 0)) { bend = midi_channel[c].pitch_bend; note = midi_voice[c2].note; sort_out_pitch_bend(&bend, ¬e); midi_driver->set_pitch(c2 + midi_driver->basevoice, note, bend); } } } } } old_midi_volume = _midi_volume; } END_OF_STATIC_FUNCTION(update_controllers); /* process_controller: * Deals with a MIDI controller message on the specified channel. */ static void process_controller(int channel, int ctrl, int data) { switch (ctrl) { case 7: /* main volume */ midi_channel[channel].new_volume = data+1; break; case 10: /* pan */ midi_channel[channel].pan = data; if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(10); midi_driver->raw_midi(data); } break; case 120: /* all sound off */ all_sound_off(channel); break; case 121: /* reset all controllers */ reset_controllers(channel); break; case 123: /* all notes off */ case 124: /* omni mode off */ case 125: /* omni mode on */ case 126: /* poly mode off */ case 127: /* poly mode on */ all_notes_off(channel); break; default: if (midi_driver->raw_midi) { midi_driver->raw_midi(0xB0+channel); midi_driver->raw_midi(ctrl); midi_driver->raw_midi(data); } break; } } END_OF_STATIC_FUNCTION(process_controller); /* process_meta_event: * Processes the next meta-event on the specified track. */ static void process_meta_event(AL_CONST unsigned char **pos, long *timer) { unsigned char metatype = *((*pos)++); long length = parse_var_len(pos); long tempo; if (midi_meta_callback) midi_meta_callback(metatype, *pos, length); if (metatype == 0x2F) { /* end of track */ *pos = NULL; *timer = LONG_MAX; return; } if (metatype == 0x51) { /* tempo change */ tempo = (*pos)[0] * 0x10000L + (*pos)[1] * 0x100 + (*pos)[2]; midi_new_speed = (tempo/1000) * (TIMERS_PER_SECOND/1000); midi_new_speed /= midifile->divisions; } (*pos) += length; } END_OF_STATIC_FUNCTION(process_meta_event); /* process_midi_event: * Processes the next MIDI event on the specified track. */ static void process_midi_event(AL_CONST unsigned char **pos, unsigned char *running_status, long *timer) { unsigned char byte1, byte2; int channel; unsigned char event; long l; event = *((*pos)++); if (event & 0x80) { /* regular message */ /* no running status for sysex and meta-events! */ if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF)) *running_status = event; byte1 = (*pos)[0]; byte2 = (*pos)[1]; } else { /* use running status */ byte1 = event; byte2 = (*pos)[0]; event = *running_status; (*pos)--; } /* program callback? */ if ((midi_msg_callback) && (event != 0xF0) && (event != 0xF7) && (event != 0xFF)) midi_msg_callback(event, byte1, byte2); channel = event & 0x0F; switch (event>>4) { case 0x08: /* note off */ midi_note_off(channel, byte1); (*pos) += 2; break; case 0x09: /* note on */ midi_note_on(channel, byte1, byte2, 1); (*pos) += 2; break; case 0x0A: /* note aftertouch */ (*pos) += 2; break; case 0x0B: /* control change */ process_controller(channel, byte1, byte2); (*pos) += 2; break; case 0x0C: /* program change */ midi_channel[channel].patch = byte1; if (midi_driver->raw_midi) raw_program_change(channel, byte1); (*pos) += 1; break; case 0x0D: /* channel aftertouch */ (*pos) += 1; break; case 0x0E: /* pitch bend */ midi_channel[channel].new_pitch_bend = byte1 + (byte2<<7); (*pos) += 2; break; case 0x0F: /* special event */ switch (event) { case 0xF0: /* sysex */ case 0xF7: l = parse_var_len(pos); if (midi_sysex_callback) midi_sysex_callback(*pos, l); (*pos) += l; break; case 0xF2: /* song position */ (*pos) += 2; break; case 0xF3: /* song select */ (*pos)++; break; case 0xFF: /* meta-event */ process_meta_event(pos, timer); break; default: /* the other special events don't have any data bytes, so we don't need to bother skipping past them */ break; } break; default: /* something has gone badly wrong if we ever get to here */ break; } } END_OF_STATIC_FUNCTION(process_midi_event); /* midi_player: * The core MIDI player: to be used as a timer callback. */ static void midi_player(void) { int c; long l; int active; if (!midifile) return; if (midi_semaphore) { midi_timer_speed += BPS_TO_TIMER(MIDI_TIMER_FREQUENCY); install_int_ex(midi_player, BPS_TO_TIMER(MIDI_TIMER_FREQUENCY)); return; } midi_semaphore = TRUE; _midi_tick++; midi_timers += midi_timer_speed; midi_time = midi_timers / TIMERS_PER_SECOND; do_it_all_again: for (c=0; c 0) { for (c=0; cdivisions; midi_new_speed = -1; } /* figure out how long until we need to be called again */ active = 0; midi_timer_speed = LONG_MAX; for (c=0; c 0) && (midi_pos >= midi_loop_end))) { if ((midi_loop) && (!midi_looping)) { if (midi_loop_start > 0) { remove_int(midi_player); midi_semaphore = FALSE; midi_looping = TRUE; if (midi_seek(midi_loop_start) != 0) { midi_looping = FALSE; stop_midi(); return; } midi_looping = FALSE; midi_semaphore = TRUE; goto do_it_all_again; } else { for (c=0; c<16; c++) { all_notes_off(c); all_sound_off(c); } prepare_to_play(midifile); goto do_it_all_again; } } else { stop_midi(); midi_semaphore = FALSE; return; } } /* reprogram the timer */ if (midi_timer_speed < BPS_TO_TIMER(MIDI_TIMER_FREQUENCY)) midi_timer_speed = BPS_TO_TIMER(MIDI_TIMER_FREQUENCY); if (!midi_seeking) install_int_ex(midi_player, midi_timer_speed); /* controller changes are cached and only processed here, so we can condense streams of controller data into just a few voice updates */ update_controllers(); /* and deal with any notes that are still waiting to be played */ for (c=0; c= 0) midi_note_on(midi_waiting[c].channel, midi_waiting[c].note, midi_waiting[c].volume, 0); midi_semaphore = FALSE; } END_OF_STATIC_FUNCTION(midi_player); /* midi_init: * Sets up the MIDI player ready for use. Returns non-zero on failure. */ static int midi_init(void) { int c, c2, c3; char **argv; int argc; char buf[32], tmp[64]; midi_loaded_patches = FALSE; midi_lock_mem(); for (c=0; c<16; c++) { midi_channel[c].volume = midi_channel[c].new_volume = 128; midi_channel[c].pitch_bend = midi_channel[c].new_pitch_bend = 0x2000; for (c2=0; c2<128; c2++) for (c3=0; c3track[c].data; end = p + midi->track[c].len; running_status = 0; while (p < end) { /* work through data stream */ #if defined ALLEGRO_BEOS || defined ALLEGRO_HAIKU /* Is there a bug in this routine, or in gcc under BeOS/x86? --PW */ { int i; for (i=1; i; i--); } #endif event = *p; if (event & 0x80) { /* regular message */ p++; if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF)) running_status = event; } else /* use running status */ event = running_status; switch (event>>4) { case 0x0C: /* program change! */ patches[*p] = TRUE; p++; break; case 0x09: /* note on, is it a drum? */ if ((event & 0x0F) == 9) drums[*p] = TRUE; p += 2; break; case 0x08: /* note off */ case 0x0A: /* note aftertouch */ case 0x0B: /* control change */ case 0x0E: /* pitch bend */ p += 2; break; case 0x0D: /* channel aftertouch */ p += 1; break; case 0x0F: /* special event */ switch (event) { case 0xF0: /* sysex */ case 0xF7: l = parse_var_len((AL_CONST unsigned char**) &p); p += l; break; case 0xF2: /* song position */ p += 2; break; case 0xF3: /* song select */ p++; break; case 0xFF: /* meta-event */ p++; l = parse_var_len((AL_CONST unsigned char**) &p); p += l; break; default: /* the other special events don't have any data bytes, so we don't need to bother skipping past them */ break; } break; default: /* something has gone badly wrong if we ever get to here */ break; } if (p < end) /* skip time offset */ parse_var_len((AL_CONST unsigned char**) &p); } } /* tell the driver to do its stuff */ return midi_driver->load_patches(patches, drums); } /* prepare_to_play: * Sets up all the global variables needed to play the specified file. */ static void prepare_to_play(MIDI *midi) { int c; ASSERT(midi); for (c=0; c<16; c++) reset_controllers(c); update_controllers(); midifile = midi; midi_pos = 0; midi_timers = 0; midi_time = 0; midi_pos_counter = 0; midi_speed = TIMERS_PER_SECOND / 2 / midifile->divisions; /* 120 bpm */ midi_new_speed = -1; midi_pos_speed = midi_speed * midifile->divisions; midi_timer_speed = 0; midi_seeking = 0; midi_looping = 0; for (c=0; c<16; c++) { midi_channel[c].patch = 0; if (midi_driver->raw_midi) raw_program_change(c, 0); } for (c=0; ctrack[c].data) { midi_track[c].pos = midi->track[c].data; midi_track[c].timer = parse_var_len((AL_CONST unsigned char**) &midi_track[c].pos); midi_track[c].timer *= midi_speed; } else { midi_track[c].pos = NULL; midi_track[c].timer = LONG_MAX; } midi_track[c].running_status = 0; } } END_OF_STATIC_FUNCTION(prepare_to_play); /* play_midi: * Starts playing the specified MIDI file. If loop is set, the MIDI file * will be repeated until replaced with something else, otherwise it will * stop at the end of the file. Passing a NULL MIDI file will stop whatever * music is currently playing: allegro.h defines the macro stop_midi() to * be play_midi(NULL, FALSE); Returns non-zero if an error occurs (this * may happen if a patch-caching wavetable driver is unable to load the * required samples). */ int play_midi(MIDI *midi, int loop) { int c; remove_int(midi_player); for (c=0; c<16; c++) { all_notes_off(c); all_sound_off(c); } if (midi) { if (!midi_loaded_patches) if (load_patches(midi) != 0) return -1; midi_loop = loop; midi_loop_start = -1; midi_loop_end = -1; prepare_to_play(midi); /* arbitrary speed, midi_player() will adjust it */ install_int(midi_player, 20); } else { midifile = NULL; if (midi_pos > 0) midi_pos = -midi_pos; else if (midi_pos == 0) midi_pos = -1; } return 0; } END_OF_FUNCTION(play_midi); /* play_looped_midi: * Like play_midi(), but the file loops from the specified end position * back to the specified start position (the end position can be -1 to * indicate the end of the file). */ int play_looped_midi(MIDI *midi, int loop_start, int loop_end) { if (play_midi(midi, TRUE) != 0) return -1; midi_loop_start = loop_start; midi_loop_end = loop_end; return 0; } /* stop_midi: * Stops whatever MIDI file is currently playing. */ void stop_midi(void) { play_midi(NULL, FALSE); } END_OF_FUNCTION(stop_midi); /* midi_pause: * Pauses the currently playing MIDI file. */ void midi_pause(void) { int c; if (!midifile) return; remove_int(midi_player); for (c=0; c<16; c++) { all_notes_off(c); all_sound_off(c); } } END_OF_FUNCTION(midi_pause); /* midi_resume: * Resumes playing a paused MIDI file. */ void midi_resume(void) { if (!midifile) return; install_int_ex(midi_player, midi_timer_speed); } END_OF_FUNCTION(midi_resume); /* midi_seek: * Seeks to the given midi_pos in the current MIDI file. If the target * is earlier in the file than the current midi_pos it seeks from the * beginning; otherwise it seeks from the current position. Returns zero * if successful, non-zero if it hit the end of the file (1 means it * stopped playing, 2 means it looped back to the start). */ int midi_seek(int target) { int old_midi_loop; MIDI *old_midifile; MIDI_DRIVER *old_driver; int old_patch[16]; int old_volume[16]; int old_pan[16]; int old_pitch_bend[16]; int c; if (!midifile) return -1; /* first stop the player */ midi_pause(); /* store current settings */ for (c=0; c<16; c++) { old_patch[c] = midi_channel[c].patch; old_volume[c] = midi_channel[c].volume; old_pan[c] = midi_channel[c].pan; old_pitch_bend[c] = midi_channel[c].pitch_bend; } /* save some variables and give temporary values */ old_driver = midi_driver; midi_driver = &_midi_none; old_midi_loop = midi_loop; midi_loop = 0; old_midifile = midifile; /* set flag to tell midi_player not to reinstall itself */ midi_seeking = 1; /* are we seeking backwards? If so, skip back to the start of the file */ if (target <= midi_pos) prepare_to_play(midifile); /* now sit back and let midi_player get to the position */ while ((midi_pos < target) && (midi_pos >= 0)) { int mmpc = midi_pos_counter; int mmp = midi_pos; mmpc -= midi_timer_speed; while (mmpc <= 0) { mmpc += midi_pos_speed; mmp++; } if (mmp >= target) break; midi_player(); } /* restore previously saved variables */ midi_loop = old_midi_loop; midi_driver = old_driver; midi_seeking = 0; if (midi_pos >= 0) { /* refresh the driver with any changed parameters */ if (midi_driver->raw_midi) { for (c=0; c<16; c++) { /* program change (this sets the volume as well) */ if ((midi_channel[c].patch != old_patch[c]) || (midi_channel[c].volume != old_volume[c])) raw_program_change(c, midi_channel[c].patch); /* pan */ if (midi_channel[c].pan != old_pan[c]) { midi_driver->raw_midi(0xB0+c); midi_driver->raw_midi(10); midi_driver->raw_midi(midi_channel[c].pan); } /* pitch bend */ if (midi_channel[c].pitch_bend != old_pitch_bend[c]) { midi_driver->raw_midi(0xE0+c); midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F); midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7); } } } /* if we didn't hit the end of the file, continue playing */ if (!midi_looping) install_int(midi_player, 20); return 0; } if ((midi_loop) && (!midi_looping)) { /* was file looped? */ prepare_to_play(old_midifile); install_int(midi_player, 20); return 2; /* seek past EOF => file restarted */ } return 1; /* seek past EOF => file stopped */ } END_OF_FUNCTION(midi_seek); /* get_midi_length: * Returns the length, in seconds, of the specified midi. This will stop any * currently playing midi. Don't call it too often, since it simulates playing * all of the midi to get the time even if the midi contains tempo changes. */ int get_midi_length(MIDI *midi) { play_midi(midi, 0); while (midi_pos < 0); /* Without this, midi_seek won't work. */ midi_seek(INT_MAX); return midi_time; } /* midi_out: * Inserts MIDI command bytes into the output stream, in realtime. */ void midi_out(unsigned char *data, int length) { unsigned char *pos = data; unsigned char running_status = 0; long timer = 0; ASSERT(data); midi_semaphore = TRUE; _midi_tick++; while (pos < data+length) process_midi_event((AL_CONST unsigned char**) &pos, &running_status, &timer); update_controllers(); midi_semaphore = FALSE; } /* load_midi_patches: * Tells the MIDI driver to preload the entire sample set. */ int load_midi_patches(void) { char patches[128], drums[128]; int c, ret; for (c=0; c<128; c++) patches[c] = drums[c] = TRUE; midi_semaphore = TRUE; ret = midi_driver->load_patches(patches, drums); midi_semaphore = FALSE; midi_loaded_patches = TRUE; return ret; } /* midi_lock_mem: * Locks all the memory that the midi player touches inside the timer * interrupt handler (which is most of it). */ static void midi_lock_mem(void) { LOCK_VARIABLE(midi_pos); LOCK_VARIABLE(midi_time); LOCK_VARIABLE(midi_timers); LOCK_VARIABLE(midi_pos_counter); LOCK_VARIABLE(_midi_tick); LOCK_VARIABLE(midifile); LOCK_VARIABLE(midi_semaphore); LOCK_VARIABLE(midi_loop); LOCK_VARIABLE(midi_loop_start); LOCK_VARIABLE(midi_loop_end); LOCK_VARIABLE(midi_timer_speed); LOCK_VARIABLE(midi_pos_speed); LOCK_VARIABLE(midi_speed); LOCK_VARIABLE(midi_new_speed); LOCK_VARIABLE(old_midi_volume); LOCK_VARIABLE(midi_alloc_channel); LOCK_VARIABLE(midi_alloc_note); LOCK_VARIABLE(midi_alloc_vol); LOCK_VARIABLE(midi_track); LOCK_VARIABLE(midi_voice); LOCK_VARIABLE(midi_channel); LOCK_VARIABLE(midi_waiting); LOCK_VARIABLE(patch_table); LOCK_VARIABLE(midi_msg_callback); LOCK_VARIABLE(midi_meta_callback); LOCK_VARIABLE(midi_sysex_callback); LOCK_VARIABLE(midi_seeking); LOCK_VARIABLE(midi_looping); LOCK_FUNCTION(parse_var_len); LOCK_FUNCTION(raw_program_change); LOCK_FUNCTION(midi_note_off); LOCK_FUNCTION(_midi_allocate_voice); LOCK_FUNCTION(midi_note_on); LOCK_FUNCTION(all_notes_off); LOCK_FUNCTION(all_sound_off); LOCK_FUNCTION(reset_controllers); LOCK_FUNCTION(update_controllers); LOCK_FUNCTION(process_controller); LOCK_FUNCTION(process_meta_event); LOCK_FUNCTION(process_midi_event); LOCK_FUNCTION(midi_player); LOCK_FUNCTION(prepare_to_play); LOCK_FUNCTION(play_midi); LOCK_FUNCTION(stop_midi); LOCK_FUNCTION(midi_pause); LOCK_FUNCTION(midi_resume); LOCK_FUNCTION(midi_seek); } /* midi_constructor: * Register my functions with the code in sound.c. */ #ifdef ALLEGRO_USE_CONSTRUCTOR CONSTRUCTOR_FUNCTION(void _midi_constructor(void)); #endif static struct _AL_LINKER_MIDI midi_linker = { midi_init, midi_exit }; void _midi_constructor(void) { _al_linker_midi = &midi_linker; } allegro-4.4.3.1/src/gui.c0000664000175000017500000017032713437077643014031 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The core GUI routines. * * By Shawn Hargreaves. * * Peter Pavlovic modified the drawing and positioning of menus. * * Menu auto-opening added by Angelo Mottola. * * Eric Botcazou added the support for non-blocking menus. * * Elias Pschernig and Sven Sandberg improved the focus algorithm. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* if set, the input focus follows the mouse pointer */ int gui_mouse_focus = TRUE; /* font alignment value */ int gui_font_baseline = 0; /* Pointers to the currently active dialog and menu objects. * * Note: active_dialog_player always points to the currently active dialog * player. However, active_menu_player only ever points to menu players * started by a d_menu_proc. The code also assumes that that d_menu_proc can * be found in the currently active dialog. * * Note: active_dialog points to the whole dialog currently running. However, * active_menu points to the *current item* of the currently running menu, * and should really have been called active_menu_item. */ static DIALOG_PLAYER *active_dialog_player = NULL; static MENU_PLAYER *active_menu_player = NULL; static int active_menu_player_zombie = FALSE; DIALOG *active_dialog = NULL; MENU *active_menu = NULL; static BITMAP *gui_screen = NULL; /* list of currently active (initialized) dialog players */ struct al_active_dialog_player { DIALOG_PLAYER *player; struct al_active_dialog_player *next; }; static struct al_active_dialog_player *first_active_dialog_player = 0; static struct al_active_dialog_player *current_active_dialog_player = 0; /* forward declarations */ static int shutdown_single_menu(MENU_PLAYER *, int *); /* hook function for reading the mouse x position */ static int default_mouse_x(void) { if (mouse_needs_poll()) poll_mouse(); return mouse_x; } END_OF_STATIC_FUNCTION(default_mouse_x); /* hook function for reading the mouse y position */ static int default_mouse_y(void) { if (mouse_needs_poll()) poll_mouse(); return mouse_y; } END_OF_STATIC_FUNCTION(default_mouse_y); /* hook function for reading the mouse z position */ static int default_mouse_z(void) { if (mouse_needs_poll()) poll_mouse(); return mouse_z; } END_OF_STATIC_FUNCTION(default_mouse_z); /* hook function for reading the mouse button state */ static int default_mouse_b(void) { if (mouse_needs_poll()) poll_mouse(); return mouse_b; } END_OF_STATIC_FUNCTION(default_mouse_b); /* hook functions for reading the mouse state */ int (*gui_mouse_x)(void) = default_mouse_x; int (*gui_mouse_y)(void) = default_mouse_y; int (*gui_mouse_z)(void) = default_mouse_z; int (*gui_mouse_b)(void) = default_mouse_b; /* timer to handle menu auto-opening */ static int gui_timer; static int gui_menu_opening_delay; /* Checking for double clicks is complicated. The user could release the * mouse button at almost any point, and I might miss it if I am doing some * other processing at the same time (eg. sending the single-click message). * To get around this I install a timer routine to do the checking for me, * so it will notice double clicks whenever they happen. */ static volatile int dclick_status, dclick_time; static int gui_install_count = 0; static int gui_install_time = 0; #define DCLICK_START 0 #define DCLICK_RELEASE 1 #define DCLICK_AGAIN 2 #define DCLICK_NOT 3 /* dclick_check: * Double click checking user timer routine. */ static void dclick_check(void) { gui_timer++; if (dclick_status==DCLICK_START) { /* first click... */ if (!gui_mouse_b()) { dclick_status = DCLICK_RELEASE; /* aah! released first */ dclick_time = 0; return; } } else if (dclick_status==DCLICK_RELEASE) { /* wait for second click */ if (gui_mouse_b()) { dclick_status = DCLICK_AGAIN; /* yes! the second click */ dclick_time = 0; return; } } else return; /* timeout? */ if (dclick_time++ > 10) dclick_status = DCLICK_NOT; } END_OF_STATIC_FUNCTION(dclick_check); /* gui_switch_callback: * Sets the dirty flags whenever a display switch occurs. */ static void gui_switch_callback(void) { if (active_dialog_player) active_dialog_player->res |= D_REDRAW_ALL; } /* position_dialog: * Moves all the objects in a dialog to the specified position. */ void position_dialog(DIALOG *dialog, int x, int y) { int min_x = INT_MAX; int min_y = INT_MAX; int xc, yc; int c; ASSERT(dialog); /* locate the upper-left corner */ for (c=0; dialog[c].proc; c++) { if (dialog[c].x < min_x) min_x = dialog[c].x; if (dialog[c].y < min_y) min_y = dialog[c].y; } /* move the dialog */ xc = min_x - x; yc = min_y - y; for (c=0; dialog[c].proc; c++) { dialog[c].x -= xc; dialog[c].y -= yc; } } /* centre_dialog: * Moves all the objects in a dialog so that the dialog is centered in * the screen. */ void centre_dialog(DIALOG *dialog) { int min_x = INT_MAX; int min_y = INT_MAX; int max_x = INT_MIN; int max_y = INT_MIN; int xc, yc; int c; ASSERT(dialog); /* find the extents of the dialog (done in many loops due to a bug * in MSVC that prevents the more sensible version from working) */ for (c=0; dialog[c].proc; c++) { if (dialog[c].x < min_x) min_x = dialog[c].x; } for (c=0; dialog[c].proc; c++) { if (dialog[c].y < min_y) min_y = dialog[c].y; } for (c=0; dialog[c].proc; c++) { if (dialog[c].x + dialog[c].w > max_x) max_x = dialog[c].x + dialog[c].w; } for (c=0; dialog[c].proc; c++) { if (dialog[c].y + dialog[c].h > max_y) max_y = dialog[c].y + dialog[c].h; } /* how much to move by? */ xc = (SCREEN_W - (max_x - min_x)) / 2 - min_x; yc = (SCREEN_H - (max_y - min_y)) / 2 - min_y; /* move it */ for (c=0; dialog[c].proc; c++) { dialog[c].x += xc; dialog[c].y += yc; } } /* set_dialog_color: * Sets the foreground and background colors of all the objects in a dialog. */ void set_dialog_color(DIALOG *dialog, int fg, int bg) { int c; ASSERT(dialog); for (c=0; dialog[c].proc; c++) { dialog[c].fg = fg; dialog[c].bg = bg; } } /* find_dialog_focus: * Searches the dialog for the object which has the input focus, returning * its index, or -1 if the focus is not set. Useful after do_dialog() exits * if you need to know which object was selected. */ int find_dialog_focus(DIALOG *dialog) { int c; ASSERT(dialog); for (c=0; dialog[c].proc; c++) if (dialog[c].flags & D_GOTFOCUS) return c; return -1; } /* object_message: * Sends a message to a widget, automatically scaring and unscaring * the mouse if the message is MSG_DRAW. */ int object_message(DIALOG *dialog, int msg, int c) { #ifdef ALLEGRO_WINDOWS /* exported address of d_clear_proc */ extern int (*_d_clear_proc)(int, DIALOG *, int); #endif int ret; ASSERT(dialog); if (msg == MSG_DRAW) { if (dialog->flags & D_HIDDEN) return D_O_K; #ifdef ALLEGRO_WINDOWS if (dialog->proc == _d_clear_proc) #else if (dialog->proc == d_clear_proc) #endif scare_mouse(); else scare_mouse_area(dialog->x, dialog->y, dialog->w, dialog->h); acquire_screen(); } ret = dialog->proc(msg, dialog, c); if (msg == MSG_DRAW) { release_screen(); unscare_mouse(); } if (ret & D_REDRAWME) { dialog->flags |= D_DIRTY; ret &= ~D_REDRAWME; } return ret; } /* dialog_message: * Sends a message to all the objects in a dialog. If any of the objects * return values other than D_O_K, returns the value and sets obj to the * object which produced it. */ int dialog_message(DIALOG *dialog, int msg, int c, int *obj) { int count, res, r, force, try; DIALOG *menu_dialog = NULL; ASSERT(dialog); /* Note: don't acquire the screen in here. A deadlock develops in a * situation like this: * * 1. this thread: acquires the screen; * 2. timer thread: wakes up, locks the timer_mutex, and calls a * callback to redraw the software mouse cursor, which tries to * acquire the screen; * 3. this thread: object_message(MSG_DRAW) calls scare_mouse() * which calls remove_int(). * * So this thread has the screen acquired and wants the timer_mutex, * whereas the timer thread holds the timer_mutex, but wants to acquire * the screen. The problem is calling scare_mouse() with the screen * acquired. */ force = ((msg == MSG_START) || (msg == MSG_END) || (msg >= MSG_USER)); res = D_O_K; /* If a menu spawned by a d_menu_proc object is active, the dialog engine * has effectively been shutdown for the sake of safety. This means that * we can't send the message to the other objects in the dialog. So try * first to send the message to the d_menu_proc object and, if the menu * is then not active anymore, send it to the other objects as well. */ if (active_menu_player) { try = 2; menu_dialog = active_menu_player->dialog; } else try = 1; for (; try > 0; try--) { for (count=0; dialog[count].proc; count++) { if ((try == 2) && (&dialog[count] != menu_dialog)) continue; if ((force) || (!(dialog[count].flags & D_HIDDEN))) { r = object_message(&dialog[count], msg, c); if (r != D_O_K) { res |= r; if (obj) *obj = count; } if ((msg == MSG_IDLE) && (dialog[count].flags & (D_DIRTY | D_HIDDEN)) == D_DIRTY) { dialog[count].flags &= ~D_DIRTY; object_message(dialog+count, MSG_DRAW, 0); } } } if (active_menu_player) break; } return res; } /* broadcast_dialog_message: * Broadcasts a message to all the objects in the active dialog. If any of * the dialog procedures return values other than D_O_K, it returns that * value. */ int broadcast_dialog_message(int msg, int c) { int nowhere; if (active_dialog) return dialog_message(active_dialog, msg, c, &nowhere); else return D_O_K; } /* find_mouse_object: * Finds which object the mouse is on top of. */ static int find_mouse_object(DIALOG *d) { int mouse_object = -1; int c; int res; ASSERT(d); for (c=0; d[c].proc; c++) { if ((gui_mouse_x() >= d[c].x) && (gui_mouse_y() >= d[c].y) && (gui_mouse_x() < d[c].x + d[c].w) && (gui_mouse_y() < d[c].y + d[c].h) && (!(d[c].flags & (D_HIDDEN | D_DISABLED)))) { /* check if this object wants the mouse */ res = object_message(d+c, MSG_WANTMOUSE, 0); if (!(res & D_DONTWANTMOUSE)) { mouse_object = c; } } } return mouse_object; } /* offer_focus: * Offers the input focus to a particular object. */ int offer_focus(DIALOG *dialog, int obj, int *focus_obj, int force) { int res = D_O_K; ASSERT(dialog); ASSERT(focus_obj); if ((obj == *focus_obj) || ((obj >= 0) && (dialog[obj].flags & (D_HIDDEN | D_DISABLED)))) return D_O_K; /* check if object wants the focus */ if (obj >= 0) { res = object_message(dialog+obj, MSG_WANTFOCUS, 0); if (res & D_WANTFOCUS) res ^= D_WANTFOCUS; else obj = -1; } if ((obj >= 0) || (force)) { /* take focus away from old object */ if (*focus_obj >= 0) { res |= object_message(dialog+*focus_obj, MSG_LOSTFOCUS, 0); if (res & D_WANTFOCUS) { if (obj < 0) return D_O_K; else res &= ~D_WANTFOCUS; } dialog[*focus_obj].flags &= ~D_GOTFOCUS; res |= object_message(dialog+*focus_obj, MSG_DRAW, 0); } *focus_obj = obj; /* give focus to new object */ if (obj >= 0) { dialog[obj].flags |= D_GOTFOCUS; res |= object_message(dialog+obj, MSG_GOTFOCUS, 0); res |= object_message(dialog+obj, MSG_DRAW, 0); } } return res; } #define MAX_OBJECTS 512 typedef struct OBJ_LIST { int index; int diff; } OBJ_LIST; /* Weight ratio between the orthogonal direction and the main direction when calculating the distance for the focus algorithm. */ #define DISTANCE_RATIO 8 /* Maximum size (in bytes) of a dialog array. */ #define MAX_SIZE 0x10000 /* 64 kb */ enum axis { X_AXIS, Y_AXIS }; /* obj_list_cmp: * Callback function for qsort(). */ static int obj_list_cmp(AL_CONST void *e1, AL_CONST void *e2) { return (((OBJ_LIST *)e1)->diff - ((OBJ_LIST *)e2)->diff); } /* cmp_tab: * Comparison function for tab key movement. */ static int cmp_tab(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2) { int ret = (int)((AL_CONST unsigned long)d2 - (AL_CONST unsigned long)d1); /* Wrap around if d2 is before d1 in the dialog array. */ if (ret < 0) ret += MAX_SIZE; return ret; } /* cmp_shift_tab: * Comparison function for shift+tab key movement. */ static int cmp_shift_tab(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2) { int ret = (int)((AL_CONST unsigned long)d1 - (AL_CONST unsigned long)d2); /* Wrap around if d2 is after d1 in the dialog array. */ if (ret < 0) ret += MAX_SIZE; return ret; } /* min_dist: * Returns the minimum distance between dialogs 'd1' and 'd2'. 'main_axis' * is taken account to give different weights to the axes in the distance * formula, as well as to shift the actual position of 'd2' along the axis * by the amount specified by 'bias'. */ static int min_dist(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2, enum axis main_axis, int bias) { int x_left = d1->x - d2->x - d2->w + 1; int x_right = d2->x - d1->x - d1->w + 1; int y_top = d1->y - d2->y - d2->h + 1; int y_bottom = d2->y - d1->y - d1->h + 1; if (main_axis == X_AXIS) { x_left -= bias; x_right += bias; y_top *= DISTANCE_RATIO; y_bottom *= DISTANCE_RATIO; } else { x_left *= DISTANCE_RATIO; x_right *= DISTANCE_RATIO; y_top -= bias; y_bottom += bias; } if (x_left > 0) { /* d2 is left of d1 */ if (y_top > 0) /* d2 is above d1 */ return x_left + y_top; else if (y_bottom > 0) /* d2 is below d1 */ return x_left + y_bottom; else /* vertically overlapping */ return x_left; } else if (x_right > 0) { /* d2 is right of d1 */ if (y_top > 0) /* d2 is above d1 */ return x_right + y_top; else if (y_bottom > 0) /* d2 is below d1 */ return x_right + y_bottom; else /* vertically overlapping */ return x_right; } /* horizontally overlapping */ else if (y_top > 0) /* d2 is above d1 */ return y_top; else if (y_bottom > 0) /* d2 is below d1 */ return y_bottom; else /* overlapping */ return 0; } /* cmp_right: * Comparison function for right arrow key movement. */ static int cmp_right(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2) { int bias; /* Wrap around if d2 is not fully contained in the half-plan delimited by d1's right edge and not containing it. */ if (d2->x < d1->x + d1->w) bias = +SCREEN_W; else bias = 0; return min_dist(d1, d2, X_AXIS, bias); } /* cmp_left: * Comparison function for left arrow key movement. */ static int cmp_left(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2) { int bias; /* Wrap around if d2 is not fully contained in the half-plan delimited by d1's left edge and not containing it. */ if (d2->x + d2->w > d1->x) bias = -SCREEN_W; else bias = 0; return min_dist(d1, d2, X_AXIS, bias); } /* cmp_down: * Comparison function for down arrow key movement. */ static int cmp_down(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2) { int bias; /* Wrap around if d2 is not fully contained in the half-plan delimited by d1's bottom edge and not containing it. */ if (d2->y < d1->y + d1->h) bias = +SCREEN_H; else bias = 0; return min_dist(d1, d2, Y_AXIS, bias); } /* cmp_up: * Comparison function for up arrow key movement. */ static int cmp_up(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2) { int bias; /* Wrap around if d2 is not fully contained in the half-plan delimited by d1's top edge and not containing it. */ if (d2->y + d2->h > d1->y) bias = -SCREEN_H; else bias = 0; return min_dist(d1, d2, Y_AXIS, bias); } /* move_focus: * Handles arrow key and tab movement through a dialog, deciding which * object should be given the input focus. */ static int move_focus(DIALOG *d, int ascii, int scan, int *focus_obj) { int (*cmp)(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2); OBJ_LIST obj[MAX_OBJECTS]; int obj_count = 0; int fobj, c; int res = D_O_K; /* choose a comparison function */ switch (scan) { case KEY_TAB: cmp = (ascii == '\t') ? cmp_tab : cmp_shift_tab; break; case KEY_RIGHT: cmp = cmp_right; break; case KEY_LEFT: cmp = cmp_left; break; case KEY_DOWN: cmp = cmp_down; break; case KEY_UP: cmp = cmp_up; break; default: return D_O_K; } /* fill temporary table */ for (c=0; d[c].proc; c++) { if (((*focus_obj < 0) || (c != *focus_obj)) && !(d[c].flags & (D_DISABLED | D_HIDDEN))) { obj[obj_count].index = c; if (*focus_obj >= 0) obj[obj_count].diff = cmp(d+*focus_obj, d+c); else obj[obj_count].diff = c; obj_count++; if (obj_count >= MAX_OBJECTS) break; } } /* sort table */ qsort(obj, obj_count, sizeof(OBJ_LIST), obj_list_cmp); /* find an object to give the focus to */ fobj = *focus_obj; for (c=0; cdialog+i, msg, c); \ if (r != D_O_K) { \ player->res |= r; \ player->obj = i; \ } \ } /* do_dialog: * The basic dialog manager. The list of dialog objects should be * terminated by one with a null dialog procedure. Returns the index of * the object which caused it to exit. */ int do_dialog(DIALOG *dialog, int focus_obj) { BITMAP *mouse_screen = _mouse_screen; BITMAP *gui_bmp = gui_get_screen(); int screen_count = _gfx_mode_set_count; void *player; ASSERT(dialog); if (!is_same_bitmap(_mouse_screen, gui_bmp) && !(gfx_capabilities&GFX_HW_CURSOR)) show_mouse(gui_bmp); player = init_dialog(dialog, focus_obj); while (update_dialog(player)) { /* If a menu is active, we yield here, since the dialog * engine is shut down so no user code can be running. */ if (active_menu_player) rest(1); } if (_gfx_mode_set_count == screen_count && !(gfx_capabilities&GFX_HW_CURSOR)) show_mouse(mouse_screen); return shutdown_dialog(player); } /* popup_dialog: * Like do_dialog(), but it stores the data on the screen before drawing * the dialog and restores it when the dialog is closed. The screen area * to be stored is calculated from the dimensions of the first object in * the dialog, so all the other objects should lie within this one. */ int popup_dialog(DIALOG *dialog, int focus_obj) { BITMAP *bmp; BITMAP *gui_bmp; int ret; ASSERT(dialog); bmp = create_bitmap(dialog->w, dialog->h); gui_bmp = gui_get_screen(); if (bmp) { scare_mouse_area(dialog->x, dialog->y, dialog->w, dialog->h); blit(gui_bmp, bmp, dialog->x, dialog->y, 0, 0, dialog->w, dialog->h); unscare_mouse(); } else *allegro_errno = ENOMEM; ret = do_dialog(dialog, focus_obj); if (bmp) { scare_mouse_area(dialog->x, dialog->y, dialog->w, dialog->h); blit(bmp, gui_bmp, 0, 0, dialog->x, dialog->y, dialog->w, dialog->h); unscare_mouse(); destroy_bitmap(bmp); } return ret; } /* init_dialog: * Sets up a dialog, returning a player object that can be used with * the update_dialog() and shutdown_dialog() functions. */ DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj) { DIALOG_PLAYER *player; BITMAP *gui_bmp = gui_get_screen(); struct al_active_dialog_player *n; char tmp1[64], tmp2[64]; int c; ASSERT(dialog); /* close any menu opened by a d_menu_proc */ if (active_menu_player) object_message(active_menu_player->dialog, MSG_LOSTMOUSE, 0); player = _AL_MALLOC(sizeof(DIALOG_PLAYER)); if (!player) { *allegro_errno = ENOMEM; return NULL; } /* append player to the list */ n = _AL_MALLOC(sizeof(struct al_active_dialog_player)); if (!n) { *allegro_errno = ENOMEM; _AL_FREE (player); return NULL; } n->next = NULL; n->player = player; if (!current_active_dialog_player) { current_active_dialog_player = first_active_dialog_player = n; } else { current_active_dialog_player->next = n; current_active_dialog_player = n; } player->res = D_REDRAW; player->joy_on = TRUE; player->click_wait = FALSE; player->dialog = dialog; player->obj = -1; player->mouse_obj = -1; player->mouse_oz = gui_mouse_z(); player->mouse_b = gui_mouse_b(); /* set up the global dialog pointer */ active_dialog_player = player; active_dialog = dialog; /* set up dclick checking code */ if (gui_install_count <= 0) { LOCK_VARIABLE(gui_timer); LOCK_VARIABLE(dclick_status); LOCK_VARIABLE(dclick_time); LOCK_VARIABLE(gui_mouse_x); LOCK_VARIABLE(gui_mouse_y); LOCK_VARIABLE(gui_mouse_z); LOCK_VARIABLE(gui_mouse_b); LOCK_FUNCTION(default_mouse_x); LOCK_FUNCTION(default_mouse_y); LOCK_FUNCTION(default_mouse_z); LOCK_FUNCTION(default_mouse_b); LOCK_FUNCTION(dclick_check); install_int(dclick_check, 20); switch (get_display_switch_mode()) { case SWITCH_AMNESIA: case SWITCH_BACKAMNESIA: set_display_switch_callback(SWITCH_IN, gui_switch_callback); } /* gets menu auto-opening delay (in milliseconds) from config file */ gui_menu_opening_delay = get_config_int(uconvert_ascii("system", tmp1), uconvert_ascii("menu_opening_delay", tmp2), 300); if (gui_menu_opening_delay >= 0) { /* adjust for actual timer speed */ gui_menu_opening_delay /= 20; } else { /* no auto opening */ gui_menu_opening_delay = -1; } gui_install_count = 1; gui_install_time = _allegro_count; } else gui_install_count++; /* initialise the dialog */ set_clip_rect(gui_bmp, 0, 0, SCREEN_W-1, SCREEN_H-1); set_clip_state(gui_bmp, TRUE); player->res |= dialog_message(dialog, MSG_START, 0, &player->obj); player->mouse_obj = find_mouse_object(dialog); if (player->mouse_obj >= 0) dialog[player->mouse_obj].flags |= D_GOTMOUSE; for (c=0; dialog[c].proc; c++) dialog[c].flags &= ~D_GOTFOCUS; if (focus_obj >= 0) c = focus_obj; else c = player->mouse_obj; if ((c >= 0) && ((object_message(dialog+c, MSG_WANTFOCUS, 0)) & D_WANTFOCUS)) { dialog[c].flags |= D_GOTFOCUS; player->focus_obj = c; } else player->focus_obj = -1; return player; } /* gui_set_screen: * Changes the target bitmap for GUI drawing operations */ void gui_set_screen(BITMAP *bmp) { gui_screen = bmp; } /* gui_get_screen: * Returns the gui_screen, or the default surface if gui_screen is NULL */ BITMAP *gui_get_screen(void) { return gui_screen?gui_screen:screen; } /* check_for_redraw: * Checks whether any parts of the current dialog need to be redraw. */ static void check_for_redraw(DIALOG_PLAYER *player) { struct al_active_dialog_player *iter; int c, r; ASSERT(player); /* need to redraw all active dialogs? */ if (player->res & D_REDRAW_ALL) { for (iter = first_active_dialog_player; iter != current_active_dialog_player; iter = iter->next) dialog_message(iter->player->dialog, MSG_DRAW, 0, NULL); player->res &= ~D_REDRAW_ALL; player->res |= D_REDRAW; } /* need to draw it? */ if (player->res & D_REDRAW) { player->res ^= D_REDRAW; player->res |= dialog_message(player->dialog, MSG_DRAW, 0, &player->obj); } /* check if any widget has to be redrawn */ for (c=0; player->dialog[c].proc; c++) { if ((player->dialog[c].flags & (D_DIRTY | D_HIDDEN)) == D_DIRTY) { player->dialog[c].flags &= ~D_DIRTY; MESSAGE(c, MSG_DRAW, 0); } } } /* update_dialog: * Updates the status of a dialog object returned by init_dialog(), * returning TRUE if it is still active or FALSE if it has finished. */ int update_dialog(DIALOG_PLAYER *player) { int c, cascii, cscan, ccombo, r, ret, nowhere, z; int new_mouse_b; ASSERT(player); /* redirect to update_menu() whenever a menu is activated */ if (active_menu_player) { if (!active_menu_player_zombie) { if (update_menu(active_menu_player)) return TRUE; } /* make sure all buttons are released before folding the menu */ if (gui_mouse_b()) { active_menu_player_zombie = TRUE; return TRUE; } else { active_menu_player_zombie = FALSE; for (c=0; player->dialog[c].proc; c++) if (&player->dialog[c] == active_menu_player->dialog) break; ASSERT(player->dialog[c].proc); MESSAGE(c, MSG_LOSTMOUSE, 0); goto getout; } } if (player->res & D_CLOSE) return FALSE; /* deal with mouse buttons presses and releases */ new_mouse_b = gui_mouse_b(); if (new_mouse_b != player->mouse_b) { player->res |= offer_focus(player->dialog, player->mouse_obj, &player->focus_obj, FALSE); if (player->mouse_obj >= 0) { /* send press and release messages */ if ((new_mouse_b & 1) && !(player->mouse_b & 1)) MESSAGE(player->mouse_obj, MSG_LPRESS, new_mouse_b); if (!(new_mouse_b & 1) && (player->mouse_b & 1)) MESSAGE(player->mouse_obj, MSG_LRELEASE, new_mouse_b); if ((new_mouse_b & 4) && !(player->mouse_b & 4)) MESSAGE(player->mouse_obj, MSG_MPRESS, new_mouse_b); if (!(new_mouse_b & 4) && (player->mouse_b & 4)) MESSAGE(player->mouse_obj, MSG_MRELEASE, new_mouse_b); if ((new_mouse_b & 2) && !(player->mouse_b & 2)) MESSAGE(player->mouse_obj, MSG_RPRESS, new_mouse_b); if (!(new_mouse_b & 2) && (player->mouse_b & 2)) MESSAGE(player->mouse_obj, MSG_RRELEASE, new_mouse_b); player->mouse_b = new_mouse_b; } else player->res |= dialog_message(player->dialog, MSG_IDLE, 0, &nowhere); } /* need to reinstall the dclick and switch handlers? */ if (gui_install_time != _allegro_count) { install_int(dclick_check, 20); switch (get_display_switch_mode()) { case SWITCH_AMNESIA: case SWITCH_BACKAMNESIA: set_display_switch_callback(SWITCH_IN, gui_switch_callback); } gui_install_time = _allegro_count; } /* are we dealing with a mouse click? */ if (player->click_wait) { if ((ABS(player->mouse_ox-gui_mouse_x()) > 8) || (ABS(player->mouse_oy-gui_mouse_y()) > 8)) dclick_status = DCLICK_NOT; /* waiting... */ if ((dclick_status != DCLICK_AGAIN) && (dclick_status != DCLICK_NOT)) { player->res |= dialog_message(player->dialog, MSG_IDLE, 0, &nowhere); check_for_redraw(player); return TRUE; } player->click_wait = FALSE; /* double click! */ if ((dclick_status==DCLICK_AGAIN) && (gui_mouse_x() >= player->dialog[player->mouse_obj].x) && (gui_mouse_y() >= player->dialog[player->mouse_obj].y) && (gui_mouse_x() <= player->dialog[player->mouse_obj].x + player->dialog[player->mouse_obj].w) && (gui_mouse_y() <= player->dialog[player->mouse_obj].y + player->dialog[player->mouse_obj].h)) { MESSAGE(player->mouse_obj, MSG_DCLICK, 0); } goto getout; } player->res &= ~D_USED_CHAR; /* need to give the input focus to someone? */ if (player->res & D_WANTFOCUS) { player->res ^= D_WANTFOCUS; player->res |= offer_focus(player->dialog, player->obj, &player->focus_obj, FALSE); } /* has mouse object changed? */ c = find_mouse_object(player->dialog); if (c != player->mouse_obj) { if (player->mouse_obj >= 0) { player->dialog[player->mouse_obj].flags &= ~D_GOTMOUSE; MESSAGE(player->mouse_obj, MSG_LOSTMOUSE, 0); } if (c >= 0) { player->dialog[c].flags |= D_GOTMOUSE; MESSAGE(c, MSG_GOTMOUSE, 0); } player->mouse_obj = c; /* move the input focus as well? */ if ((gui_mouse_focus) && (player->mouse_obj != player->focus_obj)) player->res |= offer_focus(player->dialog, player->mouse_obj, &player->focus_obj, TRUE); } /* deal with mouse button clicks */ if (new_mouse_b) { player->res |= offer_focus(player->dialog, player->mouse_obj, &player->focus_obj, FALSE); if (player->mouse_obj >= 0) { dclick_time = 0; dclick_status = DCLICK_START; player->mouse_ox = gui_mouse_x(); player->mouse_oy = gui_mouse_y(); /* send click message */ MESSAGE(player->mouse_obj, MSG_CLICK, new_mouse_b); if (player->res == D_O_K) player->click_wait = TRUE; } else player->res |= dialog_message(player->dialog, MSG_IDLE, 0, &nowhere); /* goto getout; */ /* to avoid an updating delay */ } /* deal with mouse wheel clicks */ z = gui_mouse_z(); if (z != player->mouse_oz) { player->res |= offer_focus(player->dialog, player->mouse_obj, &player->focus_obj, FALSE); if (player->mouse_obj >= 0) { MESSAGE(player->mouse_obj, MSG_WHEEL, z-player->mouse_oz); } else player->res |= dialog_message(player->dialog, MSG_IDLE, 0, &nowhere); player->mouse_oz = z; /* goto getout; */ /* to avoid an updating delay */ } /* fake joystick input by converting it to key presses */ if (player->joy_on) rest(20); poll_joystick(); if (player->joy_on) { if ((!joy[0].stick[0].axis[0].d1) && (!joy[0].stick[0].axis[0].d2) && (!joy[0].stick[0].axis[1].d1) && (!joy[0].stick[0].axis[1].d2) && (!joy[0].button[0].b) && (!joy[0].button[1].b)) { player->joy_on = FALSE; rest(20); } cascii = cscan = 0; } else { if (joy[0].stick[0].axis[0].d1) { cascii = 0; cscan = KEY_LEFT; player->joy_on = TRUE; } else if (joy[0].stick[0].axis[0].d2) { cascii = 0; cscan = KEY_RIGHT; player->joy_on = TRUE; } else if (joy[0].stick[0].axis[1].d1) { cascii = 0; cscan = KEY_UP; player->joy_on = TRUE; } else if (joy[0].stick[0].axis[1].d2) { cascii = 0; cscan = KEY_DOWN; player->joy_on = TRUE; } else if ((joy[0].button[0].b) || (joy[0].button[1].b)) { cascii = ' '; cscan = KEY_SPACE; player->joy_on = TRUE; } else cascii = cscan = 0; } /* deal with keyboard input */ if ((cascii) || (cscan) || (keypressed())) { if ((!cascii) && (!cscan)) cascii = ureadkey(&cscan); ccombo = (cscan<<8) | ((cascii <= 255) ? cascii : '^'); /* let object deal with the key */ if (player->focus_obj >= 0) { MESSAGE(player->focus_obj, MSG_CHAR, ccombo); if (player->res & (D_USED_CHAR | D_CLOSE)) goto getout; MESSAGE(player->focus_obj, MSG_UCHAR, cascii); if (player->res & (D_USED_CHAR | D_CLOSE)) goto getout; } /* keyboard shortcut? */ for (c=0; player->dialog[c].proc; c++) { if ((((cascii > 0) && (cascii <= 255) && (utolower(player->dialog[c].key) == utolower((cascii)))) || ((!cascii) && (player->dialog[c].key == (cscan<<8)))) && (!(player->dialog[c].flags & (D_HIDDEN | D_DISABLED)))) { MESSAGE(c, MSG_KEY, ccombo); goto getout; } } /* broadcast in case any other objects want it */ for (c=0; player->dialog[c].proc; c++) { if (!(player->dialog[c].flags & (D_HIDDEN | D_DISABLED))) { MESSAGE(c, MSG_XCHAR, ccombo); if (player->res & D_USED_CHAR) goto getout; } } /* pass or to selected object */ if (((cascii == '\r') || (cascii == '\n') || (cascii == ' ')) && (player->focus_obj >= 0)) { MESSAGE(player->focus_obj, MSG_KEY, ccombo); goto getout; } /* ESC closes dialog */ if (cascii == 27) { player->res |= D_CLOSE; player->obj = -1; goto getout; } /* move focus around the dialog */ player->res |= move_focus(player->dialog, cascii, cscan, &player->focus_obj); } /* redraw? */ check_for_redraw(player); /* send idle messages */ player->res |= dialog_message(player->dialog, MSG_IDLE, 0, &player->obj); getout: ret = (!(player->res & D_CLOSE)); player->res &= ~D_CLOSE; return ret; } /* shutdown_dialog: * Destroys a dialog object returned by init_dialog(), returning the index * of the object that caused it to exit. */ int shutdown_dialog(DIALOG_PLAYER *player) { struct al_active_dialog_player *iter, *prev; int obj; ASSERT(player); /* send the finish messages */ dialog_message(player->dialog, MSG_END, 0, &player->obj); /* remove the double click handler */ gui_install_count--; if (gui_install_count <= 0) { remove_int(dclick_check); remove_display_switch_callback(gui_switch_callback); } if (player->mouse_obj >= 0) player->dialog[player->mouse_obj].flags &= ~D_GOTMOUSE; /* remove dialog player from the list of active players */ for (iter = first_active_dialog_player, prev = 0; iter != 0; prev = iter, iter = iter->next) { if (iter->player == player) { if (prev) prev->next = iter->next; else first_active_dialog_player = iter->next; if (iter == current_active_dialog_player) current_active_dialog_player = prev; _AL_FREE (iter); break; } } if (current_active_dialog_player) active_dialog_player = current_active_dialog_player->player; else active_dialog_player = NULL; if (active_dialog_player) active_dialog = active_dialog_player->dialog; else active_dialog = NULL; obj = player->obj; _AL_FREE(player); return obj; } void (*gui_menu_draw_menu)(int x, int y, int w, int h) = NULL; void (*gui_menu_draw_menu_item)(MENU *m, int x, int y, int w, int h, int bar, int sel) = NULL; /* split_around_tab: * Helper function for splitting a string into two tokens * delimited by the first TAB character. */ static char* split_around_tab(const char *s, char **tok1, char **tok2) { char *buf, *last; char tmp[16]; buf = _al_ustrdup(s); *tok1 = ustrtok_r(buf, uconvert_ascii("\t", tmp), &last); *tok2 = ustrtok_r(NULL, empty_string, &last); return buf; } /* bar_entry_lengh: * Helper function for calculating the length of a menu bar entry. */ static int bar_entry_length(const char *text) { char *buf, *tok1, *tok2; int len; buf = split_around_tab(text, &tok1, &tok2); len = gui_strlen(tok1) + 16; if (tok2) len += gui_strlen(tok2) + 16; _AL_FREE(buf); return len; } /* get_menu_pos: * Calculates the coordinates of an object within a top level menu bar. */ static void get_menu_pos(MENU_PLAYER *m, int c, int *x, int *y, int *w) { int c2; if (m->bar) { *x = m->x+1; for (c2=0; c2menu[c2].text); *y = m->y+1; *w = bar_entry_length(m->menu[c].text); } else { *x = m->x+1; *y = m->y+c*(text_height(font)+4)+1; *w = m->w-3; } } /* draw_menu_item: * Draws an item from a popup menu onto the screen. */ static void draw_menu_item(MENU_PLAYER *m, int c) { int fg, bg; int x, y, w; char *buf, *tok1, *tok2; int my; BITMAP *gui_bmp = gui_get_screen(); get_menu_pos(m, c, &x, &y, &w); if (gui_menu_draw_menu_item) { gui_menu_draw_menu_item(&m->menu[c], x, y, w, text_height(font)+4, m->bar, (c == m->sel) ? TRUE : FALSE); return; } if (m->menu[c].flags & D_DISABLED) { if (c == m->sel) { fg = gui_mg_color; bg = gui_fg_color; } else { fg = gui_mg_color; bg = gui_bg_color; } } else { if (c == m->sel) { fg = gui_bg_color; bg = gui_fg_color; } else { fg = gui_fg_color; bg = gui_bg_color; } } rectfill(gui_bmp, x, y, x+w-1, y+text_height(font)+3, bg); if (ugetc(m->menu[c].text)) { buf = split_around_tab(m->menu[c].text, &tok1, &tok2); gui_textout_ex(gui_bmp, tok1, x+8, y+1, fg, bg, FALSE); if (tok2) gui_textout_ex(gui_bmp, tok2, x+w-gui_strlen(tok2)-10, y+1, fg, bg, FALSE); if ((m->menu[c].child) && (!m->bar)) { my = y + text_height(font)/2; hline(gui_bmp, x+w-8, my+1, x+w-4, fg); hline(gui_bmp, x+w-8, my+0, x+w-5, fg); hline(gui_bmp, x+w-8, my-1, x+w-6, fg); hline(gui_bmp, x+w-8, my-2, x+w-7, fg); putpixel(gui_bmp, x+w-8, my-3, fg); hline(gui_bmp, x+w-8, my+2, x+w-5, fg); hline(gui_bmp, x+w-8, my+3, x+w-6, fg); hline(gui_bmp, x+w-8, my+4, x+w-7, fg); putpixel(gui_bmp, x+w-8, my+5, fg); } _AL_FREE(buf); } else hline(gui_bmp, x, y+text_height(font)/2+2, x+w, fg); if (m->menu[c].flags & D_SELECTED) { line(gui_bmp, x+1, y+text_height(font)/2+1, x+3, y+text_height(font)+1, fg); line(gui_bmp, x+3, y+text_height(font)+1, x+6, y+2, fg); } } /* draw_menu: * Draws a popup menu onto the screen. */ static void draw_menu(MENU_PLAYER *m) { int c; if (gui_menu_draw_menu) gui_menu_draw_menu(m->x, m->y, m->w, m->h); else { BITMAP *gui_bmp = gui_get_screen(); rectfill(gui_bmp, m->x, m->y, m->x+m->w-2, m->y+m->h-2, gui_bg_color); rect(gui_bmp, m->x, m->y, m->x+m->w-2, m->y+m->h-2, gui_fg_color); vline(gui_bmp, m->x+m->w-1, m->y+1, m->y+m->h-1, gui_fg_color); hline(gui_bmp, m->x+1, m->y+m->h-1, m->x+m->w-1, gui_fg_color); } for (c=0; m->menu[c].text; c++) draw_menu_item(m, c); } /* menu_mouse_object: * Returns the index of the object the mouse is currently on top of. */ static int menu_mouse_object(MENU_PLAYER *m) { int c; int x, y, w; for (c=0; csize; c++) { get_menu_pos(m, c, &x, &y, &w); if ((gui_mouse_x() >= x) && (gui_mouse_x() < x+w) && (gui_mouse_y() >= y) && (gui_mouse_y() < y+(text_height(font)+4))) return (ugetc(m->menu[c].text)) ? c : -1; } return -1; } /* mouse_in_single_menu: * Checks if the mouse is inside a single menu. */ static INLINE int mouse_in_single_menu(MENU_PLAYER *m) { if ((gui_mouse_x() >= m->x) && (gui_mouse_x() < m->x+m->w) && (gui_mouse_y() >= m->y) && (gui_mouse_y() < m->y+m->h)) return TRUE; else return FALSE; } /* mouse_in_parent_menu: * Recursively checks if the mouse is inside a menu (or any of its parents) * and simultaneously not on the selected item of the menu. */ static int mouse_in_parent_menu(MENU_PLAYER *m) { int c; if (!m) return FALSE; c = menu_mouse_object(m); if ((c >= 0) && (c != m->sel)) return TRUE; return mouse_in_parent_menu(m->parent); } /* layout_menu: * Calculates the layout of the menu. */ static void layout_menu(MENU_PLAYER *m, MENU *menu, int bar, int x, int y, int minw, int minh) { char *buf, *tok1, *tok2; int extra = 0; int c; int child = FALSE; m->menu = menu; m->bar = bar; m->x = x; m->y = y; m->w = 3; m->h = (m->bar) ? (text_height(font)+7) : 3; m->proc = NULL; m->sel = -1; /* calculate size of the menu */ for (m->size=0; m->menu[m->size].text; m->size++) { if (m->bar) { m->w += bar_entry_length(m->menu[m->size].text); } else { if (m->menu[m->size].child) child = TRUE; if (ugetc(m->menu[m->size].text)) { buf = split_around_tab(m->menu[m->size].text, &tok1, &tok2); c = gui_strlen(tok1); } else { buf = NULL; c = 0; } m->h += text_height(font)+4; m->w = MAX(m->w, c+16); if (buf) { if (tok2) { c = gui_strlen(tok2); extra = MAX(extra, c); } _AL_FREE(buf); } } } if (extra) m->w += extra+16; if (child) m->w += 22; m->w = MAX(m->w, minw); m->h = MAX(m->h, minh); } /* menu_key_shortcut: * Returns true if c is indicated as a keyboard shortcut by a '&' character * in the specified string. */ static int menu_key_shortcut(int c, AL_CONST char *s) { int d; while ((d = ugetxc(&s)) != 0) { if (d == '&') { d = ugetc(s); if ((d != '&') && (utolower(d) == utolower(c & 0xFF))) return TRUE; } } return FALSE; } /* menu_alt_key: * Searches a menu for keyboard shortcuts, for the alt+letter to bring * up a menu. */ static int menu_alt_key(int k, MENU *m) { static unsigned char alt_table[] = { KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z }; AL_CONST char *s; int c, d; if (k & 0xFF) return 0; k >>= 8; c = scancode_to_ascii(k); if (c) { k = c; } else { for (c=0; c<(int)sizeof(alt_table); c++) { if (k == alt_table[c]) { k = c + 'a'; break; } } if (c >= (int)sizeof(alt_table)) return 0; } for (c=0; m[c].text; c++) { s = m[c].text; while ((d = ugetxc(&s)) != 0) { if (d == '&') { d = ugetc(s); if ((d != '&') && (utolower(d) == utolower(k))) return k; } } } return 0; } /* do_menu: * Displays and animates a popup menu at the specified screen position, * returning the index of the item that was selected, or -1 if it was * dismissed. If the menu crosses the edge of the screen it will be moved. */ int do_menu(MENU *menu, int x, int y) { MENU_PLAYER *player; int ret; ASSERT(menu); player = init_menu(menu, x ,y); while (update_menu(player)) rest(1); ret = shutdown_menu(player); do { } while (gui_mouse_b()); return ret; } /* init_single_menu: * Worker function for initialising a menu. */ static MENU_PLAYER *init_single_menu(MENU *menu, MENU_PLAYER *parent, DIALOG *dialog, int bar, int x, int y, int repos, int minw, int minh) { BITMAP *gui_bmp = gui_get_screen(); int scare = is_same_bitmap(gui_bmp, _mouse_screen); MENU_PLAYER *player; ASSERT(menu); player = _AL_MALLOC(sizeof(MENU_PLAYER)); if (!player) { *allegro_errno = ENOMEM; return NULL; } layout_menu(player, menu, bar, x, y, minw, minh); if (repos) { if(parent && !parent->bar) { if(player->x + player->w >= SCREEN_W) player->x = parent->x - player->w + 1; } player->x = CLAMP(0, player->x, SCREEN_W-player->w-1); player->y = CLAMP(0, player->y, SCREEN_H-player->h-1); } if (scare) scare_mouse_area(player->x, player->y, player->w, player->h); /* save screen under the menu */ player->saved = create_bitmap(player->w, player->h); if (player->saved) blit(gui_bmp, player->saved, player->x, player->y, 0, 0, player->w, player->h); else *allegro_errno = ENOMEM; /* setup state variables */ player->sel = menu_mouse_object(player); if (scare) unscare_mouse(); player->mouse_button_was_pressed = gui_mouse_b(); player->back_from_child = FALSE; player->timestamp = gui_timer; player->mouse_sel = player->sel; player->redraw = TRUE; player->auto_open = TRUE; player->ret = -1; player->dialog = dialog; player->parent = parent; player->child = NULL; return player; } /* init_menu: * Sets up a menu, returning a menu player object that can be used * with the update_menu() and shutdown_menu() functions. */ MENU_PLAYER *init_menu(MENU *menu, int x, int y) { return init_single_menu(menu, NULL, NULL, FALSE, x, y, TRUE, 0, 0); } /* update_menu: * Updates the status of a menu player object returned by init_menu(), * returning TRUE if it is still active or FALSE if it has finished. * * The navigation through the arborescence of menus can be done: * - with the arrow keys, * - with mouse point-and-clicks, * - with mouse movements when the mouse button is being held down, * - with mouse movements only if gui_menu_opening_delay is non negative. */ int update_menu(MENU_PLAYER *player) { MENU_PLAYER *i; int c, c2; int old_sel, child_ret; int child_x, child_y; ASSERT(player); /* find activated menu */ while (player->child) player = player->child; old_sel = player->sel; c = menu_mouse_object(player); if ((gui_mouse_b()) || (c != player->mouse_sel)) { player->sel = player->mouse_sel = c; player->auto_open = TRUE; } if (gui_mouse_b()) { /* button pressed? */ /* Dismiss menu if: * - the mouse cursor is outside the menu and inside the parent menu, or * - the mouse cursor is outside the menu and the button has just been pressed. */ if (!mouse_in_single_menu(player)) { if (mouse_in_parent_menu(player->parent) || (!player->mouse_button_was_pressed)) { player->ret = -2; goto End; } } if ((player->sel >= 0) && (player->menu[player->sel].child)) /* bring up child menu? */ player->ret = player->sel; /* don't trigger the 'select' event on button press for non menu item */ player->mouse_button_was_pressed = TRUE; clear_keybuf(); } else { /* button not pressed */ /* trigger the 'select' event only on button release for non menu item */ if (player->mouse_button_was_pressed) { player->ret = player->sel; player->mouse_button_was_pressed = FALSE; } if (keypressed()) { /* keyboard input */ player->timestamp = gui_timer; player->auto_open = FALSE; c = readkey(); if ((c & 0xFF) == 27) { player->ret = -2; goto End; } switch (c >> 8) { case KEY_LEFT: if (player->parent) { if (player->parent->bar) { simulate_keypress(KEY_LEFT<<8); simulate_keypress(KEY_DOWN<<8); } player->ret = -2; goto End; } /* fall through */ case KEY_UP: if ((((c >> 8) == KEY_LEFT) && (player->bar)) || (((c >> 8) == KEY_UP) && (!player->bar))) { c = player->sel; do { c--; if (c < 0) c = player->size - 1; } while ((!ugetc(player->menu[c].text)) && (c != player->sel)); player->sel = c; } break; case KEY_RIGHT: if (((player->sel < 0) || (!player->menu[player->sel].child)) && (player->parent) && (player->parent->bar)) { simulate_keypress(KEY_RIGHT<<8); simulate_keypress(KEY_DOWN<<8); player->ret = -2; goto End; } /* fall through */ case KEY_DOWN: if ((player->sel >= 0) && (player->menu[player->sel].child) && ((((c >> 8) == KEY_RIGHT) && (!player->bar)) || (((c >> 8) == KEY_DOWN) && (player->bar)))) { player->ret = player->sel; } else if ((((c >> 8) == KEY_RIGHT) && (player->bar)) || (((c >> 8) == KEY_DOWN) && (!player->bar))) { c = player->sel; do { c++; if (c >= player->size) c = 0; } while ((!ugetc(player->menu[c].text)) && (c != player->sel)); player->sel = c; } break; case KEY_SPACE: case KEY_ENTER: if (player->sel >= 0) player->ret = player->sel; break; default: if ((!player->parent) && ((c & 0xFF) == 0)) c = menu_alt_key(c, player->menu); for (c2=0; player->menu[c2].text; c2++) { if (menu_key_shortcut(c, player->menu[c2].text)) { player->ret = player->sel = c2; break; } } if (player->parent) { i = player->parent; for (c2=0; i->parent; c2++) i = i->parent; c = menu_alt_key(c, i->menu); if (c) { while (c2-- > 0) simulate_keypress(27); simulate_keypress(c); player->ret = -2; goto End; } } break; } } } /* end of input processing */ if ((player->redraw) || (player->sel != old_sel)) { /* selection changed? */ BITMAP *gui_bmp = gui_get_screen(); int scare = is_same_bitmap(gui_bmp, _mouse_screen); player->timestamp = gui_timer; if (scare) scare_mouse_area(player->x, player->y, player->w, player->h); acquire_bitmap(gui_bmp); if (player->redraw) { draw_menu(player); player->redraw = FALSE; } else { if (old_sel >= 0) draw_menu_item(player, old_sel); if (player->sel >= 0) draw_menu_item(player, player->sel); } release_bitmap(gui_bmp); if (scare) unscare_mouse(); } if (player->auto_open && (gui_menu_opening_delay >= 0)) { /* menu auto-opening on? */ if (!mouse_in_single_menu(player)) { if (mouse_in_parent_menu(player->parent)) { /* automatically goes back to parent */ player->ret = -3; goto End; } } if ((player->mouse_sel >= 0) && (player->menu[player->mouse_sel].child)) { if (player->bar) { /* top level menu auto-opening if back from child */ if (player->back_from_child) { player->timestamp = gui_timer; player->ret = player->mouse_sel; } } else { /* sub menu auto-opening if enough time has passed */ if ((gui_timer - player->timestamp) > gui_menu_opening_delay) player->ret = player->mouse_sel; } } player->back_from_child = FALSE; } End: if (player->ret >= 0) { /* item selected? */ if (player->menu[player->ret].flags & D_DISABLED) { return TRUE; /* continue */ } else if (player->menu[player->ret].child) { /* child menu? */ if (player->bar) { get_menu_pos(player, player->ret, &child_x, &child_y, &c); child_x += 6; child_y += text_height(font) + 7; } else { child_x = player->x+player->w - 3; child_y = player->y + (text_height(font)+4)*player->ret + text_height(font)/4 + 1; } /* recursively call child menu */ player->child = init_single_menu(player->menu[player->ret].child, player, NULL, FALSE, child_x, child_y, TRUE, 0, 0); return TRUE; /* continue */ } while (player->parent) { /* parent menu? */ player = player->parent; shutdown_single_menu(player->child, NULL); player->child = NULL; } return FALSE; /* item selected */ } if (player->ret < -1) { /* dismiss menu ? */ if (player->parent) { child_ret = player->ret; /* needed below */ player = player->parent; shutdown_single_menu(player->child, NULL); player->child = NULL; player->ret = -1; player->mouse_button_was_pressed = FALSE; player->mouse_sel = menu_mouse_object(player); if (child_ret == -3) { /* return caused by mouse movement? */ player->sel = player->mouse_sel; player->redraw = TRUE; player->timestamp = gui_timer; player->back_from_child = TRUE; } return TRUE; /* return to parent */ } return FALSE; /* menu dismissed */ } /* special kludge for menu bar */ if ((player->bar) && (!gui_mouse_b()) && (!keypressed()) && (!mouse_in_single_menu(player))) return FALSE; return TRUE; } /* shutdown_single_menu: * Worker function for shutting down a menu. */ static int shutdown_single_menu(MENU_PLAYER *player, int *dret) { int ret; ASSERT(player); if (dret) *dret = 0; if ((!player->proc) && (player->ret >= 0)) { /* callback function? */ active_menu = &player->menu[player->ret]; player->proc = active_menu->proc; } if (player->ret >= 0) { if (player->parent) player->parent->proc = player->proc; else { if (player->proc) { ret = player->proc(); if (dret) *dret = ret; } } } /* restore screen */ if (player->saved) { BITMAP *gui_bmp = gui_get_screen(); int scare = is_same_bitmap(gui_bmp, _mouse_screen); if (scare) scare_mouse_area(player->x, player->y, player->w, player->h); blit(player->saved, gui_bmp, 0, 0, player->x, player->y, player->w, player->h); if (scare) unscare_mouse(); destroy_bitmap(player->saved); } ret = player->ret; _AL_FREE(player); return ret; } /* shutdown_tree_menu: * Destroys a menu player object returned by init_single_menu(), after * recursively closing all the sub-menus if necessary, and returns the * index of the item that was selected, or -1 if it was dismissed. */ static int shutdown_tree_menu(MENU_PLAYER *player, int *dret) { ASSERT(player); if (player->child) { shutdown_tree_menu(player->child, dret); player->child = NULL; } return shutdown_single_menu(player, dret); } /* shutdown_menu: * Destroys a menu player object returned by init_menu() and returns * the index of the item that was selected, or -1 if it was dismissed. */ int shutdown_menu(MENU_PLAYER *player) { return shutdown_tree_menu(player, NULL); } /* d_menu_proc: * Dialog procedure for adding drop down menus to a GUI dialog. This * displays the top level menu items as a horizontal bar (eg. across the * top of the screen), and pops up child menus when they are clicked. * When it executes one of the menu callback routines, it passes the * return value back to the dialog manager, so these can return D_O_K, * D_CLOSE, D_REDRAW, etc. */ int d_menu_proc(int msg, DIALOG *d, int c) { MENU_PLAYER m, *mp; int ret = D_O_K; int x, i; ASSERT(d); switch (msg) { case MSG_START: layout_menu(&m, d->dp, TRUE, d->x, d->y, d->w, d->h); d->w = m.w; d->h = m.h; break; case MSG_DRAW: layout_menu(&m, d->dp, TRUE, d->x, d->y, d->w, d->h); draw_menu(&m); break; case MSG_XCHAR: x = menu_alt_key(c, d->dp); if (!x) break; ret |= D_USED_CHAR; simulate_keypress(x); /* fall through */ case MSG_GOTMOUSE: case MSG_CLICK: /* steal the mouse */ for (i=0; active_dialog[i].proc; i++) if (active_dialog[i].flags & D_GOTMOUSE) { active_dialog[i].flags &= ~D_GOTMOUSE; object_message(active_dialog+i, MSG_LOSTMOUSE, 0); break; } /* initialize the menu */ active_menu_player = init_single_menu(d->dp, NULL, d, TRUE, d->x, d->y, FALSE, d->w, d->h); break; case MSG_LOSTMOUSE: case MSG_END: if (active_menu_player) { /* shutdown_tree_menu may call nested dialogs */ mp = active_menu_player; active_menu_player = NULL; shutdown_tree_menu(mp, &x); ret |= x; /* put the mouse */ i = find_mouse_object(active_dialog); if ((i >= 0) && (&active_dialog[i] != d)) { active_dialog[i].flags |= D_GOTMOUSE; object_message(active_dialog+i, MSG_GOTMOUSE, 0); } } break; } return ret; } static DIALOG alert_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { _gui_shadow_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; #define A_S1 1 #define A_S2 2 #define A_S3 3 #define A_B1 4 #define A_B2 5 #define A_B3 6 /* alert3: * Displays a simple alert box, containing three lines of text (s1-s3), * and with either one, two, or three buttons. The text for these buttons * is passed in b1, b2, and b3 (NULL for buttons which are not used), and * the keyboard shortcuts in c1 and c2. Returns 1, 2, or 3 depending on * which button was selected. */ int alert3(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3) { char tmp[16]; int avg_w, avg_h; int len1, len2, len3; int maxlen = 0; int buttons = 0; int b[3]; int c; #define SORT_OUT_BUTTON(x) { \ if (b##x) { \ alert_dialog[A_B##x].flags &= ~D_HIDDEN; \ alert_dialog[A_B##x].key = c##x; \ alert_dialog[A_B##x].dp = (char *)b##x; \ len##x = gui_strlen(b##x); \ b[buttons++] = A_B##x; \ } \ else { \ alert_dialog[A_B##x].flags |= D_HIDDEN; \ len##x = 0; \ } \ } usetc(tmp+usetc(tmp, ' '), 0); avg_w = text_length(font, tmp); avg_h = text_height(font); alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp = alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = empty_string; if (s1) { alert_dialog[A_S1].dp = (char *)s1; maxlen = text_length(font, s1); } if (s2) { alert_dialog[A_S2].dp = (char *)s2; len1 = text_length(font, s2); if (len1 > maxlen) maxlen = len1; } if (s3) { alert_dialog[A_S3].dp = (char *)s3; len1 = text_length(font, s3); if (len1 > maxlen) maxlen = len1; } SORT_OUT_BUTTON(1); SORT_OUT_BUTTON(2); SORT_OUT_BUTTON(3); len1 = MAX(len1, MAX(len2, len3)) + avg_w*3; if (len1*buttons > maxlen) maxlen = len1*buttons; maxlen += avg_w*4; alert_dialog[0].w = maxlen; alert_dialog[A_S1].w = alert_dialog[A_S2].w = alert_dialog[A_S3].w = maxlen - avg_w*2; alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x = alert_dialog[0].x + avg_w; alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1; alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x = alert_dialog[0].x + maxlen/2 - len1/2; if (buttons == 3) { alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1*3/2 - avg_w; alert_dialog[b[2]].x = alert_dialog[0].x + maxlen/2 + len1/2 + avg_w; } else if (buttons == 2) { alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1 - avg_w; alert_dialog[b[1]].x = alert_dialog[0].x + maxlen/2 + avg_w; } alert_dialog[0].h = avg_h*8; alert_dialog[A_S1].y = alert_dialog[0].y + avg_h; alert_dialog[A_S2].y = alert_dialog[0].y + avg_h*2; alert_dialog[A_S3].y = alert_dialog[0].y + avg_h*3; alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h; alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = alert_dialog[0].y + avg_h*5; alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = avg_h*2; centre_dialog(alert_dialog); set_dialog_color(alert_dialog, gui_fg_color, gui_bg_color); for (c = 0; alert_dialog[c].proc; c++) if (alert_dialog[c].proc == _gui_ctext_proc) alert_dialog[c].bg = -1; clear_keybuf(); do { } while (gui_mouse_b()); c = popup_dialog(alert_dialog, A_B1); if (c == A_B1) return 1; else if (c == A_B2) return 2; else return 3; } /* alert: * Displays a simple alert box, containing three lines of text (s1-s3), * and with either one or two buttons. The text for these buttons is passed * in b1 and b2 (b2 may be null), and the keyboard shortcuts in c1 and c2. * Returns 1 or 2 depending on which button was selected. */ int alert(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2) { int ret; ret = alert3(s1, s2, s3, b1, b2, NULL, c1, c2, 0); if (ret > 2) ret = 2; return ret; } allegro-4.4.3.1/src/timer.c0000664000175000017500000003367313437077643014367 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Timer interrupt routines. * * By Shawn Hargreaves. * * Synchronization added by Eric Botcazou. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" TIMER_DRIVER *timer_driver = NULL; /* the active driver */ int _timer_installed = FALSE; TIMER_QUEUE _timer_queue[MAX_TIMERS]; /* list of active callbacks */ volatile int retrace_count = 0; /* used for retrace syncing */ void (*retrace_proc)(void) = NULL; long _vsync_speed = BPS_TO_TIMER(70); /* retrace speed */ static long vsync_counter; /* retrace position counter */ int _timer_use_retrace = FALSE; /* are we synced to the retrace? */ volatile int _retrace_hpp_value = -1; /* to set during next retrace */ #ifdef ALLEGRO_MULTITHREADED static void *timer_mutex = NULL; /* global timer mutex */ /* Why we need timer_mutex: * * 1. So _timer_queue[] is not changed in the middle of * _handle_timer_tick's loop, possibly causing a null pointer * dereference or corruption; * * 2. So that after "remove_int(my_callback);" returns, my_callback * is guaranteed not to be in the _timer_queue and will not be * called from the timer thread. Eric explains it more clearly: * * my_callback can have been fired but has not completed yet; context * switch; the main thread returns from remove_int and set my_pointer * to 0; context switch; the callback dereferences my_pointer. Ergo * remove_int must wait for all callbacks to have completed before * returning. */ #else static int timer_semaphore = FALSE; /* reentrant interrupt? */ #endif static volatile long timer_delay = 0; /* lost interrupt rollover */ /* _handle_timer_tick: * Called by the driver to handle a timer tick. */ long _handle_timer_tick(int interval) { long new_delay = 0x8000; long d; int i; timer_delay += interval; #ifdef ALLEGRO_MULTITHREADED system_driver->lock_mutex(timer_mutex); #else /* reentrant interrupt? */ if (timer_semaphore) return 0x2000; timer_semaphore = TRUE; #endif d = timer_delay; /* deal with retrace synchronisation */ vsync_counter -= d; while (vsync_counter <= 0) { vsync_counter += _vsync_speed; retrace_count++; if (retrace_proc) retrace_proc(); } /* process the user callbacks */ for (i=0; i 0)) { _timer_queue[i].counter -= d; while ((_timer_queue[i].counter <= 0) && ((_timer_queue[i].proc) || (_timer_queue[i].param_proc)) && (_timer_queue[i].speed > 0)) { _timer_queue[i].counter += _timer_queue[i].speed; if (_timer_queue[i].param_proc) _timer_queue[i].param_proc(_timer_queue[i].param); else _timer_queue[i].proc(); } if ((_timer_queue[i].counter > 0) && ((_timer_queue[i].proc) || (_timer_queue[i].param_proc)) && (_timer_queue[i].counter < new_delay)) { new_delay = _timer_queue[i].counter; } } } timer_delay -= d; #ifdef ALLEGRO_MULTITHREADED system_driver->unlock_mutex(timer_mutex); #else timer_semaphore = FALSE; #endif #ifdef ALLEGRO_WINDOWS /* fudge factor to prevent interrupts from coming too close to each other */ if (new_delay < MSEC_TO_TIMER(1)) new_delay = MSEC_TO_TIMER(1); #endif return new_delay; } END_OF_FUNCTION(_handle_timer_tick); /* simple interrupt handler for the rest() function */ static volatile long rest_count; static void rest_int(void) { rest_count--; } END_OF_STATIC_FUNCTION(rest_int); /* rest_callback: * Waits for time milliseconds. */ void rest_callback(unsigned int time, void (*callback)(void)) { if (!time) { ASSERT(system_driver); if (system_driver->yield_timeslice) system_driver->yield_timeslice(); return; } if (timer_driver) { if (timer_driver->rest) { timer_driver->rest(time, callback); } else { rest_count = time; if (install_int(rest_int, 1) < 0) return; do { if (callback) callback(); else rest(0); } while (rest_count > 0); remove_int(rest_int); } } else { time = clock() + MIN(time * CLOCKS_PER_SEC / 1000, 2); do { rest(0); } while (clock() < (clock_t)time); } } /* rest: * Waits for time milliseconds. */ void rest(unsigned int time) { rest_callback(time, NULL); } /* timer_can_simulate_retrace: [deprecated but used internally] * Checks whether the current driver is capable of a video retrace * syncing mode. */ int timer_can_simulate_retrace(void) { if ((timer_driver) && (timer_driver->can_simulate_retrace)) return timer_driver->can_simulate_retrace(); else return FALSE; } /* timer_simulate_retrace: [deprecated but used internally] * Turns retrace simulation on or off, and if turning it on, calibrates * the retrace timer. */ void timer_simulate_retrace(int enable) { if (!timer_can_simulate_retrace()) return; timer_driver->simulate_retrace(enable); } /* timer_is_using_retrace: [deprecated] * Tells the user whether the current driver is providing a retrace * sync. */ int timer_is_using_retrace(void) { return _timer_use_retrace; } /* find_timer_slot: * Searches the list of user timer callbacks for a specified function, * returning the position at which it was found, or -1 if it isn't there. */ static int find_timer_slot(void (*proc)(void)) { int x; for (x=0; xinstall_param_int) return timer_driver->install_param_int((void (*)(void *))proc, param, speed); x = find_param_timer_slot((void (*)(void *))proc, param); } else { if (timer_driver->install_int) return timer_driver->install_int((void (*)(void))proc, speed); x = find_timer_slot((void (*)(void))proc); } if (x < 0) x = find_empty_timer_slot(); if (x < 0) return -1; #ifdef ALLEGRO_MULTITHREADED system_driver->lock_mutex(timer_mutex); #endif if ((proc == _timer_queue[x].proc) || (proc == _timer_queue[x].param_proc)) { _timer_queue[x].counter -= _timer_queue[x].speed; _timer_queue[x].counter += speed; } else { _timer_queue[x].counter = speed; if (param_used) { _timer_queue[x].param = param; _timer_queue[x].param_proc = proc; } else _timer_queue[x].proc = proc; } _timer_queue[x].speed = speed; #ifdef ALLEGRO_MULTITHREADED system_driver->unlock_mutex(timer_mutex); #endif return 0; } END_OF_STATIC_FUNCTION(install_timer_int); /* install_int: * Wrapper for install_timer_int, which takes the speed in milliseconds, * no paramater. */ int install_int(void (*proc)(void), long speed) { return install_timer_int((void *)proc, NULL, MSEC_TO_TIMER(speed), FALSE); } END_OF_FUNCTION(install_int); /* install_int_ex: * Wrapper for install_timer_int, which takes the speed in timer ticks, * no paramater. */ int install_int_ex(void (*proc)(void), long speed) { return install_timer_int((void *)proc, NULL, speed, FALSE); } END_OF_FUNCTION(install_int_ex); /* install_param_int: * Wrapper for install_timer_int, which takes the speed in milliseconds, * with paramater. */ int install_param_int(void (*proc)(void *param), void *param, long speed) { return install_timer_int((void *)proc, param, MSEC_TO_TIMER(speed), TRUE); } END_OF_FUNCTION(install_param_int); /* install_param_int_ex: * Wrapper for install_timer_int, which takes the speed in timer ticks, * no paramater. */ int install_param_int_ex(void (*proc)(void *param), void *param, long speed) { return install_timer_int((void *)proc, param, speed, TRUE); } END_OF_FUNCTION(install_param_int_ex); /* remove_timer_int: * Removes a function from the list of user timers. */ static void remove_timer_int(void *proc, void *param, int param_used) { int x; if (param_used) { if ((timer_driver) && (timer_driver->remove_param_int)) { timer_driver->remove_param_int((void (*)(void *))proc, param); return; } x = find_param_timer_slot((void (*)(void *))proc, param); } else { if ((timer_driver) && (timer_driver->remove_int)) { timer_driver->remove_int((void (*)(void))proc); return; } x = find_timer_slot((void (*)(void))proc); } if (x < 0) return; #ifdef ALLEGRO_MULTITHREADED system_driver->lock_mutex(timer_mutex); #endif _timer_queue[x].proc = NULL; _timer_queue[x].param_proc = NULL; _timer_queue[x].param = NULL; _timer_queue[x].speed = 0; _timer_queue[x].counter = 0; #ifdef ALLEGRO_MULTITHREADED system_driver->unlock_mutex(timer_mutex); #endif } END_OF_FUNCTION(remove_timer_int); /* remove_int: * Wrapper for remove_timer_int, without parameters. */ void remove_int(void (*proc)(void)) { remove_timer_int((void *)proc, NULL, FALSE); } END_OF_FUNCTION(remove_int); /* remove_param_int: * Wrapper for remove_timer_int, with parameters. */ void remove_param_int(void (*proc)(void *param), void *param) { remove_timer_int((void *)proc, param, TRUE); } END_OF_FUNCTION(remove_param_int); /* clear_timer_queue: * Clears the timer queue. */ static void clear_timer_queue(void) { int i; for (i=0; itimer_drivers) driver_list = system_driver->timer_drivers(); else driver_list = _timer_driver_list; #ifdef ALLEGRO_MULTITHREADED timer_mutex = system_driver->create_mutex(); if (!timer_mutex) return -1; #endif for (i=0; driver_list[i].driver; i++) { timer_driver = driver_list[i].driver; timer_driver->name = timer_driver->desc = get_config_text(timer_driver->ascii_name); if (timer_driver->init() == 0) break; } if (!driver_list[i].driver) { #ifdef ALLEGRO_MULTITHREADED system_driver->destroy_mutex(timer_mutex); timer_mutex = NULL; #endif timer_driver = NULL; return -1; } _add_exit_func(remove_timer, "remove_timer"); _timer_installed = TRUE; return 0; } /* remove_timer: * Removes our timer handler and resets the BIOS clock. You don't normally * need to call this, because allegro_exit() will do it for you. */ void remove_timer(void) { if (!timer_driver) return; _timer_use_retrace = FALSE; timer_driver->exit(); timer_driver = NULL; #ifdef ALLEGRO_MULTITHREADED system_driver->destroy_mutex(timer_mutex); timer_mutex = NULL; #endif /* make sure subsequent remove_int() calls don't crash */ clear_timer_queue(); _remove_exit_func(remove_timer); _timer_installed = FALSE; } allegro-4.4.3.1/src/vtable24.c0000664000175000017500000000462113437077643014661 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Table of functions for drawing onto 24 bit linear bitmaps. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_COLOR24 void _linear_draw_sprite24_end(void); void _linear_blit24_end(void); GFX_VTABLE __linear_vtable24 = { 24, MASK_COLOR_24, _stub_unbank_switch, NULL, NULL, NULL, NULL, NULL, _linear_getpixel24, _linear_putpixel24, _linear_vline24, _linear_hline24, _linear_hline24, _normal_line, _fast_line, _normal_rectfill, _soft_triangle, _linear_draw_sprite24, _linear_draw_256_sprite24, _linear_draw_sprite_v_flip24, _linear_draw_sprite_h_flip24, _linear_draw_sprite_vh_flip24, _linear_draw_trans_sprite24, _linear_draw_trans_rgba_sprite24, _linear_draw_lit_sprite24, _linear_draw_rle_sprite24, _linear_draw_trans_rle_sprite24, _linear_draw_trans_rgba_rle_sprite24, _linear_draw_lit_rle_sprite24, _linear_draw_character24, _linear_draw_glyph24, _linear_blit24, _linear_blit24, _linear_blit24, _linear_blit24, _linear_blit24, _linear_blit24, _linear_blit_backward24, _blit_between_formats, _linear_masked_blit24, _linear_clear_to_color24, _pivot_scaled_sprite_flip, NULL, // AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)) _soft_draw_gouraud_sprite, _linear_draw_sprite24_end, _linear_blit24_end, _soft_polygon, _soft_rect, _soft_circle, _soft_circlefill, _soft_ellipse, _soft_ellipsefill, _soft_arc, _soft_spline, _soft_floodfill, _soft_polygon3d, _soft_polygon3d_f, _soft_triangle3d, _soft_triangle3d_f, _soft_quad3d, _soft_quad3d_f, _linear_draw_sprite_ex24 }; #endif allegro-4.4.3.1/src/misc/0000775000175000017500000000000013437077643014022 5ustar siegesiegeallegro-4.4.3.1/src/misc/vga.c0000664000175000017500000002143413437077643014747 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video driver for VGA mode 13h (320x200x256). * * By Shawn Hargreaves. * * 320x100 mode contributed by Salvador Eduardo Tropea. * * 80x80 mode contributed by Pedro Cardoso. * * See readme.txt for copyright information. */ #include #include "allegro.h" #ifdef ALLEGRO_GFX_HAS_VGA #include "allegro/internal/aintern.h" #include "allegro/internal/aintvga.h" #ifdef ALLEGRO_INTERNAL_HEADER #include ALLEGRO_INTERNAL_HEADER #endif #if (!defined ALLEGRO_LINUX) || ((defined ALLEGRO_LINUX_VGA) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))) static BITMAP *vga_init(int w, int h, int v_w, int v_h, int color_depth); static void vga_exit(BITMAP *b); static int vga_scroll(int x, int y); static GFX_MODE_LIST *vga_fetch_mode_list(void); GFX_DRIVER gfx_vga = { GFX_VGA, empty_string, empty_string, "Standard VGA", vga_init, vga_exit, NULL, _vga_vsync, _vga_set_palette_range, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ _save_vga_mode, _restore_vga_mode, NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ vga_fetch_mode_list, 320, 200, TRUE, 0, 0, 0x10000, 0, FALSE }; static GFX_MODE vga_gfx_modes[] = { { 80, 80, 8 }, { 160, 120, 8 }, { 256, 256, 8 }, { 320, 100, 8 }, { 320, 200, 8 }, { 0, 0, 0 } }; /* vga_init: * Selects mode 13h and creates a screen bitmap for it. */ static BITMAP *vga_init(int w, int h, int v_w, int v_h, int color_depth) { unsigned long addr; BITMAP *b; int c; /* check it is a valid resolution */ if (color_depth != 8) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VGA only supports 8 bit color")); return NULL; } /* for setting GFX_SAFE */ if ((!w) && (!h)) { w = 320; h = 200; } if ((w == 320) && (h == 200) && (v_w <= 320) && (v_h <= 200)) { /* standard mode 13h */ addr = _set_vga_mode(0x13); if (!addr) return NULL; b = _make_bitmap(320, 200, addr, &gfx_vga, 8, 320); if (!b) return NULL; gfx_vga.scroll = NULL; gfx_vga.w = 320; gfx_vga.h = 200; } else if ((w == 320) && (h == 100) && (v_w <= 320) && (v_h <= 200)) { /* tweaked 320x100 mode */ addr = _set_vga_mode(0x13); if (!addr) return NULL; b = _make_bitmap(320, 200, addr, &gfx_vga, 8, 320); if (!b) return NULL; outportb(0x3D4, 9); outportb(0x3D5, inportb(0x3D5) | 0x80); gfx_vga.scroll = vga_scroll; gfx_vga.w = 320; gfx_vga.h = 100; } else if ((w == 256) && (h == 256) && (v_w <= 256) && (v_h <= 256)) { /* tweaked 256x256 mode */ addr = _set_vga_mode(0x13); if (!addr) return NULL; b = _make_bitmap(256, 256, addr, &gfx_vga, 8, 256); if (!b) return NULL; outportb(0x3D4, 0x11); c = inportb(0x3D5) & 0x7F; outportb(0x3D4, (c << 8) | 0x11); outportb(0x3D5, c); outportb(0x3C2, 0xE3); outportw(0x3D4, 0x5F00); outportw(0x3D4, 0x3F01); outportw(0x3D4, 0x4002); outportw(0x3D4, 0x8203); outportw(0x3D4, 0x4A04); outportw(0x3D4, 0x9A05); outportw(0x3D4, 0x2306); outportw(0x3D4, 0xB207); outportw(0x3D4, 0x0008); outportw(0x3D4, 0x6109); outportw(0x3D4, 0x0A10); outportw(0x3D4, 0xAC11); outportw(0x3D4, 0xFF12); outportw(0x3D4, 0x2013); outportw(0x3D4, 0x4014); outportw(0x3D4, 0x0715); outportw(0x3D4, 0x1A16); outportw(0x3D4, 0xA317); outportw(0x3C4, 0x0101); outportw(0x3C4, 0x0E04); outportw(0x3CE, 0x4005); outportw(0x3CE, 0x0506); inportb(0x3DA); outportb(0x3C0, 0x30); outportb(0x3C0, 0x41); inportb(0x3DA); outportb(0x3C0, 0x33); outportb(0x3C0, 0x00); outportb(0x3C6, 0xFF); gfx_vga.scroll = NULL; gfx_vga.w = 256; gfx_vga.h = 256; } else if ((w == 160) && (h == 120) && (v_w <= 160) && (v_h <= 409)) { /* tweaked 160x120 mode */ addr = _set_vga_mode(0x0D); if (!addr) return NULL; b = _make_bitmap(160, 409, addr, &gfx_vga, 8, 160); if (!b) return NULL; outportb(0x3D4, 0x11); outportb(0x3D5, inportb(0x3D5)&0x7F); outportb(0x3D4, 0x04); outportb(0x3D5, inportb(0x3D5)+1); outportb(0x3D4, 0x11); outportb(0x3D5, inportb(0x3D5)|0x80); outportb(0x3C2, (inportb(0x3CC)&~0xC0)|0x80); outportb(0x3D4, 0x11); outportb(0x3D5, inportb(0x3D5)&0x7F); outportb(0x3D4, 0x06); outportb(0x3D5, 0x0B); outportb(0x3D4, 0x07); outportb(0x3D5, 0x3E); outportb(0x3D4, 0x10); outportb(0x3D5, 0xEA); outportb(0x3D4, 0x11); outportb(0x3D5, 0x8C); outportb(0x3D4, 0x12); outportb(0x3D5, 0xDF); outportb(0x3D4, 0x15); outportb(0x3D5, 0xE7); outportb(0x3D4, 0x16); outportb(0x3D5, 0x04); outportb(0x3D4, 0x11); outportb(0x3D5, inportb(0x3D5)|0x80); outportb(0x3CE, 0x05); outportb(0x3CF, (inportb(0x3CF)&0x60)|0x40); inportb(0x3DA); outportb(0x3C0, 0x30); outportb(0x3C0, inportb(0x3C1)|0x40); for (c=0; c<16; c++) { outportb(0x3C0, c); outportb(0x3C0, c); } outportb(0x3C0, 0x20); outportb(0x3C8, 0x00); outportb(0x3C4, 0x04); outportb(0x3C5, (inportb(0x3C5)&0xF7)|8); outportb(0x3D4, 0x14); outportb(0x3D5, (inportb(0x3D5)&~0x40)|64); outportb(0x3D4, 0x017); outportb(0x3D5, (inportb(0x3D5)&~0x40)|64); outportb(0x3D4, 0x09); outportb(0x3D5, (inportb(0x3D5)&0x60)|3); gfx_vga.scroll = vga_scroll; gfx_vga.w = 160; gfx_vga.h = 120; } else if ((w == 80) && (h == 80) && (v_w <= 80) && (v_h <= 819)) { /* tweaked 80x80 mode */ addr = _set_vga_mode(0x13); if (!addr) return NULL; b = _make_bitmap(80, 819, addr, &gfx_vga, 8, 80); if (!b) return NULL; outportw(0x3C4, 0x0604); outportw(0x3C4, 0x0F02); outportw(0x3D4, 0x0014); outportw(0x3D4, 0xE317); outportw(0x3D4, 0xE317); outportw(0x3D4, 0x0409); gfx_vga.scroll = vga_scroll; gfx_vga.w = 80; gfx_vga.h = 80; } else { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not a valid VGA resolution")); return NULL; } #ifdef ALLEGRO_LINUX b->vtable->acquire = __al_linux_acquire_bitmap; b->vtable->release = __al_linux_release_bitmap; #endif return b; } /* vga_exit: * Unsets the video mode. */ static void vga_exit(BITMAP *b) { _unset_vga_mode(); } /* vga_scroll: * Hardware scrolling routine for standard VGA modes. */ static int vga_scroll(int x, int y) { long a = (x + (y * VIRTUAL_W)); if (gfx_vga.w > 80) a /= 4; DISABLE(); if (_wait_for_vsync) _vsync_out_h(); /* write to VGA address registers */ _write_vga_register(_crtc, 0x0D, a & 0xFF); _write_vga_register(_crtc, 0x0C, (a>>8) & 0xFF); ENABLE(); if (_wait_for_vsync) _vsync_in(); return 0; } /* vga_fetch_mode_list: * Creates a list of of currently implemented VGA modes. */ static GFX_MODE_LIST *vga_fetch_mode_list(void) { GFX_MODE_LIST *mode_list; mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) return NULL; mode_list->mode = _AL_MALLOC(sizeof(vga_gfx_modes)); if (!mode_list->mode) return NULL; memcpy(mode_list->mode, vga_gfx_modes, sizeof(vga_gfx_modes)); mode_list->num_modes = sizeof(vga_gfx_modes) / sizeof(GFX_MODE) - 1; return mode_list; } #ifdef ALLEGRO_MODULE extern void _module_init_modex(int); /* from modex.c */ /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _module_init_modex(system_driver); if (system_driver == SYSTEM_LINUX) _unix_register_gfx_driver(GFX_VGA, &gfx_vga, TRUE, TRUE); } #endif /* ifdef ALLEGRO_MODULE */ #endif /* (!defined ALLEGRO_LINUX) || ((defined ALLEGRO_LINUX_VGA) && ...) */ #endif /* ifdef ALLEGRO_GFX_HAS_VGA */ allegro-4.4.3.1/src/misc/asmcapa.s0000664000175000017500000000022713437077643015614 0ustar siegesiege# source file for testing assembler capabilities .text .ifdef ASMCAPA_MMX_TEST emms .endif .ifdef ASMCAPA_SSE_TEST maskmovq %mm3, %mm1 .endif allegro-4.4.3.1/src/misc/vbeafex.c0000664000175000017500000006601213437077643015613 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper routines for the VBE/AF driver. This file is in charge of * filling in the libc and pmode function export structures used by * the FreeBE/AF extensions, which is mainly needed for compatibility * with the SciTech Nucleus drivers (see the comments at at the top * of vbeaf.c). * * This file is based on the SciTech PM/Lite library API. * * Someday this might want to work on Linux, which is why it lives * in the misc directory, but it isn't going to be much fun trying * to make that happen :-) * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #ifdef ALLEGRO_INTERNAL_HEADER #include ALLEGRO_INTERNAL_HEADER #endif #ifndef SCAN_DEPEND #ifdef ALLEGRO_DOS #include #include #endif #ifdef ALLEGRO_DJGPP #include #include #endif #endif #define BUFFER_SIZE 256 /* FAFEXT_LIBC extension structure */ typedef struct LIBC_DATA { long size; void (*abort)(void); void *(*calloc)(unsigned long num_elements, unsigned long size); void (*exit)(int status); void (*free)(void *ptr); char *(*getenv)(const char *name); void *(*malloc)(unsigned long size); void *(*realloc)(void *ptr, unsigned long size); int (*system)(const char *s); int (*putenv)(const char *val); int (*open)(const char *file, int mode, ...); int (*access)(const char *filename, int flags); int (*close)(int fd); int (*lseek)(int fd, int offset, int whence); int (*read)(int fd, void *buffer, unsigned long count); int (*unlink)(const char *file); int (*write)(int fd, const void *buffer, unsigned long count); int (*isatty)(int fd); int (*remove)(const char *file); int (*rename)(const char *oldname, const char *newname); unsigned int (*time)(unsigned int *t); void (*setfileattr)(const char *filename, unsigned attrib); unsigned long (*getcurrentdate)(void); } LIBC_DATA; /* setfileattr: * Export function for modifying DOS file attributes. */ static void setfileattr(const char *filename, unsigned attrib) { _dos_setfileattr(filename, attrib); } /* getcurrentdate: * Export function for checking the current date. Returns the number of * days since 1/1/1980. */ static unsigned long getcurrentdate(void) { unsigned long t = time(NULL); /* this calculation _might_ be right, but somehow I doubt it :=) */ t /= (24*60*60); /* convert from seconds to days */ t -= (365*10); /* convert from 1970 origin to 1980 */ t -= 2; /* adjust for leap years in 1972 and 1976 */ return t; } /* _fill_vbeaf_libc_exports: * Provides libc function exports for the FAFEXT_LIBC extension. */ void _fill_vbeaf_libc_exports(void *ptr) { LIBC_DATA *lc = (LIBC_DATA *)ptr; #define FILL_LIBC(field, func) \ { \ if ((long)offsetof(LIBC_DATA, field) < lc->size) \ lc->field = (void *)func; \ } FILL_LIBC(abort, abort); FILL_LIBC(calloc, calloc); FILL_LIBC(exit, exit); FILL_LIBC(free, free); FILL_LIBC(getenv, getenv); FILL_LIBC(malloc, malloc); FILL_LIBC(realloc, realloc); FILL_LIBC(system, system); FILL_LIBC(putenv, putenv); FILL_LIBC(open, open); FILL_LIBC(access, access); FILL_LIBC(close, close); FILL_LIBC(lseek, lseek); FILL_LIBC(read, read); FILL_LIBC(unlink, unlink); FILL_LIBC(write, write); FILL_LIBC(isatty, isatty); FILL_LIBC(remove, remove); FILL_LIBC(rename, rename); FILL_LIBC(time, time); FILL_LIBC(setfileattr, setfileattr); FILL_LIBC(getcurrentdate, getcurrentdate); } /* This pmode export structure basically provides the SciTech pmode * library API, which is required by their Nucleus drivers. Why oh why * is there so !"$%^ much of it? They don't need nearly so many callbacks * just to write a simple video driver, and I resent being made to include * all this code just to use their drivers... */ typedef union { struct { unsigned long eax, ebx, ecx, edx, esi, edi, cflag; } e; struct { unsigned short ax, ax_hi; unsigned short bx, bx_hi; unsigned short cx, cx_hi; unsigned short dx, dx_hi; unsigned short si, si_hi; unsigned short di, di_hi; unsigned short cflag, cflag_hi; } x; struct { unsigned char al, ah; unsigned short ax_hi; unsigned char bl, bh; unsigned short bx_hi; unsigned char cl, ch; unsigned short cx_hi; unsigned char dl, dh; unsigned short dx_hi; } h; } SCITECH_REGS; typedef struct { unsigned short es, cs, ss, ds, fs, gs; } SCITECH_SREGS; /* FAFEXT_PMODE extension structure */ typedef struct PMODE_DATA { long size; int (*getModeType)(void); void *(*getBIOSPointer)(void); void *(*getA0000Pointer)(void); void *(*mapPhysicalAddr)(unsigned long base, unsigned long limit); void *(*mallocShared)(long size); int (*mapShared)(void *ptr); void (*freeShared)(void *ptr); void *(*mapToProcess)(void *linear, unsigned long limit); void (*loadDS)(void); void (*saveDS)(void); void *(*mapRealPointer)(unsigned int r_seg, unsigned int r_off); void *(*allocRealSeg)(unsigned int size, unsigned int *r_seg, unsigned int *r_off); void (*freeRealSeg)(void *mem); void *(*allocLockedMem)(unsigned int size, unsigned long *physAddr); void (*freeLockedMem)(void *p); void (*callRealMode)(unsigned int seg, unsigned int off, SCITECH_REGS *regs, SCITECH_SREGS *sregs); int (*int86)(int intno, SCITECH_REGS *in, SCITECH_REGS *out); int (*int86x)(int intno, SCITECH_REGS *in, SCITECH_REGS *out, SCITECH_SREGS *sregs); void (*DPMI_int86)(int intno, __dpmi_regs *regs); void (*segread)(SCITECH_SREGS *sregs); int (*int386)(int intno, SCITECH_REGS *in, SCITECH_REGS *out); int (*int386x)(int intno, SCITECH_REGS *in, SCITECH_REGS *out, SCITECH_SREGS *sregs); void (*availableMemory)(unsigned long *physical, unsigned long *total); void *(*getVESABuf)(unsigned int *len, unsigned int *rseg, unsigned int *roff); long (*getOSType)(void); void (*fatalError)(const char *msg); void (*setBankA)(int bank); void (*setBankAB)(int bank); const char *(*getCurrentPath)(void); const char *(*getVBEAFPath)(void); const char *(*getNucleusPath)(void); const char *(*getNucleusConfigPath)(void); const char *(*getUniqueID)(void); const char *(*getMachineName)(void); int (*VF_available)(void); void *(*VF_init)(unsigned long baseAddr, int bankSize, int codeLen, void *bankFunc); void (*VF_exit)(void); int (*kbhit)(void); int (*getch)(void); int (*openConsole)(void); int (*getConsoleStateSize)(void); void (*saveConsoleState)(void *stateBuf, int console_id); void (*restoreConsoleState)(const void *stateBuf, int console_id); void (*closeConsole)(int console_id); void (*setOSCursorLocation)(int x, int y); void (*setOSScreenWidth)(int width, int height); int (*enableWriteCombine)(unsigned long base, unsigned long length); void (*backslash)(char *filename); } PMODE_DATA; /* get_mode_type: * Return that we are running in 386 mode. */ static int get_mode_type(void) { return 2; /* 0=real mode, 1=16 bit pmode, 2=32 bit pmode */ } /* get_bios_pointer: * Returns a pointer to the BIOS data area at segment 0x400. */ static void *get_bios_pointer(void) { if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) if (__djgpp_nearptr_enable() == 0) return NULL; return (void *)(__djgpp_conventional_base + 0x400); } /* get_a0000_pointer: * Returns a linear pointer to the VGA frame buffer memory. */ static void *get_a0000_pointer(void) { if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) if (__djgpp_nearptr_enable() == 0) return NULL; return (void *)(__djgpp_conventional_base + 0xA0000); } /* map_physical_addr: * Maps physical memory into the current DS segment. */ static void *map_physical_addr(unsigned long base, unsigned long limit) { unsigned long linear; if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) if (__djgpp_nearptr_enable() == 0) return NULL; if (_create_linear_mapping(&linear, base, limit) != 0) return NULL; return (void *)(__djgpp_conventional_base + linear); } /* malloc_shared: * Allocates a memory block in the global shared region. */ static void *malloc_shared(long size) { return _AL_MALLOC(size); } /* map_shared: * Maps a shared memory block into the current process. */ static int map_shared(void *ptr) { return 0; } /* free_shared: * Frees the allocated shared memory block. */ static void free_shared(void *ptr) { _AL_FREE(ptr); } /* map_to_process: * Attaches a previously allocated linear mapping to a new process. */ static void *map_to_process(void *linear, unsigned long limit) { return linear; } /* for the save_ds() / load_ds() functions */ static unsigned short saved_ds = 0; /* save_ds: * Saves the current data segment selector into a code segment variable. */ static void save_ds(void) { saved_ds = _default_ds(); } /* load_ds: * Restores a data segment selector previously stored by save_ds(). */ static void load_ds(void) { #ifdef ALLEGRO_GCC /* use gcc-style inline asm */ asm ( " movw %%cs:_saved_ds, %%ax ; " " movw %%ax, %%ds " : : : "%eax" ); #elif defined ALLEGRO_WATCOM /* use Watcom-style inline asm */ { int _ds(void); #pragma aux _ds = \ " mov ax, cs:saved_ds " \ " mov ds, ax " \ \ modify [eax]; _ds(); } #endif } /* map_real_pointer: * Maps a real mode pointer into our address space. */ static void *map_real_pointer(unsigned int r_seg, unsigned int r_off) { if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) if (__djgpp_nearptr_enable() == 0) return NULL; return (void *)(__djgpp_conventional_base + (r_seg<<4) + r_off); } /* cache so we know how to free real mode memory blocks */ static struct { void *ptr; int sel; } rm_blocks[] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 }, { NULL, 0 } }; /* alloc_real_seg: * Allocates a block of conventional memory. */ static void *alloc_real_seg(unsigned int size, unsigned int *r_seg, unsigned int *r_off) { int seg, sel, i; void *ptr; seg = __dpmi_allocate_dos_memory((size+15)>>4, &sel); if (seg < 0) return NULL; *r_seg = seg; *r_off = 0; ptr = map_real_pointer(seg, 0); for (i=0; i<(int)(sizeof(rm_blocks)/sizeof(rm_blocks[0])); i++) { if (!rm_blocks[i].ptr) { rm_blocks[i].ptr = ptr; rm_blocks[i].sel = sel; break; } } return ptr; } /* free_real_seg: * Frees a block of conventional memory. */ static void free_real_seg(void *mem) { int i; for (i=0; i<(int)(sizeof(rm_blocks)/sizeof(rm_blocks[0])); i++) { if (rm_blocks[i].ptr == mem) { __dpmi_free_dos_memory(rm_blocks[i].sel); rm_blocks[i].ptr = NULL; rm_blocks[i].sel = 0; break; } } } /* alloc_locked_mem: * Allocates a block of locked memory. */ static void *alloc_locked_mem(unsigned int size, unsigned long *physAddr) { return NULL; } /* free_locked_mem: * Frees a block of locked memory. */ static void free_locked_mem(void *p) { } /* call_real_mode: * Calls a real mode asm procedure. */ static void call_real_mode(unsigned int seg, unsigned int off, SCITECH_REGS *regs, SCITECH_SREGS *sregs) { __dpmi_regs r; memset(&r, 0, sizeof(r)); r.d.eax = regs->e.eax; r.d.ebx = regs->e.ebx; r.d.ecx = regs->e.ecx; r.d.edx = regs->e.edx; r.d.esi = regs->e.esi; r.d.edi = regs->e.edi; r.x.ds = sregs->ds; r.x.es = sregs->es; r.x.cs = seg; r.x.ip = off; __dpmi_simulate_real_mode_procedure_retf(&r); regs->e.eax = r.d.eax; regs->e.ebx = r.d.ebx; regs->e.ecx = r.d.ecx; regs->e.edx = r.d.edx; regs->e.esi = r.d.esi; regs->e.edi = r.d.edi; sregs->cs = r.x.cs; sregs->ds = r.x.ds; sregs->es = r.x.es; sregs->ss = r.x.ss; regs->x.cflag = (r.x.flags & 1); } /* my_int86: * Generates a real mode interrupt. */ static int my_int86(int intno, SCITECH_REGS *in, SCITECH_REGS *out) { __dpmi_regs r; memset(&r, 0, sizeof(r)); r.d.eax = in->e.eax; r.d.ebx = in->e.ebx; r.d.ecx = in->e.ecx; r.d.edx = in->e.edx; r.d.esi = in->e.esi; r.d.edi = in->e.edi; __dpmi_simulate_real_mode_interrupt(intno, &r); out->e.eax = r.d.eax; out->e.ebx = r.d.ebx; out->e.ecx = r.d.ecx; out->e.edx = r.d.edx; out->e.esi = r.d.esi; out->e.edi = r.d.edi; out->x.cflag = (r.x.flags & 1); return out->x.ax; } /* my_int86x: * Generates a real mode interrupt. */ static int my_int86x(int intno, SCITECH_REGS *in, SCITECH_REGS *out, SCITECH_SREGS *sregs) { __dpmi_regs r; memset(&r, 0, sizeof(r)); r.d.eax = in->e.eax; r.d.ebx = in->e.ebx; r.d.ecx = in->e.ecx; r.d.edx = in->e.edx; r.d.esi = in->e.esi; r.d.edi = in->e.edi; r.x.ds = sregs->ds; r.x.es = sregs->es; __dpmi_simulate_real_mode_interrupt(intno, &r); out->e.eax = r.d.eax; out->e.ebx = r.d.ebx; out->e.ecx = r.d.ecx; out->e.edx = r.d.edx; out->e.esi = r.d.esi; out->e.edi = r.d.edi; sregs->cs = r.x.cs; sregs->ds = r.x.ds; sregs->es = r.x.es; sregs->ss = r.x.ss; out->x.cflag = (r.x.flags & 1); return out->x.ax; } /* dpmi_int86: * Generates a real mode interrupt. */ static void dpmi_int86(int intno, __dpmi_regs *regs) { __dpmi_simulate_real_mode_interrupt(intno, regs); } /* my_segread: * Reads the current selector values. */ static void my_segread(SCITECH_SREGS *sregs) { #ifdef ALLEGRO_GCC /* use gcc-style inline asm */ asm ( " movw %%cs, %w0 ; " " movw %%ds, %w1 ; " " movw %%es, %w2 ; " " movw %%fs, %w3 ; " " movw %%gs, %w4 ; " " movw %%ss, %w5 ; " : "=m" (sregs->cs), "=m" (sregs->ds), "=m" (sregs->es), "=m" (sregs->fs), "=m" (sregs->gs), "=m" (sregs->ss) ); #elif defined WATCOM segread((struct SREGS *)sregs); #endif } #ifdef ALLEGRO_GCC /* gcc version of my_int386x() */ /* code fragment for issuing interrupt calls */ #define INT(n) \ { \ 0xCD, /* int */ \ n, \ 0xC3, /* ret */ \ } #define INTROW(n) \ INT(n+0x00), INT(n+0x01), INT(n+0x02), INT(n+0x03), \ INT(n+0x04), INT(n+0x05), INT(n+0x06), INT(n+0x07), \ INT(n+0x08), INT(n+0x09), INT(n+0x0A), INT(n+0x0B), \ INT(n+0x0C), INT(n+0x0D), INT(n+0x0E), INT(n+0x0F) static unsigned char asm_int_code[256][3] = { INTROW(0x00), INTROW(0x10), INTROW(0x20), INTROW(0x30), INTROW(0x40), INTROW(0x50), INTROW(0x60), INTROW(0x70), INTROW(0x80), INTROW(0x90), INTROW(0xA0), INTROW(0xB0), INTROW(0xC0), INTROW(0xD0), INTROW(0xE0), INTROW(0xF0) }; #undef INT #undef INTROW /* temporary global for storing the data selector * FIXME: this is supposed to be static but that doesn't work with the * following asm code with gcc 4 */ int __al_vbeafex_int_ds; /* my_int386x: * Generates a protected mode interrupt (gcc version). */ static int my_int386x(int intno, SCITECH_REGS *in, SCITECH_REGS *out, SCITECH_SREGS *sregs) { asm ( " pushal ; " /* push lots of stuff */ " pushw %%es ; " " pushw %%fs ; " " pushw %%gs ; " " pushl %%esi ; " " pushl %%edx ; " " pushw %%ds ; " " pushl %%ecx ; " " movw (%%esi), %%es ; " /* load selectors */ " movw 6(%%esi), %%ax ; " " movw %%ax, ___al_vbeafex_int_ds ; " " movw 8(%%esi), %%fs ; " " movw 10(%%esi), %%gs ; " " movl (%%edi), %%eax ; " /* load registers */ " movl 4(%%edi), %%ebx ; " " movl 8(%%edi), %%ecx ; " " movl 12(%%edi), %%edx ; " " movl 16(%%edi), %%esi ; " " movl 20(%%edi), %%edi ; " " movw ___al_vbeafex_int_ds, %%ds ; " /* load %ds selector */ " clc ; " /* generate the interrupt */ " popl %%ebp ; " " call *%%ebp ; " " movw %%ds, %%ss:___al_vbeafex_int_ds ; " /* store returned %ds value */ " popw %%ds ; " /* restore original %ds */ " movl %%edi, %%ebp ; " /* store %edi */ " popl %%edi ; " /* pop output pointer into %edi */ " movl %%eax, (%%edi) ; " /* store output registers */ " movl %%ebx, 4(%%edi) ; " " movl %%ecx, 8(%%edi) ; " " movl %%edx, 12(%%edi) ; " " movl %%esi, 16(%%edi) ; " " movl %%ebp, 20(%%edi) ; " " pushfl ; " /* store output carry flag */ " popl %%eax ; " " andl $1, %%eax ; " " movl %%eax, 24(%%edi) ; " " popl %%esi ; " /* pop sregs pointer into %esi */ " movw %%es, (%%esi) ; " /* store output selectors */ " movw ___al_vbeafex_int_ds, %%ax ; " " movw %%ax, 6(%%esi) ; " " movw %%fs, 8(%%esi) ; " " movw %%gs, 10(%%esi) ; " " popw %%gs ; " /* pop remaining values */ " popw %%fs ; " " popw %%es ; " " popal ; " : /* no outputs */ : "S" (sregs), /* sregs in %esi */ "D" (in), /* in pointer in %edi */ "d" (out), /* out pointer in %edx */ "c" (asm_int_code[intno]) /* function pointer in %ecx */ ); return out->e.eax; } #elif defined ALLEGRO_WATCOM /* my_int386x: * Generates a protected mode interrupt (Watcom version). */ static int my_int386x(int intno, SCITECH_REGS *in, SCITECH_REGS *out, SCITECH_SREGS *sregs) { return int386x(intno, (union REGS *)in, (union REGS *)out, (struct SREGS *)sregs); } #endif /* gcc vs. Watcom */ /* my_int386: * Generates a protected mode interrupt. */ static int my_int386(int intno, SCITECH_REGS *in, SCITECH_REGS *out) { SCITECH_SREGS sregs; my_segread(&sregs); return my_int386x(intno, in, out, &sregs); } /* available_memory: * Returns the amount of available free memory. */ static void available_memory(unsigned long *physical, unsigned long *total) { __dpmi_free_mem_info info; __dpmi_get_free_memory_information(&info); *physical = info.total_number_of_free_pages * 4096; *total = info.largest_available_free_block_in_bytes; if (*total < *physical) *physical = *total; } /* conventional memory buffer for communicating with VESA */ static void *vesa_ptr = NULL; /* free_vesa_buf: * Cleanup routine. */ static void free_vesa_buf(void) { if (vesa_ptr) { free_real_seg(vesa_ptr); vesa_ptr = NULL; } } /* get_vesa_buf: * Returns the address of a global VESA real mode transfer buffer. */ static void *get_vesa_buf(unsigned int *len, unsigned int *rseg, unsigned int *roff) { static unsigned int seg, off; if (!vesa_ptr) { vesa_ptr = alloc_real_seg(2048, &seg, &off); if (!vesa_ptr) return NULL; atexit(free_vesa_buf); } *len = 2048; *rseg = seg; *roff = off; return vesa_ptr; } /* get_os_type: * Returns the OS type flag. */ static long get_os_type(void) { return 1; /* _OS_DOS */ } /* fatal_error: * Handles a fatal error condition. */ static void fatal_error(const char *msg) { fprintf(stderr, "%s\n", msg); fflush(stderr); exit(1); } /* set_banka: * Sets a VBE bank using int 0x10. */ static void set_banka(int bank) { __dpmi_regs r; r.x.ax = 0x4F05; r.x.bx = 0; r.x.dx = bank; __dpmi_int(0x10, &r); } /* set_bankab: * Sets both VBE banks using int 0x10. */ static void set_bankab(int bank) { __dpmi_regs r; r.x.ax = 0x4F05; r.x.bx = 0; r.x.dx = bank; __dpmi_int(0x10, &r); r.x.ax = 0x4F05; r.x.bx = 1; r.x.dx = bank; __dpmi_int(0x10, &r); } /* get_current_path: * Returns the current working directory. */ static const char *get_current_path(void) { static char *buffer = NULL; if (!buffer) buffer = _AL_MALLOC(BUFFER_SIZE); getcwd(buffer, BUFFER_SIZE-1); return buffer; } /* get_vbeaf_path: * Returns the VBE/AF driver directory. */ static const char *get_vbeaf_path(void) { return "c:\\"; } /* get_nucleus_path: * Returns the Nucleus driver directory. */ static const char *get_nucleus_path(void) { static char *buffer = NULL; char *p; p = getenv("NUCLEUS_PATH"); if (p) return p; p = getenv("WINBOOTDIR"); if (p) { if (!buffer) buffer = _AL_MALLOC(BUFFER_SIZE); _al_sane_strncpy(buffer , p, BUFFER_SIZE); strncat(buffer, "\\nucleus", BUFFER_SIZE-1); return buffer; } return "c:\\nucleus"; } /* get_nucleus_config_path: * Returns the Nucleus config directory. */ static const char *get_nucleus_config_path(void) { static char *buffer = NULL; if (!buffer) buffer = _AL_MALLOC(BUFFER_SIZE); _al_sane_strncpy(buffer, get_nucleus_path(), BUFFER_SIZE); put_backslash(buffer); strncat(buffer, "config", BUFFER_SIZE-1); return buffer; } /* get_unique_id: * Returns a network unique machine identifier as a string. */ static const char *get_unique_id(void) { return "DOS"; } /* get_machine_name: * Returns the network machine name as a string. */ static const char *get_machine_name(void) { static char *buffer = NULL; if (!buffer) buffer = _AL_MALLOC(BUFFER_SIZE); #ifdef ALLEGRO_DJGPP gethostname(buffer, BUFFER_SIZE-1); #else _al_sane_strncpy(buffer, "pc", BUFFER_SIZE); #endif return buffer; } /* vf_available: * Checks whether the virtual framebuffer mode is avaliable (no, it isn't). */ static int vf_available(void) { return 0; } /* vf_init: * Initialises the virtual framebuffer mode. */ static void *vf_init(unsigned long baseAddr, int bankSize, int codeLen, void *bankFunc) { return NULL; } /* vf_exit: * Shuts down the virtual framebuffer mode. */ static void vf_exit(void) { } /* stored console state structure */ typedef struct { int mode; int tall; } CONSOLE_STATE; /* open_console: * Prepares the system for console output. */ static int open_console(void) { return 0; } /* get_console_state_size: * Returns the size of a console state buffer. */ static int get_console_state_size(void) { return sizeof(CONSOLE_STATE); } /* save_console_state: * Stores the current console status. */ static void save_console_state(void *stateBuf, int console_id) { CONSOLE_STATE *state = stateBuf; __dpmi_regs r; r.x.ax = 0x0F00; __dpmi_int(0x10, &r); state->mode = r.h.al & 0x7F; if (state->mode == 0x3) { r.x.ax = 0x1130; r.x.bx = 0; r.x.dx = 0; __dpmi_int(0x10, &r); state->tall = ((r.h.dl == 42) || (r.h.dl == 49)); } else state->tall = FALSE; } /* restore_console_state: * Restores a previously saved console status. */ static void restore_console_state(const void *stateBuf, int console_id) { const CONSOLE_STATE *state = stateBuf; __dpmi_regs r; if (state->tall) { r.x.ax = 0x1112; r.x.bx = 0; __dpmi_int(0x10, &r); } } /* close_console: * Shuts down the console mode. */ static void close_console(int console_id) { } /* set_os_cursor_location: * Positions the text mode cursor. */ static void set_os_cursor_location(int x, int y) { _farsetsel(_dos_ds); _farnspokeb(0x450, x); _farnspokeb(0x451, y); } /* set_os_screen_width: * Sets the console width. */ static void set_os_screen_width(int width, int height) { _farnspokeb(0x44A, width); _farnspokeb(0x484, height-1); } /* enable_write_combine: * Enables the Intel PPro/PII write combining. */ static int enable_write_combine(unsigned long base, unsigned long length) { return 0; } /* _fill_vbeaf_pmode_exports: * Provides pmode function exports for the FAFEXT_PMODE extension. */ void _fill_vbeaf_pmode_exports(void *ptr) { PMODE_DATA *pm = (PMODE_DATA *)ptr; #define FILL_PMODE(field, func) \ { \ if ((long)offsetof(PMODE_DATA, field) < pm->size) \ pm->field = func; \ } FILL_PMODE(getModeType, get_mode_type); FILL_PMODE(getBIOSPointer, get_bios_pointer); FILL_PMODE(getA0000Pointer, get_a0000_pointer); FILL_PMODE(mapPhysicalAddr, map_physical_addr); FILL_PMODE(mallocShared, malloc_shared); FILL_PMODE(mapShared, map_shared); FILL_PMODE(freeShared, free_shared); FILL_PMODE(mapToProcess, map_to_process); FILL_PMODE(loadDS, load_ds); FILL_PMODE(saveDS, save_ds); FILL_PMODE(mapRealPointer, map_real_pointer); FILL_PMODE(allocRealSeg, alloc_real_seg); FILL_PMODE(freeRealSeg, free_real_seg); FILL_PMODE(allocLockedMem, alloc_locked_mem); FILL_PMODE(freeLockedMem, free_locked_mem); FILL_PMODE(callRealMode, call_real_mode); FILL_PMODE(int86, my_int86); FILL_PMODE(int86x, my_int86x); FILL_PMODE(DPMI_int86, dpmi_int86); FILL_PMODE(segread, my_segread); FILL_PMODE(int386, my_int386); FILL_PMODE(int386x, my_int386x); FILL_PMODE(availableMemory, available_memory); FILL_PMODE(getVESABuf, get_vesa_buf); FILL_PMODE(getOSType, get_os_type); FILL_PMODE(fatalError, fatal_error); FILL_PMODE(setBankA, set_banka); FILL_PMODE(setBankAB, set_bankab); FILL_PMODE(getCurrentPath, get_current_path); FILL_PMODE(getVBEAFPath, get_vbeaf_path); FILL_PMODE(getNucleusPath, get_nucleus_path); FILL_PMODE(getNucleusConfigPath, get_nucleus_config_path); FILL_PMODE(getUniqueID, get_unique_id); FILL_PMODE(getMachineName, get_machine_name); FILL_PMODE(VF_available, vf_available); FILL_PMODE(VF_init, vf_init); FILL_PMODE(VF_exit, vf_exit); FILL_PMODE(kbhit, kbhit); FILL_PMODE(getch, getch); FILL_PMODE(openConsole, open_console); FILL_PMODE(getConsoleStateSize, get_console_state_size); FILL_PMODE(saveConsoleState, save_console_state); FILL_PMODE(restoreConsoleState, restore_console_state); FILL_PMODE(closeConsole, close_console); FILL_PMODE(setOSCursorLocation, set_os_cursor_location); FILL_PMODE(setOSScreenWidth, set_os_screen_width); FILL_PMODE(enableWriteCombine, enable_write_combine); FILL_PMODE(backslash, put_backslash); } allegro-4.4.3.1/src/misc/modexsms.c0000664000175000017500000000257513437077643016036 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Hack to handle split_modex_screen(). * * By Peter Wang. * * See readme.txt for copyright information. */ #include "allegro.h" #include "modexsms.h" #ifdef GFX_MODEX /* split_modex_screen() should be available whenever GFX_MODEX is defined, * but the ModeX driver itself either may not be available on the given * platform or may reside in a module. The right way to handle this would be * to add another method to the GFX_VTABLE, but in this case the method would * be useless for all other drivers. Also split_modex_screen() is going to * be removed soon anyway. Hence this hack: we set _split_modex_screen_ptr * to point to the real function when the ModeX driver is initialised and * unset it when it is shut down. */ void (*_split_modex_screen_ptr)(int); void split_modex_screen(int line) { if (_split_modex_screen_ptr) _split_modex_screen_ptr(line); } #endif allegro-4.4.3.1/src/misc/runner.c0000664000175000017500000000417313437077643015504 0ustar siegesiege/* * Silly little bodge for getting GNU make to pass long commands * to broken programs like the Microsoft and Watcom linkers. This * tool is built with gcc, and invoked using GNU make. It echoes * the arguments into a temporary file, and then passes that as a * script to the utility in question. Ugly, but it does the job. * An @ symbol marks that all commands from here on should go in * the argument file, and a \ character indicates to convert slashes * from / to \ format. */ #include #include #include char **__crt0_glob_function(char *_arg) { /* don't let djgpp glob our command line arguments */ return NULL; } int main(int argc, char *argv[]) { char buf[256] = ""; FILE *f = NULL; int flip_slashes = 0; int ret, i, j; char *p; if (argc < 2) { printf("Usage: runner program args\n"); return 1; } for (i=1; i= 126) { fprintf(stderr, "runner: oops: command line is longer than 126 characters!\n"); remove("_tmpfile.arg"); return 1; } } ret = system(buf); remove("_tmpfile.arg"); return ret; } allegro-4.4.3.1/src/misc/vgaregs.c0000664000175000017500000000356013437077643015630 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helpers for accessing the VGA hardware registers. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #ifdef ALLEGRO_GFX_HAS_VGA #include "allegro/internal/aintern.h" #include "allegro/internal/aintvga.h" int _crtc = 0x3D4; /* _vga_regs_init: * Initialiases the VGA register access functions. */ void _vga_regs_init(void) { LOCK_VARIABLE(_crtc); if (inportb(0x3CC) & 1) _crtc = 0x3D4; else _crtc = 0x3B4; } /* _vga_vsync: * Waits for the start of a vertical retrace. */ void _vga_vsync(void) { _vsync_out_v(); _vsync_in(); } /* _set_vga_virtual_width: * Used by various graphics drivers to adjust the virtual width of * the screen, using VGA register 0x3D4 index 0x13. */ void _set_vga_virtual_width(int old_width, int new_width) { int width; if (old_width != new_width) { width = _read_vga_register(_crtc, 0x13); _write_vga_register(_crtc, 0x13, (width * new_width) / old_width); } } /* _vga_set_palette_range: * Sets part of the VGA palette. */ void _vga_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) { int i; if (vsync) _vga_vsync(); outportb(0x3C8, from); for (i=from; i<=to; i++) { outportb(0x3C9, p[i].r); outportb(0x3C9, p[i].g); outportb(0x3C9, p[i].b); } } #endif /* ALLEGRO_GFX_HAS_VGA */ allegro-4.4.3.1/src/misc/colconv.c0000664000175000017500000002410613437077643015634 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Asm routines for software color conversion. * Suggestions to make it faster are welcome :) * * By Isaac Cruz. * * 24-bit color support and non MMX routines by Eric Botcazou. * * Support for rectangles of any width, 8-bit destination color * and cross-conversion between 15-bit and 16-bit colors, * additional MMX and color copy routines by Robert J. Ohannessian. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" int *_colorconv_indexed_palette = NULL; /* for conversion from 8-bit */ int *_colorconv_rgb_scale_5x35 = NULL; /* for conversion from 15/16-bit */ unsigned char *_colorconv_rgb_map = NULL; /* for conversion from 8/12-bit to 8-bit */ static int indexed_palette_depth; /* target depth of the indexed palette */ static int indexed_palette_size; /* size of the indexed palette */ /* build_rgb_scale_5235_table: * Builds pre-calculated tables for 15-bit to truecolor conversion. */ static void build_rgb_scale_5235_table(int to_depth) { int i, color, red, green, blue; if (to_depth == 24) /* 6 contiguous 256-entry tables (6k) */ _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*1536); else if (to_depth == 32) /* 2 contiguous 256-entry tables (2k) */ _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*512); /* 1st table: r5g2 to r8g8b0 */ for (i=0; i<128; i++) { red = _rgb_scale_5[i>>2]; green=((i&3)<<6)+((i&3)<<1); color = (red<<16) | (green<<8); _colorconv_rgb_scale_5x35[i] = color; if (to_depth == 24) { _colorconv_rgb_scale_5x35[ 512+i] = (color>>8)+((color&0xff)<<24); _colorconv_rgb_scale_5x35[1024+i] = (color>>16)+((color&0xffff)<<16); } } /* 2nd table: g3b5 to r0g8b8 */ for (i=0; i<256; i++) { blue = _rgb_scale_5[i&0x1f]; green=(i>>5)<<3; if (green == 0x38) green++; color = (green<<8) | blue; _colorconv_rgb_scale_5x35[256+i] = color; if (to_depth == 24) { _colorconv_rgb_scale_5x35[ 512+256+i] = (color>>8)+((color&0xff)<<24); _colorconv_rgb_scale_5x35[1024+256+i] = (color>>16)+((color&0xffff)<<16); } } } /* build_rgb_scale_5335_table: * Builds pre-calculated tables for 16-bit to truecolor conversion. */ static void build_rgb_scale_5335_table(int to_depth) { int i, color, red, green, blue; if (to_depth == 24) /* 6 contiguous 256-entry tables (6k) */ _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*1536); else if (to_depth == 32) /* 2 contiguous 256-entry tables (2k) */ _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*512); /* 1st table: r5g3 to r8g8b0 */ for (i=0; i<256; i++) { red = _rgb_scale_5[i>>3]; green=(i&7)<<5; if (green >= 68) green++; if (green >= 160) green++; color = (red<<16) | (green<<8); _colorconv_rgb_scale_5x35[i] = color; if (to_depth == 24) { _colorconv_rgb_scale_5x35[ 512+i] = (color>>8)+((color&0xff)<<24); _colorconv_rgb_scale_5x35[1024+i] = (color>>16)+((color&0xffff)<<16); } } /* 2nd table: g3b5 to r0g8b8 */ for (i=0; i<256; i++) { blue = _rgb_scale_5[i&0x1f]; green=(i>>5)<<2; if (green == 0x1c) green++; color = (green<<8) | blue; _colorconv_rgb_scale_5x35[256+i] = color; if (to_depth == 24) { _colorconv_rgb_scale_5x35[ 512+256+i] = (color>>8)+((color&0xff)<<24); _colorconv_rgb_scale_5x35[1024+256+i] = (color>>16)+((color&0xffff)<<16); } } } /* create_indexed_palette: * Reserves storage for the 8-bit palette. */ static void create_indexed_palette(int to_depth) { switch (to_depth) { case 15: case 16: indexed_palette_size = PAL_SIZE*2; break; case 24: indexed_palette_size = PAL_SIZE*4; break; case 32: indexed_palette_size = PAL_SIZE; break; } indexed_palette_depth = to_depth; _colorconv_indexed_palette = _AL_MALLOC_ATOMIC(sizeof(int) * indexed_palette_size); } /* _set_colorconv_palette: * Updates 8-bit palette entries. */ void _set_colorconv_palette(AL_CONST struct RGB *p, int from, int to) { int n, color; if (!indexed_palette_size) return; for (n = from; n <= to; n++) { color = makecol_depth(indexed_palette_depth, (p[n].r << 2) | ((p[n].r & 0x30) >> 4), (p[n].g << 2) | ((p[n].g & 0x30) >> 4), (p[n].b << 2) | ((p[n].b & 0x30) >> 4)); _colorconv_indexed_palette[n] = color; if ((indexed_palette_depth == 15) || (indexed_palette_depth == 16)) { /* 2 pre-calculated shift tables (2k) */ _colorconv_indexed_palette[PAL_SIZE+n] = color<<16; } else if (indexed_palette_depth == 24) { /* 4 pre-calculated shift tables (4k) */ _colorconv_indexed_palette[PAL_SIZE+n] = (color>>8)+((color&0xff)<<24); _colorconv_indexed_palette[PAL_SIZE*2+n] = (color>>16)+((color&0xffff)<<16); _colorconv_indexed_palette[PAL_SIZE*3+n] = color<<8; } } } /* create_rgb_map: * Reserves storage for the rgb map to 8-bit. */ static void create_rgb_map(int from_depth) { int rgb_map_size = 0; switch (from_depth) { case 8: rgb_map_size = 256; /* 8-bit */ break; case 15: case 16: case 24: case 32: rgb_map_size = 4096; /* 12-bit */ break; } _colorconv_rgb_map = _AL_MALLOC_ATOMIC(sizeof(int) * rgb_map_size); } /* _get_colorconv_map: * Retrieves a handle to the rgb map. */ unsigned char *_get_colorconv_map(void) { return _colorconv_rgb_map; } /* _get_colorconv_blitter: * Returns the blitter function matching the specified depths. */ COLORCONV_BLITTER_FUNC *_get_colorconv_blitter(int from_depth, int to_depth) { switch (from_depth) { #ifdef ALLEGRO_COLOR8 case 8: switch (to_depth) { case 8: create_rgb_map(8); return &_colorconv_blit_8_to_8; case 15: create_indexed_palette(15); return &_colorconv_blit_8_to_15; case 16: create_indexed_palette(16); return &_colorconv_blit_8_to_16; case 24: create_indexed_palette(24); return &_colorconv_blit_8_to_24; case 32: create_indexed_palette(32); return &_colorconv_blit_8_to_32; } break; #endif #ifdef ALLEGRO_COLOR16 case 15: switch (to_depth) { case 8: create_rgb_map(15); return &_colorconv_blit_15_to_8; case 15: #ifndef ALLEGRO_NO_COLORCOPY return &_colorcopy_blit_15_to_15; #else return NULL; #endif case 16: return &_colorconv_blit_15_to_16; case 24: build_rgb_scale_5235_table(24); return &_colorconv_blit_15_to_24; case 32: build_rgb_scale_5235_table(32); return &_colorconv_blit_15_to_32; } break; case 16: switch (to_depth) { case 8: create_rgb_map(16); return &_colorconv_blit_16_to_8; case 15: return &_colorconv_blit_16_to_15; case 16: #ifndef ALLEGRO_NO_COLORCOPY return &_colorcopy_blit_16_to_16; #else return NULL; #endif case 24: build_rgb_scale_5335_table(24); return &_colorconv_blit_16_to_24; case 32: build_rgb_scale_5335_table(32); return &_colorconv_blit_16_to_32; } break; #endif #ifdef ALLEGRO_COLOR24 case 24: switch (to_depth) { case 8: create_rgb_map(24); return &_colorconv_blit_24_to_8; case 15: return &_colorconv_blit_24_to_15; case 16: return &_colorconv_blit_24_to_16; case 24: #ifndef ALLEGRO_NO_COLORCOPY return &_colorcopy_blit_24_to_24; #else return NULL; #endif case 32: return &_colorconv_blit_24_to_32; } break; #endif #ifdef ALLEGRO_COLOR32 case 32: switch (to_depth) { case 8: create_rgb_map(32); return &_colorconv_blit_32_to_8; case 15: return &_colorconv_blit_32_to_15; case 16: return &_colorconv_blit_32_to_16; case 24: return &_colorconv_blit_32_to_24; case 32: #ifndef ALLEGRO_NO_COLORCOPY return &_colorcopy_blit_32_to_32; #else return NULL; #endif } break; #endif } return NULL; } /* _release_colorconv_blitter: * Frees previously allocated resources. */ void _release_colorconv_blitter(COLORCONV_BLITTER_FUNC *blitter) { /* destroy the 8-bit palette */ if (_colorconv_indexed_palette) { _AL_FREE(_colorconv_indexed_palette); _colorconv_indexed_palette = NULL; indexed_palette_size = 0; } /* destroy the shift table */ if (_colorconv_rgb_scale_5x35) { _AL_FREE(_colorconv_rgb_scale_5x35); _colorconv_rgb_scale_5x35 = NULL; } /* destroy the rgb map to 8-bit */ if (_colorconv_rgb_map) { _AL_FREE(_colorconv_rgb_map); _colorconv_rgb_map = NULL; } } allegro-4.4.3.1/src/misc/pckeys.c0000664000175000017500000007547013437077643015501 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Shared helper routines for converting PC keyboard scancodes * into a format that the main keyboard.c can understand, using * the mapping tables from keyboard.dat. * * By Shawn Hargreaves. * * Salvador Eduardo Tropea added support for extended scancodes, * keyboard LED's, capslock and numlock, and alt+numpad input. * * Fabian Nunez added support for the special Microsoft keys. * * Mathieu Lafon added support for the Pause and PrtScr keys and * changed the key[] table to a normal/extended bitfield. * * Dynamic keyboard switching by Peter Cech. * * Peter Pavlovic improved the handling of accented keymaps. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG) #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG) #define KB_ACCENTS (KB_ACCENT1_FLAG | KB_ACCENT2_FLAG | KB_ACCENT3_FLAG | KB_ACCENT4_FLAG) #define KB_SH_CTRL_ALT (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG) #define KB_CTRL_ALT (KB_CTRL_FLAG | KB_ALT_FLAG) static int key_extended = FALSE; static int key_altgr = FALSE; static int key_pad_seq = 0; static int key_pause_loop = 0; static int key_paused = FALSE; int _key_accent1 = 0; int _key_accent2 = 0; int _key_accent3 = 0; int _key_accent4 = 0; int _key_accent1_flag = 0; int _key_accent2_flag = 0; int _key_accent3_flag = 0; int _key_accent4_flag = 0; int _key_standard_kb = TRUE; char *_keyboard_layout = NULL; /* lookup table for converting hardware scancodes into Allegro format */ static unsigned char hw_to_mycode[128] = { /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R, /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I, /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S, /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON, /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH, /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK, /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD, /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD, /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD, /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD, /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, /* 0x60 */ 0, 0, 0, 0, /* 0x64 */ 0, 0, 0, 0, /* 0x68 */ 0, 0, 0, 0, /* 0x6C */ 0, 0, 0, 0, /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1, /* 0x74 */ 0, 0, 0, 0, /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT, /* 0x7C */ 0, KEY_YEN, 0, 0 }; /* lookup table for converting extended hardware codes into Allegro format */ static unsigned char hw_to_mycode_ex[128] = { /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R, /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I, /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S, /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON, /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH, /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR, /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME, /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT, /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END, /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL, /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, /* 0x60 */ 0, 0, 0, 0, /* 0x64 */ 0, 0, 0, 0, /* 0x68 */ 0, 0, 0, 0, /* 0x6C */ 0, 0, 0, 0, /* 0x70 */ 0, 0, 0, 0, /* 0x74 */ 0, 0, 0, 0, /* 0x78 */ 0, 0, 0, 0, /* 0x7C */ 0, 0, 0, 0 }; /* convert Allegro format scancodes into key_shifts flag bits */ static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = { KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG, KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG, KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG, KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG }; /* convert numeric pad scancodes into arrow codes */ static unsigned char numlock_table[10] = { KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT, KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP }; /* default mapping table for the US keyboard layout */ static unsigned short standard_key_ascii_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* capslock mapping table for the US keyboard layout */ static unsigned short standard_key_capslock_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* shifted mapping table for the US keyboard layout */ static unsigned short standard_key_shift_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ', /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ '/', '*', '-', '+', '.', 13, /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, '"', 0, 0, 0, 0, 0, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* ctrl+key mapping table for the US keyboard layout */ static unsigned short standard_key_control_table[KEY_MAX] = { /* start */ 0, /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* numpad */ 2, 2, 2, 2, 2, 10, /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* empty table for stuff we don't need (accents in US map) */ static unsigned short standard_key_empty_table[KEY_MAX]; /* alternative mappings for custom keyboard layouts */ static unsigned short custom_key_ascii_table[KEY_MAX]; static unsigned short custom_key_capslock_table[KEY_MAX]; static unsigned short custom_key_shift_table[KEY_MAX]; static unsigned short custom_key_control_table[KEY_MAX]; static unsigned short custom_key_altgr_lower_table[KEY_MAX]; static unsigned short custom_key_altgr_upper_table[KEY_MAX]; static unsigned short custom_key_accent1_lower_table[KEY_MAX]; static unsigned short custom_key_accent1_upper_table[KEY_MAX]; static unsigned short custom_key_accent2_lower_table[KEY_MAX]; static unsigned short custom_key_accent2_upper_table[KEY_MAX]; static unsigned short custom_key_accent3_lower_table[KEY_MAX]; static unsigned short custom_key_accent3_upper_table[KEY_MAX]; static unsigned short custom_key_accent4_lower_table[KEY_MAX]; static unsigned short custom_key_accent4_upper_table[KEY_MAX]; /* shortcut pointers to the current layout mappings */ unsigned short *_key_ascii_table = standard_key_ascii_table; unsigned short *_key_capslock_table = standard_key_capslock_table; unsigned short *_key_shift_table = standard_key_shift_table; unsigned short *_key_control_table = standard_key_control_table; unsigned short *_key_altgr_lower_table = standard_key_empty_table; unsigned short *_key_altgr_upper_table = standard_key_empty_table; unsigned short *_key_accent1_lower_table = standard_key_empty_table; unsigned short *_key_accent1_upper_table = standard_key_empty_table; unsigned short *_key_accent2_lower_table = standard_key_empty_table; unsigned short *_key_accent2_upper_table = standard_key_empty_table; unsigned short *_key_accent3_lower_table = standard_key_empty_table; unsigned short *_key_accent3_upper_table = standard_key_empty_table; unsigned short *_key_accent4_lower_table = standard_key_empty_table; unsigned short *_key_accent4_upper_table = standard_key_empty_table; /* Table with key descriptions. */ char *_pckeys_names[KEY_MAX]; /* set_standard_keyboard: * Sets up pointers ready to use the standard US keyboard mapping. */ static INLINE void set_standard_keyboard(void) { _key_ascii_table = standard_key_ascii_table; _key_capslock_table = standard_key_capslock_table; _key_shift_table = standard_key_shift_table; _key_control_table = standard_key_control_table; _key_altgr_lower_table = standard_key_empty_table; _key_altgr_upper_table = standard_key_empty_table; _key_accent1_lower_table = standard_key_empty_table; _key_accent1_upper_table = standard_key_empty_table; _key_accent2_lower_table = standard_key_empty_table; _key_accent2_upper_table = standard_key_empty_table; _key_accent3_lower_table = standard_key_empty_table; _key_accent3_upper_table = standard_key_empty_table; _key_accent4_lower_table = standard_key_empty_table; _key_accent4_upper_table = standard_key_empty_table; _key_standard_kb = TRUE; } /* set_custom_keyboard: * Sets up pointers ready to use the custom keyboard mapping. */ static INLINE void set_custom_keyboard(void) { _key_ascii_table = custom_key_ascii_table; _key_capslock_table = custom_key_capslock_table; _key_shift_table = custom_key_shift_table; _key_control_table = custom_key_control_table; _key_altgr_lower_table = custom_key_altgr_lower_table; _key_altgr_upper_table = custom_key_altgr_upper_table; _key_accent1_lower_table = custom_key_accent1_lower_table; _key_accent1_upper_table = custom_key_accent1_upper_table; _key_accent2_lower_table = custom_key_accent2_lower_table; _key_accent2_upper_table = custom_key_accent2_upper_table; _key_accent3_lower_table = custom_key_accent3_lower_table; _key_accent3_upper_table = custom_key_accent3_upper_table; _key_accent4_lower_table = custom_key_accent4_lower_table; _key_accent4_upper_table = custom_key_accent4_upper_table; _key_standard_kb = FALSE; } /* _pckey_scancode_to_ascii: * Looks up a scancode in the current mapping table. */ int _pckey_scancode_to_ascii(int scancode) { int val; if ((scancode < 0) || (scancode >= KEY_MAX)) return 0; val = _key_ascii_table[scancode]; if (val == 0xFFFF) val = 0; return val; } /* _pckey_scancode_to_name: * Like above, but returns a static string and also works for things like * modifier keys. */ AL_CONST char *_pckey_scancode_to_name(int scancode) { if ((scancode < 0) || (scancode >= KEY_MAX)) return NULL; return _pckeys_names[scancode]; } /* _handle_pckey: * Handles PC keyboard input, in the same format it comes from the * keyboard controller hardware (raw scancodes, top bit set means the * key was released, special escapes for extended keys, pause, etc). * This routine translates the data using the current mapping table, * and calls routines from keyboard.c as required. */ void _handle_pckey(int code) { int origcode, mycode, flag, numflag, i=0; unsigned short *table; if (key_pause_loop) { /* skip multiple codes generated by the pause key */ key_pause_loop--; return; } if (code == 0xE1) { /* the pause key requires special handling */ if (key_paused) _handle_key_release(KEY_PAUSE); else _handle_key_press(0, KEY_PAUSE); key_paused = !key_paused; key_pause_loop = 5; return; } if (code == 0xE0) { /* flag that the next key will be an extended one */ key_extended = TRUE; return; } /* convert from hardware to Allegro format */ if (key_extended) { mycode = hw_to_mycode_ex[code & 0x7F]; key_extended = FALSE; } else mycode = hw_to_mycode[code & 0x7F]; if (!mycode) return; origcode = mycode; if (mycode >= KEY_MODIFIERS) flag = modifier_table[mycode - KEY_MODIFIERS]; else flag = 0; numflag = ((_key_shifts & KB_NUMLOCK_FLAG) != 0) == ((_key_shifts & KB_SHIFT_FLAG) != 0); /* handle released keys */ if (code & 0x80) { if (flag & KB_ALT_FLAG) { /* end of an alt+numpad numeric entry sequence */ if (_key_shifts & KB_INALTSEQ_FLAG) { _key_shifts &= ~KB_INALTSEQ_FLAG; _handle_key_press(key_pad_seq, 0); } } if (flag & KB_MODIFIERS) { /* turn off the shift state for this key */ _key_shifts &= ~flag; if (mycode == KEY_ALTGR) key_altgr = FALSE; } /* update the key array for a released key */ _handle_key_release(mycode); return; } if ((mycode == KEY_F1) && ((_key_shifts & KB_CTRL_ALT) == KB_CTRL_ALT)) { /* switch to the standard keyboard layout */ _handle_key_press(-1, KEY_F1); set_standard_keyboard(); return; } if ((mycode == KEY_F2) && ((_key_shifts & KB_CTRL_ALT) == KB_CTRL_ALT)) { /* switch to the custom keyboard layout */ _handle_key_press(-1, KEY_F2); set_custom_keyboard(); return; } if (flag & KB_MODIFIERS) { /* turn on a modifier key */ _key_shifts |= flag; if (mycode == KEY_ALTGR) key_altgr = TRUE; _handle_key_press(-1, origcode); return; } if ((flag & KB_LED_FLAGS) && (key_led_flag)) { /* toggle caps/num/scroll lock */ _key_shifts ^= flag; _handle_key_press(-1, origcode); return; } /* new ACCENT stuff */ if (!_key_standard_kb) { if ((mycode == _key_accent1) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent1_flag)) { _key_shifts |= KB_ACCENT1_FLAG; _handle_key_press(-1, origcode); return; } else if ((mycode == _key_accent2) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent2_flag)) { _key_shifts |= KB_ACCENT2_FLAG; _handle_key_press(-1, origcode); return; } else if ((mycode == _key_accent3) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent3_flag)) { _key_shifts |= KB_ACCENT3_FLAG; _handle_key_press(-1, origcode); return; } else if ((mycode == _key_accent4) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent4_flag)) { _key_shifts |= KB_ACCENT4_FLAG; _handle_key_press(-1, origcode); return; } } if (_key_shifts & KB_ACCENTS) { /* accented character input */ if (((_key_shifts & KB_SHIFT_FLAG) != 0) ^ ((_key_shifts & KB_CAPSLOCK_FLAG) != 0)) { if (_key_shifts & KB_ACCENT1_FLAG) table = _key_accent1_upper_table; else if (_key_shifts & KB_ACCENT2_FLAG) table = _key_accent2_upper_table; else if (_key_shifts & KB_ACCENT3_FLAG) table = _key_accent3_upper_table; else if (_key_shifts & KB_ACCENT4_FLAG) table = _key_accent4_upper_table; else table = NULL; } else { if (_key_shifts & KB_ACCENT1_FLAG) table = _key_accent1_lower_table; else if (_key_shifts & KB_ACCENT2_FLAG) table = _key_accent2_lower_table; else if (_key_shifts & KB_ACCENT3_FLAG) table = _key_accent3_lower_table; else if (_key_shifts & KB_ACCENT4_FLAG) table = _key_accent4_lower_table; else table = NULL; } if (table[mycode]) { /* simple accented char */ _key_shifts &= ~KB_ACCENTS; _handle_key_press(table[mycode], origcode); return; } else { /* add the accent as an individual character */ if (_key_shifts & (KB_ACCENT1_FLAG)) i = _key_accent1; else if (_key_shifts & (KB_ACCENT2_FLAG)) i = _key_accent2; else if (_key_shifts & (KB_ACCENT3_FLAG)) i = _key_accent3; else if (_key_shifts & (KB_ACCENT4_FLAG)) i = _key_accent4; _handle_key_press(_key_ascii_table[i], i); _key_shifts &= ~KB_ACCENTS; } } if (_key_shifts & KB_ALT_FLAG) { if ((mycode >= KEY_0_PAD) && (mycode <= KEY_9_PAD)) { /* alt+numpad numeric entry */ if (_key_shifts & KB_INALTSEQ_FLAG) { key_pad_seq = key_pad_seq*10 + mycode - KEY_0_PAD; } else { _key_shifts |= KB_INALTSEQ_FLAG; key_pad_seq = mycode - KEY_0_PAD; } _handle_key_press(-1, origcode); return; } else { /* alt+key */ if (_key_ascii_table[mycode] == 0xFFFF) i = 0xFFFF; else if (key_altgr) { if (((_key_shifts & KB_SHIFT_FLAG) != 0) ^ ((_key_shifts & KB_CAPSLOCK_FLAG) != 0)) i = _key_altgr_upper_table[mycode]; else i = _key_altgr_lower_table[mycode]; } else i = 0; } } else if ((mycode >= KEY_0_PAD) && (mycode <= KEY_9_PAD)) { /* handle numlock number->arrow conversions */ i = mycode - KEY_0_PAD; if ((_key_shifts & KB_CTRL_FLAG) || (numflag)) { mycode = numlock_table[i]; i = 0xFFFF; } else i = _key_ascii_table[mycode]; } else if (mycode == KEY_DEL_PAD) { /* handle numlock logic for the del key */ if (numflag) { mycode = KEY_DEL; i = 0xFFFF; } else i = _key_ascii_table[KEY_DEL_PAD]; } else if (_key_shifts & KB_CTRL_FLAG) { /* ctrl+key */ i = _key_control_table[mycode]; } else if (_key_shifts & KB_SHIFT_FLAG) { /* shift+key */ if (_key_shifts & KB_CAPSLOCK_FLAG) { if (_key_ascii_table[mycode] == _key_capslock_table[mycode]) i = _key_shift_table[mycode]; else i = _key_ascii_table[mycode]; } else i = _key_shift_table[mycode]; } else if (_key_shifts & KB_CAPSLOCK_FLAG) { /* capslock+key */ i = _key_capslock_table[mycode]; } else { /* normal key */ i = _key_ascii_table[mycode]; } /* use the current modifier state in place of the key code? */ if (i == 0xFFFF) i = _key_shifts & KB_MODIFIERS; _key_shifts &= ~KB_INALTSEQ_FLAG; /* phew! */ _handle_key_press(i, origcode); } END_OF_FUNCTION(_handle_pckey); /* read_key_table: * Reads a specific keymapping table from the config file. */ static void read_key_table(unsigned short *out, unsigned short *in, char *section) { char tmp1[64], tmp2[128], name[128]; char *fmt = uconvert_ascii("key%d", tmp1); char *sec = uconvert_ascii(section, tmp2); int i; for (i=0; i ' ') { uszprintf(str, sizeof str, "%c", ascii); _pckeys_names[i] = strdup (str); } else { _pckeys_names[i] = strdup(_keyboard_common_names[i]); } } } /* read_keyboard_config: * Reads in the keyboard config tables. */ static void read_keyboard_config(void) { char filename[1024], tmp1[128], tmp2[128], *ext, *datafile; AL_CONST char* name; name = get_config_string(uconvert_ascii("system", tmp1), uconvert_ascii("keyboard", tmp2), _keyboard_layout); if ((!name) || (!ugetc(name))) return; ext = uconvert_ascii(".cfg", tmp1); datafile = uconvert_ascii("keyboard.dat", tmp2); if (find_allegro_resource(filename, name, ext, datafile, NULL, NULL, NULL, sizeof(filename)) != 0) return; push_config_state(); set_config_file(filename); read_key_table(custom_key_ascii_table, standard_key_ascii_table, "key_ascii"); read_key_table(custom_key_capslock_table, standard_key_capslock_table, "key_capslock"); read_key_table(custom_key_shift_table, standard_key_shift_table, "key_shift"); read_key_table(custom_key_control_table, standard_key_control_table, "key_control"); /* preserve backward compatibility with former unique key_altgr table */ read_key_table(custom_key_altgr_lower_table, standard_key_empty_table, "key_altgr"); read_key_table(custom_key_altgr_upper_table, standard_key_empty_table, "key_altgr"); read_key_table(custom_key_altgr_lower_table, custom_key_altgr_lower_table, "key_altgr_lower"); read_key_table(custom_key_altgr_upper_table, custom_key_altgr_upper_table, "key_altgr_upper"); read_key_table(custom_key_accent1_lower_table, standard_key_empty_table, "key_accent1_lower"); read_key_table(custom_key_accent1_upper_table, standard_key_empty_table, "key_accent1_upper"); read_key_table(custom_key_accent2_lower_table, standard_key_empty_table, "key_accent2_lower"); read_key_table(custom_key_accent2_upper_table, standard_key_empty_table, "key_accent2_upper"); read_key_table(custom_key_accent3_lower_table, standard_key_empty_table, "key_accent3_lower"); read_key_table(custom_key_accent3_upper_table, standard_key_empty_table, "key_accent3_upper"); read_key_table(custom_key_accent4_lower_table, standard_key_empty_table, "key_accent4_lower"); read_key_table(custom_key_accent4_upper_table, standard_key_empty_table, "key_accent4_upper"); _key_accent1 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent1", tmp2), 0); _key_accent2 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent2", tmp2), 0); _key_accent3 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent3", tmp2), 0); _key_accent4 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent4", tmp2), 0); _key_accent1_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent1_flag", tmp2), 0); _key_accent2_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent2_flag", tmp2), 0); _key_accent3_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent3_flag", tmp2), 0); _key_accent4_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent4_flag", tmp2), 0); pop_config_state(); set_custom_keyboard(); update_key_descriptions(); } /* _pckeys_init: * Initialises the scancode translation routines, loading mapping tables * from keyboard.dat. */ void _pckeys_init(void) { int i; _key_accent1 = 0; _key_accent2 = 0; _key_accent3 = 0; _key_accent4 = 0; _key_accent1_flag = 0; _key_accent2_flag = 0; _key_accent3_flag = 0; _key_accent4_flag = 0; key_extended = FALSE; key_altgr = FALSE; key_pad_seq = 0; key_pause_loop = 0; key_paused = FALSE; for (i=0; i #include #include int main(int argc, char *argv[]) { char var[4096], *p; FILE *file; int i,c; p = var; *p = '\0'; for (i=1; i < argc; i++) { if (argv[i][0] == '@') { if ((file=fopen(argv[i]+1, "r")) == NULL) { fprintf(stderr, "runnergw: Unable to open '%s'.\n", argv[i]); exit(EXIT_FAILURE); } while ((c=fgetc(file)) != EOF) { if (c != '\n') *p++ = c; } fclose(file); } else { strncat(var, argv[i], sizeof(var)-1); p = var + strlen(var); } *p++ = ' '; *p = '\0'; } return system(var); } allegro-4.4.3.1/src/misc/modex.c0000664000175000017500000012462613437077643015315 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video driver for VGA tweaked modes (aka mode-X). * * By Shawn Hargreaves. * * Jonathan Tarbox wrote the mode set code. * * TBD/FeR added the 320x600 and 360x600 modes. * * See readme.txt for copyright information. */ #include #include "allegro.h" #ifdef ALLEGRO_GFX_HAS_VGA #include "allegro/internal/aintern.h" #include "allegro/internal/aintvga.h" #ifdef ALLEGRO_INTERNAL_HEADER #include ALLEGRO_INTERNAL_HEADER #endif #include "modexsms.h" #if (!defined ALLEGRO_LINUX) || ((defined ALLEGRO_LINUX_VGA) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))) void _x_draw_sprite_end(void); void _x_blit_from_memory_end(void); void _x_blit_to_memory_end(void); static void really_split_modex_screen(int line); /* table of functions for drawing onto the mode-X screen */ static GFX_VTABLE __modex_vtable = { 8, MASK_COLOR_8, _x_unbank_switch, NULL, NULL, NULL, NULL, NULL, _x_getpixel, _x_putpixel, _x_vline, _x_hline, _x_hline, _normal_line, _fast_line, _normal_rectfill, _soft_triangle, _x_draw_sprite, _x_draw_sprite, _x_draw_sprite_v_flip, _x_draw_sprite_h_flip, _x_draw_sprite_vh_flip, _x_draw_trans_sprite, NULL, _x_draw_lit_sprite, _x_draw_rle_sprite, _x_draw_trans_rle_sprite, NULL, _x_draw_lit_rle_sprite, _x_draw_character, _x_draw_glyph, _x_blit_from_memory, _x_blit_to_memory, _x_blit_from_memory, _x_blit_to_memory, _x_blit, _x_blit_forward, _x_blit_backward, _blit_between_formats, _x_masked_blit, _x_clear_to_color, _pivot_scaled_sprite_flip, NULL, /* AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)); */ _soft_draw_gouraud_sprite, _x_draw_sprite_end, _x_blit_from_memory_end, _soft_polygon, _soft_rect, _soft_circle, _soft_circlefill, _soft_ellipse, _soft_ellipsefill, _soft_arc, _soft_spline, _soft_floodfill, _soft_polygon3d, _soft_polygon3d_f, _soft_triangle3d, _soft_triangle3d_f, _soft_quad3d, _soft_quad3d_f }; static BITMAP *modex_init(int w, int h, int v_w, int v_h, int color_depth); static void modex_exit(BITMAP *b); static int modex_scroll(int x, int y); static int request_modex_scroll(int x, int y); static int poll_modex_scroll(void); static void modex_enable_triple_buffer(void); static GFX_MODE_LIST *modex_fetch_mode_list(void); GFX_DRIVER gfx_modex = { GFX_MODEX, empty_string, empty_string, "Mode-X", modex_init, modex_exit, modex_scroll, _vga_vsync, _vga_set_palette_range, NULL, NULL, /* no triple buffering (yet) */ modex_enable_triple_buffer, NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ _save_vga_mode, _restore_vga_mode, NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ modex_fetch_mode_list, 0, 0, TRUE, 0, 0, 0x40000, 0, FALSE }; static GFX_MODE modex_gfx_modes[] = { { 256, 200, 8 }, { 256, 224, 8 }, { 256, 240, 8 }, { 256, 256, 8 }, { 320, 200, 8 }, { 320, 240, 8 }, { 320, 350, 8 }, { 320, 400, 8 }, { 320, 480, 8 }, { 320, 600, 8 }, { 360, 200, 8 }, { 360, 240, 8 }, { 360, 270, 8 }, { 360, 360, 8 }, { 360, 400, 8 }, { 360, 480, 8 }, { 360, 600, 8 }, { 376, 282, 8 }, { 376, 308, 8 }, { 376, 564, 8 }, { 400, 150, 8 }, { 400, 300, 8 }, { 400, 600, 8 }, { 0, 0, 0 } }; #ifdef GFX_XTENDED static BITMAP *xtended_init(int w, int h, int v_w, int v_h, int color_depth); static GFX_MODE_LIST *xtended_fetch_mode_list(void); GFX_DRIVER gfx_xtended = { GFX_XTENDED, empty_string, empty_string, "Xtended mode", xtended_init, modex_exit, NULL, /* no hardware scrolling */ _vga_vsync, _vga_set_palette_range, NULL, NULL, NULL, /* no triple buffering */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor */ NULL, /* no drawing mode hook */ NULL, NULL, /* no state saving */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ xtended_fetch_mode_list, 640, 400, TRUE, 0, 0, 0x40000, 0, FALSE }; GFX_MODE xtended_gfx_modes[] = { { 640, 400, 8 }, { 0, 0, 0 } }; #endif /* GFX_XTENDED */ /* VGA register contents for the various tweaked modes */ typedef struct VGA_REGISTER { unsigned short port; unsigned char index; unsigned char value; } VGA_REGISTER; static VGA_REGISTER mode_256x200[] = { { 0x3C2, 0x0, 0xE3 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x3F }, { 0x3D4, 0x2, 0x40 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x4E }, { 0x3D4, 0x5, 0x96 }, { 0x3D4, 0x6, 0xBF }, { 0x3D4, 0x7, 0x1F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0x9C }, { 0x3D4, 0x11, 0x8E }, { 0x3D4, 0x12, 0x8F }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x96 }, { 0x3D4, 0x16, 0xB9 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_256x224[] = { { 0x3C2, 0x0, 0xE3 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x3F }, { 0x3D4, 0x2, 0x40 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x4A }, { 0x3D4, 0x5, 0x9A }, { 0x3D4, 0x6, 0xB }, { 0x3D4, 0x7, 0x3E }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0xDA }, { 0x3D4, 0x11, 0x9C }, { 0x3D4, 0x12, 0xBF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0xC7 }, { 0x3D4, 0x16, 0x4 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_256x240[] = { { 0x3C2, 0x0, 0xE3 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x3F }, { 0x3D4, 0x2, 0x40 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x4E }, { 0x3D4, 0x5, 0x96 }, { 0x3D4, 0x6, 0xD }, { 0x3D4, 0x7, 0x3E }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0xEA }, { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xDF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0xE7 }, { 0x3D4, 0x16, 0x6 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_256x256[] = { { 0x3C2, 0x0, 0xE3 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x3F }, { 0x3D4, 0x2, 0x40 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x4A }, { 0x3D4, 0x5, 0x9A }, { 0x3D4, 0x6, 0x23 }, { 0x3D4, 0x7, 0xB2 }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x61 }, { 0x3D4, 0x10, 0xA }, { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xFF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x7 }, { 0x3D4, 0x16, 0x1A }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_320x200[] = { { 0x3C2, 0x0, 0x63 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x4F }, { 0x3D4, 0x2, 0x50 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x54 }, { 0x3D4, 0x5, 0x80 }, { 0x3D4, 0x6, 0xBF }, { 0x3D4, 0x7, 0x1F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0x9C }, { 0x3D4, 0x11, 0x8E }, { 0x3D4, 0x12, 0x8F }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x96 }, { 0x3D4, 0x16, 0xB9 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_320x240[] = { { 0x3C2, 0x0, 0xE3 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x4F }, { 0x3D4, 0x2, 0x50 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x54 }, { 0x3D4, 0x5, 0x80 }, { 0x3D4, 0x6, 0xD }, { 0x3D4, 0x7, 0x3E }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0xEA }, { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xDF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0xE7 }, { 0x3D4, 0x16, 0x6 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_320x400[] = { { 0x3C2, 0x0, 0x63 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x4F }, { 0x3D4, 0x2, 0x50 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x54 }, { 0x3D4, 0x5, 0x80 }, { 0x3D4, 0x6, 0xBF }, { 0x3D4, 0x7, 0x1F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x40 }, { 0x3D4, 0x10, 0x9C }, { 0x3D4, 0x11, 0x8E }, { 0x3D4, 0x12, 0x8F }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x96 }, { 0x3D4, 0x16, 0xB9 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_320x480[] = { { 0x3C2, 0x0, 0xE3 }, { 0x3D4, 0x0, 0x5F }, { 0x3D4, 0x1, 0x4F }, { 0x3D4, 0x2, 0x50 }, { 0x3D4, 0x3, 0x82 }, { 0x3D4, 0x4, 0x54 }, { 0x3D4, 0x5, 0x80 }, { 0x3D4, 0x6, 0xD }, { 0x3D4, 0x7, 0x3E }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x40 }, { 0x3D4, 0x10, 0xEA }, { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xDF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0xE7 }, { 0x3D4, 0x16, 0x6 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_320x600[] = { { 0x3C2, 0x00, 0xE7 }, { 0x3D4, 0x00, 0x5F }, { 0x3D4, 0x01, 0x4F }, { 0x3D4, 0x02, 0x50 }, { 0x3D4, 0x03, 0x82 }, { 0x3D4, 0x04, 0x54 }, { 0x3D4, 0x05, 0x80 }, { 0x3D4, 0x06, 0x70 }, { 0x3D4, 0x07, 0xF0 }, { 0x3D4, 0x08, 0x00 }, { 0x3D4, 0x09, 0x60 }, { 0x3D4, 0x10, 0x5B }, { 0x3D4, 0x11, 0x8C }, { 0x3D4, 0x12, 0x57 }, { 0x3D4, 0x13, 0x28 }, { 0x3D4, 0x14, 0x00 }, { 0x3D4, 0x15, 0x58 }, { 0x3D4, 0x16, 0x70 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x01, 0x01 }, { 0x3C4, 0x04, 0x06 }, { 0x3CE, 0x05, 0x40 }, { 0x3CE, 0x06, 0x05 }, { 0x3C0, 0x10, 0x41 }, { 0x3C0, 0x13, 0x00 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x200[] = { { 0x3C2, 0x0, 0x67 }, { 0x3D4, 0x0, 0x6B }, { 0x3D4, 0x1, 0x59 }, { 0x3D4, 0x2, 0x5A }, { 0x3D4, 0x3, 0x8E }, { 0x3D4, 0x4, 0x5E }, { 0x3D4, 0x5, 0x8A }, { 0x3D4, 0x6, 0xBF }, { 0x3D4, 0x7, 0x1F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0x9C }, { 0x3D4, 0x11, 0x8E }, { 0x3D4, 0x12, 0x8F }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x96 }, { 0x3D4, 0x16, 0xB9 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x240[] = { { 0x3C2, 0x0, 0xE7 }, { 0x3D4, 0x0, 0x6B }, { 0x3D4, 0x1, 0x59 }, { 0x3D4, 0x2, 0x5A }, { 0x3D4, 0x3, 0x8E }, { 0x3D4, 0x4, 0x5E }, { 0x3D4, 0x5, 0x8A }, { 0x3D4, 0x6, 0xD }, { 0x3D4, 0x7, 0x3E }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x41 }, { 0x3D4, 0x10, 0xEA }, { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xDF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0xE7 }, { 0x3D4, 0x16, 0x6 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x270[] = { { 0x3C2, 0x0, 0xE7 }, { 0x3D4, 0x0, 0x6B }, { 0x3D4, 0x1, 0x59 }, { 0x3D4, 0x2, 0x5A }, { 0x3D4, 0x3, 0x8E }, { 0x3D4, 0x4, 0x5E }, { 0x3D4, 0x5, 0x8A }, { 0x3D4, 0x6, 0x30 }, { 0x3D4, 0x7, 0xF0 }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x61 }, { 0x3D4, 0x10, 0x20 }, { 0x3D4, 0x11, 0xA9 }, { 0x3D4, 0x12, 0x1B }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x1F }, { 0x3D4, 0x16, 0x2F }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x360[] = { { 0x3C2, 0x0, 0x67 }, { 0x3D4, 0x0, 0x6B }, { 0x3D4, 0x1, 0x59 }, { 0x3D4, 0x2, 0x5A }, { 0x3D4, 0x3, 0x8E }, { 0x3D4, 0x4, 0x5E }, { 0x3D4, 0x5, 0x8A }, { 0x3D4, 0x6, 0xBF }, { 0x3D4, 0x7, 0x1F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x40 }, { 0x3D4, 0x10, 0x88 }, { 0x3D4, 0x11, 0x85 }, { 0x3D4, 0x12, 0x67 }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x6D }, { 0x3D4, 0x16, 0xBA }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x400[] = { { 0x3C2, 0x0, 0x67 }, { 0x3D4, 0x0, 0x6B }, { 0x3D4, 0x1, 0x59 }, { 0x3D4, 0x2, 0x5A }, { 0x3D4, 0x3, 0x8E }, { 0x3D4, 0x4, 0x5E }, { 0x3D4, 0x5, 0x8A }, { 0x3D4, 0x6, 0xBF }, { 0x3D4, 0x7, 0x1F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x40 }, { 0x3D4, 0x10, 0x9C }, { 0x3D4, 0x11, 0x8E }, { 0x3D4, 0x12, 0x8F }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x96 }, { 0x3D4, 0x16, 0xB9 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x480[] = { { 0x3C2, 0x0, 0xE7 }, { 0x3D4, 0x0, 0x6B }, { 0x3D4, 0x1, 0x59 }, { 0x3D4, 0x2, 0x5A }, { 0x3D4, 0x3, 0x8E }, { 0x3D4, 0x4, 0x5E }, { 0x3D4, 0x5, 0x8A }, { 0x3D4, 0x6, 0xD }, { 0x3D4, 0x7, 0x3E }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x40 }, { 0x3D4, 0x10, 0xEA }, { 0x3D4, 0x11, 0xAC }, { 0x3D4, 0x12, 0xDF }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0xE7 }, { 0x3D4, 0x16, 0x6 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_360x600[] = { { 0x3C2, 0x00, 0xE7 }, { 0x3D4, 0x00, 0x5F }, { 0x3D4, 0x01, 0x59 }, { 0x3D4, 0x02, 0x50 }, { 0x3D4, 0x03, 0x82 }, { 0x3D4, 0x04, 0x54 }, { 0x3D4, 0x05, 0x80 }, { 0x3D4, 0x06, 0x70 }, { 0x3D4, 0x07, 0xF0 }, { 0x3D4, 0x08, 0x00 }, { 0x3D4, 0x09, 0x60 }, { 0x3D4, 0x10, 0x5B }, { 0x3D4, 0x11, 0x8C }, { 0x3D4, 0x12, 0x57 }, { 0x3D4, 0x13, 0x2D }, { 0x3D4, 0x14, 0x00 }, { 0x3D4, 0x15, 0x58 }, { 0x3D4, 0x16, 0x70 }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x01, 0x01 }, { 0x3C4, 0x03, 0x00 }, { 0x3C4, 0x04, 0x06 }, { 0x3CE, 0x05, 0x40 }, { 0x3CE, 0x06, 0x05 }, { 0x3C0, 0x10, 0x41 }, { 0x3C0, 0x11, 0x00 }, { 0x3C0, 0x12, 0x0F }, { 0x3C0, 0x13, 0x00 }, { 0x3C0, 0x14, 0x00 }, { 0, 0, 0 } }; static VGA_REGISTER mode_376x282[] = { { 0x3C2, 0x0, 0xE7 }, { 0x3D4, 0x0, 0x6E }, { 0x3D4, 0x1, 0x5D }, { 0x3D4, 0x2, 0x5E }, { 0x3D4, 0x3, 0x91 }, { 0x3D4, 0x4, 0x62 }, { 0x3D4, 0x5, 0x8F }, { 0x3D4, 0x6, 0x62 }, { 0x3D4, 0x7, 0xF0 }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x61 }, { 0x3D4, 0x10, 0x37 }, { 0x3D4, 0x11, 0x89 }, { 0x3D4, 0x12, 0x33 }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x3C }, { 0x3D4, 0x16, 0x5C }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_376x308[] = { { 0x3C2, 0x0, 0xE7 }, { 0x3D4, 0x0, 0x6E }, { 0x3D4, 0x1, 0x5D }, { 0x3D4, 0x2, 0x5E }, { 0x3D4, 0x3, 0x91 }, { 0x3D4, 0x4, 0x62 }, { 0x3D4, 0x5, 0x8F }, { 0x3D4, 0x6, 0x62 }, { 0x3D4, 0x7, 0x0F }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x40 }, { 0x3D4, 0x10, 0x37 }, { 0x3D4, 0x11, 0x89 }, { 0x3D4, 0x12, 0x33 }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x3C }, { 0x3D4, 0x16, 0x5C }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_376x564[] = { { 0x3C2, 0x0, 0xE7 }, { 0x3D4, 0x0, 0x6E }, { 0x3D4, 0x1, 0x5D }, { 0x3D4, 0x2, 0x5E }, { 0x3D4, 0x3, 0x91 }, { 0x3D4, 0x4, 0x62 }, { 0x3D4, 0x5, 0x8F }, { 0x3D4, 0x6, 0x62 }, { 0x3D4, 0x7, 0xF0 }, { 0x3D4, 0x8, 0x0 }, { 0x3D4, 0x9, 0x60 }, { 0x3D4, 0x10, 0x37 }, { 0x3D4, 0x11, 0x89 }, { 0x3D4, 0x12, 0x33 }, { 0x3D4, 0x14, 0x0 }, { 0x3D4, 0x15, 0x3C }, { 0x3D4, 0x16, 0x5C }, { 0x3D4, 0x17, 0xE3 }, { 0x3C4, 0x1, 0x1 }, { 0x3CE, 0x5, 0x40 }, { 0x3CE, 0x6, 0x5 }, { 0x3C0, 0x10, 0x41 }, { 0, 0, 0 } }; static VGA_REGISTER mode_notweak[] = { { 0, 0, 0 } }; /* information about a mode-X resolution */ typedef struct TWEAKED_MODE { int w, h; VGA_REGISTER *regs; int parent; int hrs; int shift; int repeat; } TWEAKED_MODE; static TWEAKED_MODE xmodes[] = { { 256, 200, mode_256x200, 0x13, 0, 0, 0 }, { 256, 224, mode_256x224, 0x13, 0, 0, 0 }, { 256, 240, mode_256x240, 0x13, 0, 0, 0 }, { 256, 256, mode_256x256, 0x13, 0, 0, 0 }, { 320, 200, mode_320x200, 0x13, 0, 0, 0 }, { 320, 240, mode_320x240, 0x13, 0, 0, 0 }, { 320, 350, mode_notweak, 0x10, 1, 1, 0 }, { 320, 400, mode_320x400, 0x13, 0, 0, 0 }, { 320, 480, mode_320x480, 0x13, 0, 0, 0 }, { 320, 600, mode_320x600, 0x13, 0, 0, 0 }, { 360, 200, mode_360x200, 0x13, 0, 0, 0 }, { 360, 240, mode_360x240, 0x13, 0, 0, 0 }, { 360, 270, mode_360x270, 0x13, 0, 0, 0 }, { 360, 360, mode_360x360, 0x13, 0, 0, 0 }, { 360, 400, mode_360x400, 0x13, 0, 0, 0 }, { 360, 480, mode_360x480, 0x13, 0, 0, 0 }, { 360, 600, mode_360x600, 0x13, 0, 0, 0 }, { 376, 282, mode_376x282, 0x13, 0, 0, 0 }, { 376, 308, mode_376x308, 0x13, 0, 0, 0 }, { 376, 564, mode_376x564, 0x13, 0, 0, 0 }, { 400, 150, mode_notweak, 0x6A, 1, 1, 3 }, { 400, 300, mode_notweak, 0x6A, 1, 1, 1 }, { 400, 600, mode_notweak, 0x6A, 1, 1, 0 }, { 0, 0, NULL, 0, 0, 0, 0 } }; /* lookup tables for use by modexgfx.s */ char _x_left_mask_table[] = { 0x00, 0x08, 0x0C, 0x0E, 0x0F }; char _x_right_mask_table[] = { 0x00, 0x01, 0x03, 0x07, 0x0F }; /* memory buffer for emulating linear access to a mode-X screen */ unsigned long _x_magic_buffer_addr = 0; unsigned long _x_magic_screen_addr = 0; int _x_magic_screen_width = 0; #ifdef ALLEGRO_DOS static int magic_sel = 0; #endif /* setup_x_magic: * To make sure that things will go on working properly even if a few * bits of code don't know about mode-X screens, we do special magic * inside the bank switch functions to emulate a linear image surface. * Whenever someone tries to access the screen directly, these routines * copy the planar image into a temporary buffer, let the client write * there, and then automatically refresh the screen with the updated * graphics. Very slow, but it makes 100% sure that everything will work. */ static void setup_x_magic(BITMAP *b) { #ifdef ALLEGRO_DOS /* DOS buffer has to go in conventional memory */ int seg = __dpmi_allocate_dos_memory((b->w+15)/16, &magic_sel); if (seg > 0) _x_magic_buffer_addr = seg*16; else _x_magic_buffer_addr = 0; #else /* other platforms can put the buffer wherever they like */ _x_magic_buffer_addr = (unsigned long)_AL_MALLOC(b->w); #endif _x_magic_screen_addr = 0; _x_magic_screen_width = 0; LOCK_VARIABLE(_x_magic_buffer_addr); LOCK_VARIABLE(_x_magic_screen_addr); LOCK_VARIABLE(_x_magic_screen_width); LOCK_FUNCTION(_x_bank_switch); b->write_bank = b->read_bank = _x_bank_switch; } /* modex_exit: * Frees the magic bank switch buffer. */ static void modex_exit(BITMAP *b) { #ifdef ALLEGRO_DOS /* free conventional memory buffer */ if (_x_magic_buffer_addr) { __dpmi_free_dos_memory(magic_sel); magic_sel = 0; _x_magic_buffer_addr = 0; } #else /* free normal memory buffer */ if (_x_magic_buffer_addr) { _AL_FREE((void *)_x_magic_buffer_addr); _x_magic_buffer_addr = 0; } #endif _unset_vga_mode(); /* see modexsms.c */ _split_modex_screen_ptr = NULL; } /* modex_init: * Selects a tweaked VGA mode and creates a screen bitmap for it. */ static BITMAP *modex_init(int w, int h, int v_w, int v_h, int color_depth) { TWEAKED_MODE *mode = xmodes; VGA_REGISTER *reg; BITMAP *b; unsigned long addr; int c; /* Do not continue if this version of Allegro was built in C-only mode. * The bank switchers assume asm-mode calling conventions, but the * library would try to call them with C calling conventions. */ #ifdef ALLEGRO_NO_ASM return NULL; #endif /* see modexsms.c */ _split_modex_screen_ptr = really_split_modex_screen; /* check it is a valid resolution */ if (color_depth != 8) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Mode-X only supports 8 bit color")); return NULL; } /* search the mode table for the requested resolution */ while ((mode->regs) && ((mode->w != w) || (mode->h != h))) mode++; if (!mode->regs) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not a VGA mode-X resolution")); return NULL; } /* round up virtual size if required (v_w must be a multiple of eight) */ v_w = MAX(w, (v_w+7) & 0xFFF8); v_h = MAX(h, v_h); if (v_h > 0x40000/v_w) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen size too large")); return NULL; } /* calculate virtual height = vram / width */ v_h = 0x40000 / v_w; /* lock everything that is used to draw mouse pointers */ LOCK_VARIABLE(__modex_vtable); LOCK_FUNCTION(_x_draw_sprite); LOCK_FUNCTION(_x_blit_from_memory); LOCK_FUNCTION(_x_blit_to_memory); /* set the base video mode, then start tweaking things */ addr = _set_vga_mode(mode->parent); if (!addr) return NULL; outportw(0x3C4, 0x0100); /* synchronous reset */ outportb(0x3D4, 0x11); /* enable crtc regs 0-7 */ outportb(0x3D5, inportb(0x3D5) & 0x7F); outportw(0x3C4, 0x0604); /* disable chain-4 */ for (reg=mode->regs; reg->port; reg++) { /* set the VGA registers */ if (reg->port == 0x3C0) { inportb(0x3DA); outportb(0x3C0, reg->index | 0x20); outportb(0x3C0, reg->value); } else if (reg->port == 0x3C2) { outportb(reg->port, reg->value); } else { outportb(reg->port, reg->index); outportb(reg->port+1, reg->value); } } if (mode->hrs) { outportb(0x3D4, 0x11); outportb(0x3D5, inportb(0x3D5)&0x7F); outportb(0x3D4, 0x04); outportb(0x3D5, inportb(0x3D5)+mode->hrs); outportb(0x3D4, 0x11); outportb(0x3D5,inportb(0x3D5)|0x80); } if (mode->shift) { outportb(0x3CE, 0x05); outportb(0x3CF, (inportb(0x3CF)&0x60)|0x40); inportb(0x3DA); outportb(0x3C0, 0x30); outportb(0x3C0, inportb(0x3C1)|0x40); for (c=0; c<16; c++) { outportb(0x3C0, c); outportb(0x3C0, c); } outportb(0x3C0, 0x20); } if (mode->repeat) { outportb(0x3D4, 0x09); outportb(0x3D5,(inportb(0x3D5)&0x60)|mode->repeat); } outportb(0x3D4, 0x13); /* set scanline length */ outportb(0x3D5, v_w/8); outportw(0x3C4, 0x0300); /* restart sequencer */ /* We only use 1/4th of the real width for the bitmap line pointers, * so they can be used directly for writing to vram, eg. the address * for pixel(x,y) is bmp->line[y]+(x/4). Divide the x coordinate, but * not the line pointer. The clipping position and bitmap width are * stored in the linear pixel format, though, not as mode-X planes. */ b = _make_bitmap(v_w/4, v_h, addr, &gfx_modex, 8, v_w/4); if (!b) return NULL; b->w = b->cr = v_w; b->vtable = &__modex_vtable; b->id |= BMP_ID_PLANAR; setup_x_magic(b); gfx_modex.w = w; gfx_modex.h = h; if (_timer_use_retrace) { gfx_modex.request_scroll = request_modex_scroll; gfx_modex.poll_scroll = poll_modex_scroll; } else { gfx_modex.request_scroll = NULL; gfx_modex.poll_scroll = NULL; } #ifdef ALLEGRO_LINUX b->vtable->acquire = __al_linux_acquire_bitmap; b->vtable->release = __al_linux_release_bitmap; #endif return b; } #ifdef GFX_XTENDED /* xtended_init: * Selects the unchained 640x400 mode. */ static BITMAP *xtended_init(int w, int h, int v_w, int v_h, int color_depth) { unsigned long addr; BITMAP *b; /* Do not continue if this version of Allegro was built in C-only mode. * The bank switchers assume asm-mode calling conventions, but the * library would try to call them with C calling conventions. */ #ifdef ALLEGRO_NO_ASM return NULL; #endif /* see modexsms.c */ _split_modex_screen_ptr = really_split_modex_screen; /* check it is a valid resolution */ if (color_depth != 8) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Xtended mode only supports 8 bit color")); return NULL; } if ((w != 640) || (h != 400) || (v_w > 640) || (v_h > 400)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Xtended mode only supports 640x400")); return NULL; } /* lock everything that is used to draw mouse pointers */ LOCK_VARIABLE(__modex_vtable); LOCK_FUNCTION(_x_draw_sprite); LOCK_FUNCTION(_x_blit_from_memory); LOCK_FUNCTION(_x_blit_to_memory); /* set VESA mode 0x100 */ addr = _set_vga_mode(0x100); if (!addr) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA mode 0x100 not available")); return NULL; } outportw(0x3C4, 0x0604); /* disable chain-4 */ /* we only use 1/4th of the width for the bitmap line pointers */ b = _make_bitmap(640/4, 400, addr, &gfx_xtended, 8, 640/4); if (!b) return NULL; b->w = b->cr = 640; b->vtable = &__modex_vtable; b->id |= BMP_ID_PLANAR; setup_x_magic(b); return b; } /* xtended_fetch_mode_list: * Creates a list of of currently implemented Xtended modes. */ static GFX_MODE_LIST *xtended_fetch_mode_list(void) { GFX_MODE_LIST *mode_list; mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) return NULL; mode_list->mode = _AL_MALLOC(sizeof(xtended_gfx_modes)); if (!mode_list->mode) return NULL; memcpy(mode_list->mode, xtended_gfx_modes, sizeof(xtended_gfx_modes)); mode_list->num_modes = sizeof(xtended_gfx_modes) / sizeof(GFX_MODE) - 1; return mode_list; } #endif /* GFX_XTENDED */ /* modex_scroll: * Hardware scrolling routine for mode-X. */ static int modex_scroll(int x, int y) { long a = x + (y * VIRTUAL_W); DISABLE(); _vsync_out_h(); /* write to VGA address registers */ _write_vga_register(_crtc, 0x0D, (a>>2) & 0xFF); _write_vga_register(_crtc, 0x0C, (a>>10) & 0xFF); ENABLE(); /* write low 2 bits to horizontal pan register */ _write_hpp((a&3)<<1); return 0; } /* request_modex_scroll: * Requests a scroll but doesn't wait for it to be competed: just writes * to some VGA registers and some variables used by the vertical retrace * interrupt simulator, and then returns immediately. The scroll will * actually take place during the next vertical retrace, so this function * can be used together with poll_modex_scroll to implement triple buffered * animation systems (see examples/ex20.c). */ static int request_modex_scroll(int x, int y) { long a = x + (y * VIRTUAL_W); DISABLE(); _vsync_out_h(); /* write to VGA address registers */ _write_vga_register(_crtc, 0x0D, (a>>2) & 0xFF); _write_vga_register(_crtc, 0x0C, (a>>10) & 0xFF); ENABLE(); if (_timer_use_retrace) { /* store low 2 bits where the timer handler will find them */ _retrace_hpp_value = (a&3)<<1; } else { /* change instantly */ _write_hpp((a&3)<<1); } return 0; } /* poll_modex_scroll: * Returns non-zero if there is a scroll waiting to take place, previously * set by request_modex_scroll(). Only works if vertical retrace interrupts * are enabled. */ static int poll_modex_scroll(void) { if ((_retrace_hpp_value < 0) || (!_timer_use_retrace)) return FALSE; return TRUE; } /* modex_enable_triple_buffer: * Tries to turn on triple buffering mode, if that is currently possible. */ static void modex_enable_triple_buffer(void) { if ((!_timer_use_retrace) && (timer_can_simulate_retrace())) timer_simulate_retrace(TRUE); if (_timer_use_retrace) { gfx_modex.request_scroll = request_modex_scroll; gfx_modex.poll_scroll = poll_modex_scroll; } } /* x_write: * Inline helper for the C drawing functions: writes a pixel onto a * mode-X bitmap, performing clipping but ignoring the drawing mode. */ static INLINE void x_write(BITMAP *bmp, int x, int y, int color) { if ((x >= bmp->cl) && (x < bmp->cr) && (y >= bmp->ct) && (y < bmp->cb)) { outportw(0x3C4, (0x100<<(x&3))|2); bmp_write8((unsigned long)bmp->line[y]+(x>>2), color); } } /* _x_vline: * Draws a vertical line onto a mode-X screen. */ void _x_vline(BITMAP *bmp, int x, int y1, int y2, int color) { int c; if (y1 > y2) { c = y1; y1 = y2; y2 = c; } for (c=y1; c<=y2; c++) _x_putpixel(bmp, x, c, color); } /* _x_draw_sprite_v_flip: * Draws a vertically flipped sprite onto a mode-X screen. */ void _x_draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y) { int c1, c2; bmp_select(bmp); for (c1=0; c1h; c1++) for (c2=0; c2w; c2++) if (sprite->line[sprite->h-1-c1][c2]) x_write(bmp, x+c2, y+c1, sprite->line[sprite->h-1-c1][c2]); } /* _x_draw_sprite_h_flip: * Draws a horizontally flipped sprite onto a mode-X screen. */ void _x_draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y) { int c1, c2; bmp_select(bmp); for (c1=0; c1h; c1++) for (c2=0; c2w; c2++) if (sprite->line[c1][sprite->w-1-c2]) x_write(bmp, x+c2, y+c1, sprite->line[c1][sprite->w-1-c2]); } /* _x_draw_sprite_vh_flip: * Draws a diagonally flipped sprite onto a mode-X screen. */ void _x_draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y) { int c1, c2; bmp_select(bmp); for (c1=0; c1h; c1++) for (c2=0; c2w; c2++) if (sprite->line[sprite->h-1-c1][sprite->w-1-c2]) x_write(bmp, x+c2, y+c1, sprite->line[sprite->h-1-c1][sprite->w-1-c2]); } /* _x_draw_trans_sprite: * Draws a translucent sprite onto a mode-X screen. */ void _x_draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) { int sx, sy, sy2; int dx, dy; int xlen, ylen; int plane; unsigned char *src; unsigned long addr; sx = sy = 0; if (bmp->clip) { if (x < bmp->cl) { sx = bmp->cl - x; x = bmp->cl; } if (y < bmp->ct) { sy = bmp->ct - y; y = bmp->ct; } xlen = MIN(sprite->w - sx, bmp->cr - x); ylen = MIN(sprite->h - sy, bmp->cb - y); } else { xlen = sprite->w; ylen = sprite->h; } if ((xlen <= 0) || (ylen <= 0)) return; bmp_select(bmp); sy2 = sy; for (plane=0; plane<4; plane++) { sy = sy2; outportw(0x3C4, (0x100<<((x+plane)&3))|2); outportw(0x3CE, (((x+plane)&3)<<8)|4); for (dy=0; dyline[sy]+sx+plane; addr = (unsigned long)bmp->line[y+dy]+((x+plane)>>2); for (dx=plane; dxdata[*src][bmp_read8(addr)]); addr++; src+=4; } sy++; } } } /* _x_draw_lit_sprite: * Draws a lit sprite onto a mode-X screen. */ void _x_draw_lit_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int color) { int sx, sy, sy2; int dx, dy; int xlen, ylen; int plane; unsigned char *src; unsigned long addr; sx = sy = 0; if (bmp->clip) { if (x < bmp->cl) { sx = bmp->cl - x; x = bmp->cl; } if (y < bmp->ct) { sy = bmp->ct - y; y = bmp->ct; } xlen = MIN(sprite->w - sx, bmp->cr - x); ylen = MIN(sprite->h - sy, bmp->cb - y); } else { xlen = sprite->w; ylen = sprite->h; } if ((xlen <= 0) || (ylen <= 0)) return; bmp_select(bmp); sy2 = sy; for (plane=0; plane<4; plane++) { sy = sy2; outportw(0x3C4, (0x100<<((x+plane)&3))|2); for (dy=0; dyline[sy]+sx+plane; addr = (unsigned long)bmp->line[y+dy]+((x+plane)>>2); for (dx=plane; dxdata[color][*src]); addr++; src+=4; } sy++; } } } /* _x_draw_rle_sprite: * Draws an RLE sprite onto a mode-X screen. */ void _x_draw_rle_sprite(BITMAP *bmp, AL_CONST RLE_SPRITE *sprite, int x, int y) { AL_CONST signed char *p = sprite->dat; int c; int x_pos, y_pos; int lgap, width; unsigned long addr; bmp_select(bmp); y_pos = 0; /* clip on the top */ while (y+y_pos < bmp->ct) { y_pos++; if ((y_pos >= sprite->h) || (y+y_pos >= bmp->cb)) return; while (*p) p++; p++; } /* x axis clip */ lgap = MAX(bmp->cl-x, 0); width = MIN(sprite->w, bmp->cr-x); if (width <= lgap) return; /* draw it */ while ((y_posh) && (y+y_pos < bmp->cb)) { addr = (unsigned long)bmp->line[y+y_pos]; x_pos = 0; c = *(p++); /* skip pixels on the left */ while (x_pos < lgap) { if (c > 0) { /* skip a run of solid pixels */ if (c > lgap-x_pos) { p += lgap-x_pos; c -= lgap-x_pos; x_pos = lgap; break; } x_pos += c; p += c; } else { /* skip a run of zeros */ if (-c > lgap-x_pos) { c += lgap-x_pos; x_pos = lgap; break; } x_pos -= c; } c = *(p++); } /* draw a line of the sprite */ for (;;) { if (c > 0) { /* draw a run of solid pixels */ c = MIN(c, width-x_pos); while (c > 0) { outportw(0x3C4, (0x100<<((x+x_pos)&3))|2); bmp_write8(addr+((x+x_pos)>>2), *p); x_pos++; p++; c--; } } else { /* skip a run of zeros */ x_pos -= c; } if (x_pos < width) c = (*p++); else break; } /* skip pixels on the right */ if (x_pos < sprite->w) { while (*p) p++; p++; } y_pos++; } } /* _x_draw_trans_rle_sprite: * Draws an RLE sprite onto a mode-X screen. */ void _x_draw_trans_rle_sprite(BITMAP *bmp, AL_CONST RLE_SPRITE *sprite, int x, int y) { AL_CONST signed char *p = sprite->dat; int c; int x_pos, y_pos; int lgap, width; unsigned long addr, a; bmp_select(bmp); y_pos = 0; /* clip on the top */ while (y+y_pos < bmp->ct) { y_pos++; if ((y_pos >= sprite->h) || (y+y_pos >= bmp->cb)) return; while (*p) p++; p++; } /* x axis clip */ lgap = MAX(bmp->cl-x, 0); width = MIN(sprite->w, bmp->cr-x); if (width <= lgap) return; /* draw it */ while ((y_posh) && (y+y_pos < bmp->cb)) { addr = (unsigned long)bmp->line[y+y_pos]; x_pos = 0; c = *(p++); /* skip pixels on the left */ while (x_pos < lgap) { if (c > 0) { /* skip a run of solid pixels */ if (c > lgap-x_pos) { p += lgap-x_pos; c -= lgap-x_pos; x_pos = lgap; break; } x_pos += c; p += c; } else { /* skip a run of zeros */ if (-c > lgap-x_pos) { c += lgap-x_pos; x_pos = lgap; break; } x_pos -= c; } c = *(p++); } /* draw a line of the sprite */ for (;;) { if (c > 0) { /* draw a run of solid pixels */ c = MIN(c, width-x_pos); while (c > 0) { outportw(0x3C4, (0x100<<((x+x_pos)&3))|2); outportw(0x3CE, (((x+x_pos)&3)<<8)|4); a = addr+((x+x_pos)>>2); bmp_write8(a, color_map->data[*p][bmp_read8(a)]); x_pos++; p++; c--; } } else { /* skip a run of zeros */ x_pos -= c; } if (x_pos < width) c = (*p++); else break; } /* skip pixels on the right */ if (x_pos < sprite->w) { while (*p) p++; p++; } y_pos++; } } /* _x_draw_lit_rle_sprite: * Draws a tinted RLE sprite onto a mode-X screen. */ void _x_draw_lit_rle_sprite(BITMAP *bmp, AL_CONST RLE_SPRITE *sprite, int x, int y, int color) { AL_CONST signed char *p = sprite->dat; int c; int x_pos, y_pos; int lgap, width; unsigned long addr; bmp_select(bmp); y_pos = 0; /* clip on the top */ while (y+y_pos < bmp->ct) { y_pos++; if ((y_pos >= sprite->h) || (y+y_pos >= bmp->cb)) return; while (*p) p++; p++; } /* x axis clip */ lgap = MAX(bmp->cl-x, 0); width = MIN(sprite->w, bmp->cr-x); if (width <= lgap) return; /* draw it */ while ((y_posh) && (y+y_pos < bmp->cb)) { addr = (unsigned long)bmp->line[y+y_pos]; x_pos = 0; c = *(p++); /* skip pixels on the left */ while (x_pos < lgap) { if (c > 0) { /* skip a run of solid pixels */ if (c > lgap-x_pos) { p += lgap-x_pos; c -= lgap-x_pos; x_pos = lgap; break; } x_pos += c; p += c; } else { /* skip a run of zeros */ if (-c > lgap-x_pos) { c += lgap-x_pos; x_pos = lgap; break; } x_pos -= c; } c = *(p++); } /* draw a line of the sprite */ for (;;) { if (c > 0) { /* draw a run of solid pixels */ c = MIN(c, width-x_pos); while (c > 0) { outportw(0x3C4, (0x100<<((x+x_pos)&3))|2); bmp_write8(addr+((x+x_pos)>>2), color_map->data[color][*p]); x_pos++; p++; c--; } } else { /* skip a run of zeros */ x_pos -= c; } if (x_pos < width) c = (*p++); else break; } /* skip pixels on the right */ if (x_pos < sprite->w) { while (*p) p++; p++; } y_pos++; } } /* _x_draw_character: * Draws a character from a proportional font onto a mode-X screen. */ void _x_draw_character(BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg) { int c1, c2; bmp_select(bmp); for (c1=0; c1h; c1++) { for (c2=0; c2w; c2++) { if (sprite->line[c1][c2]) x_write(bmp, x+c2, y+c1, color); else { if (bg >= 0) x_write(bmp, x+c2, y+c1, bg); } } } } /* _x_draw_glyph: * Draws monochrome text onto a mode-X screen. */ void _x_draw_glyph(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg) { AL_CONST unsigned char *data = glyph->dat; AL_CONST unsigned char *dat; unsigned long addr; int w = glyph->w; int h = glyph->h; int stride = (w+7)/8; int lgap = 0; int plane, d, i, j, k; if (bmp->clip) { /* clip the top */ if (y < bmp->ct) { d = bmp->ct - y; h -= d; if (h <= 0) return; data += d*stride; y = bmp->ct; } /* clip the bottom */ if (y+h >= bmp->cb) { h = bmp->cb - y; if (h <= 0) return; } /* clip the left */ if (x < bmp->cl) { d = bmp->cl - x; w -= d; if (w <= 0) return; data += d/8; lgap = d&7; x = bmp->cl; } /* clip the right */ if (x+w >= bmp->cr) { w = bmp->cr - x; if (w <= 0) return; } } /* draw it */ bmp_select(bmp); for (plane=0; plane < MIN(w, 4); plane++) { outportw(0x3C4, (0x100<<((x+plane)&3))|2); dat = data; for (j=0; jline[y+j]+((x+plane)>>2); d = dat[(plane+lgap)/8]; k = 0x80 >> ((plane+lgap)&7); i = plane; for (;;) { if (d & k) bmp_write8(addr, color); else if (bg >= 0) bmp_write8(addr, bg); i += 4; if (i >= w) break; k >>= 4; if (!k) { d = dat[(i+lgap)/8]; k = 0x80 >> ((i+lgap)&7); } addr++; } dat += stride; } } } /* modex_fetch_mode_list: * Creates a list of of currently implemented ModeX modes. */ static GFX_MODE_LIST *modex_fetch_mode_list(void) { GFX_MODE_LIST *mode_list; mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!mode_list) return NULL; mode_list->mode = _AL_MALLOC(sizeof(modex_gfx_modes)); if (!mode_list->mode) return NULL; memcpy(mode_list->mode, modex_gfx_modes, sizeof(modex_gfx_modes)); mode_list->num_modes = sizeof(modex_gfx_modes) / sizeof(GFX_MODE) - 1; return mode_list; } /* really_split_modex_screen: * Enables a horizontal split screen at the specified line. * Based on code from Paul Fenwick's XLIBDJ, which was in turn based * on Michael Abrash's routines in PC Techniques, June 1991. */ static void really_split_modex_screen(int line) { if (gfx_driver != &gfx_modex) return; if (line < 0) line = 0; else if (line >= SCREEN_H) line = 0; _screen_split_position = line; /* adjust the line for double-scanned modes */ if (SCREEN_H <= 150) line <<= 2; else if (SCREEN_H <= 300) line <<= 1; /* disable panning of the split screen area */ _alter_vga_register(0x3C0, 0x30, 0x20, 0x20); /* set the line compare registers */ _write_vga_register(0x3D4, 0x18, (line-1) & 0xFF); _alter_vga_register(0x3D4, 7, 0x10, ((line-1) & 0x100) >> 4); _alter_vga_register(0x3D4, 9, 0x40, ((line-1) & 0x200) >> 3); } #endif /* (!defined ALLEGRO_LINUX) || ((defined ALLEGRO_LINUX_VGA) && ... */ #if (defined ALLEGRO_LINUX_VGA) && (defined ALLEGRO_MODULE) /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init_modex(int system_driver) { if (system_driver == SYSTEM_LINUX) _unix_register_gfx_driver(GFX_MODEX, &gfx_modex, TRUE, FALSE); } #endif /* (defined ALLEGRO_LINUX_VGA) && (defined ALLEGRO_MODULE) */ #endif /* ALLEGRO_GFX_HAS_VGA */ allegro-4.4.3.1/src/misc/fm_instr.h0000664000175000017500000006526013437077643016025 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * General Midi sound bank for the Adlib FM synth. This must only be * included once, from adlib.c. There are two alternative versions of * the patches here: change the "#if 1" to "#if 0" if you want to * use the older set. */ typedef struct FM_INSTRUMENT { unsigned char characteristic1; unsigned char characteristic2; unsigned char level1; unsigned char level2; unsigned char attackdecay1; unsigned char attackdecay2; unsigned char sustainrelease1; unsigned char sustainrelease2; unsigned char wave1; unsigned char wave2; unsigned char feedback; unsigned char freq; unsigned char key; unsigned char type; } FM_INSTRUMENT; static FM_INSTRUMENT fm_instrument[128] = { #if 1 /* This set of GM instrument patches was provided by Jorrit Rouwe... */ { 0x21, 0x21, 0x8f, 0x0c, 0xf2, 0xf2, 0x45, 0x76, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Acoustic Grand */ { 0x31, 0x21, 0x4b, 0x09, 0xf2, 0xf2, 0x54, 0x56, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Bright Acoustic */ { 0x31, 0x21, 0x49, 0x09, 0xf2, 0xf2, 0x55, 0x76, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Electric Grand */ { 0xb1, 0x61, 0x0e, 0x09, 0xf2, 0xf3, 0x3b, 0x0b, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Honky-Tonk */ { 0x01, 0x21, 0x57, 0x09, 0xf1, 0xf1, 0x38, 0x28, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Piano 1 */ { 0x01, 0x21, 0x93, 0x09, 0xf1, 0xf1, 0x38, 0x28, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Piano 2 */ { 0x21, 0x36, 0x80, 0x17, 0xa2, 0xf1, 0x01, 0xd5, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Harpsichord */ { 0x01, 0x01, 0x92, 0x09, 0xc2, 0xc2, 0xa8, 0x58, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Clav */ { 0x0c, 0x81, 0x5c, 0x09, 0xf6, 0xf3, 0x54, 0xb5, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Celesta */ { 0x07, 0x11, 0x97, 0x89, 0xf6, 0xf5, 0x32, 0x11, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Glockenspiel */ { 0x17, 0x01, 0x21, 0x09, 0x56, 0xf6, 0x04, 0x04, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Music Box */ { 0x18, 0x81, 0x62, 0x09, 0xf3, 0xf2, 0xe6, 0xf6, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Vibraphone */ { 0x18, 0x21, 0x23, 0x09, 0xf7, 0xe5, 0x55, 0xd8, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Marimba */ { 0x15, 0x01, 0x91, 0x09, 0xf6, 0xf6, 0xa6, 0xe6, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Xylophone */ { 0x45, 0x81, 0x59, 0x89, 0xd3, 0xa3, 0x82, 0xe3, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Tubular Bells */ { 0x03, 0x81, 0x49, 0x89, 0x74, 0xb3, 0x55, 0x05, 0x01, 0x00, 0x04, 0, 0, 0 }, /* Dulcimer */ { 0x71, 0x31, 0x92, 0x09, 0xf6, 0xf1, 0x14, 0x07, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Drawbar Organ */ { 0x72, 0x30, 0x14, 0x09, 0xc7, 0xc7, 0x58, 0x08, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Percussive Organ */ { 0x70, 0xb1, 0x44, 0x09, 0xaa, 0x8a, 0x18, 0x08, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Rock Organ */ { 0x23, 0xb1, 0x93, 0x09, 0x97, 0x55, 0x23, 0x14, 0x01, 0x00, 0x04, 0, 0, 0 }, /* Church Organ */ { 0x61, 0xb1, 0x13, 0x89, 0x97, 0x55, 0x04, 0x04, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Reed Organ */ { 0x24, 0xb1, 0x48, 0x09, 0x98, 0x46, 0x2a, 0x1a, 0x01, 0x00, 0x0c, 0, 0, 0 }, /* Accoridan */ { 0x61, 0x21, 0x13, 0x09, 0x91, 0x61, 0x06, 0x07, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Harmonica */ { 0x21, 0xa1, 0x13, 0x92, 0x71, 0x61, 0x06, 0x07, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Tango Accordian */ { 0x02, 0x41, 0x9c, 0x89, 0xf3, 0xf3, 0x94, 0xc8, 0x01, 0x00, 0x0c, 0, 0, 0 }, /* Acoustic Guitar(nylon) */ { 0x03, 0x11, 0x54, 0x09, 0xf3, 0xf1, 0x9a, 0xe7, 0x01, 0x00, 0x0c, 0, 0, 0 }, /* Acoustic Guitar(steel) */ { 0x23, 0x21, 0x5f, 0x09, 0xf1, 0xf2, 0x3a, 0xf8, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Guitar(jazz) */ { 0x03, 0x21, 0x87, 0x89, 0xf6, 0xf3, 0x22, 0xf8, 0x01, 0x00, 0x06, 0, 0, 0 }, /* Electric Guitar(clean) */ { 0x03, 0x21, 0x47, 0x09, 0xf9, 0xf6, 0x54, 0x3a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Guitar(muted) */ { 0x23, 0x21, 0x4a, 0x0e, 0x91, 0x84, 0x41, 0x19, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Overdriven Guitar */ { 0x23, 0x21, 0x4a, 0x09, 0x95, 0x94, 0x19, 0x19, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Distortion Guitar */ { 0x09, 0x84, 0xa1, 0x89, 0x20, 0xd1, 0x4f, 0xf8, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Guitar Harmonics */ { 0x21, 0xa2, 0x1e, 0x09, 0x94, 0xc3, 0x06, 0xa6, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Acoustic Bass */ { 0x31, 0x31, 0x12, 0x09, 0xf1, 0xf1, 0x28, 0x18, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Electric Bass(finger) */ { 0x31, 0x31, 0x8d, 0x09, 0xf1, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Electric Bass(pick) */ { 0x31, 0x32, 0x5b, 0x09, 0x51, 0x71, 0x28, 0x48, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Fretless Bass */ { 0x01, 0x21, 0x8b, 0x49, 0xa1, 0xf2, 0x9a, 0xdf, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Slap Bass 1 */ { 0x21, 0x21, 0x8b, 0x11, 0xa2, 0xa1, 0x16, 0xdf, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Slap Bass 2 */ { 0x31, 0x31, 0x8b, 0x09, 0xf4, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Synth Bass 1 */ { 0x31, 0x31, 0x12, 0x09, 0xf1, 0xf1, 0x28, 0x18, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Synth Bass 2 */ { 0x31, 0x21, 0x15, 0x09, 0xdd, 0x56, 0x13, 0x26, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Violin */ { 0x31, 0x21, 0x16, 0x09, 0xdd, 0x66, 0x13, 0x06, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Viola */ { 0x71, 0x31, 0x49, 0x09, 0xd1, 0x61, 0x1c, 0x0c, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Cello */ { 0x21, 0x23, 0x4d, 0x89, 0x71, 0x72, 0x12, 0x06, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Contrabass */ { 0xf1, 0xe1, 0x40, 0x09, 0xf1, 0x6f, 0x21, 0x16, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Tremolo Strings */ { 0x02, 0x01, 0x1a, 0x89, 0xf5, 0x85, 0x75, 0x35, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Pizzicato Strings */ { 0x02, 0x01, 0x1d, 0x89, 0xf5, 0xf3, 0x75, 0xf4, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Orchestral Strings */ { 0x10, 0x11, 0x41, 0x09, 0xf5, 0xf2, 0x05, 0xc3, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Timpani */ { 0x21, 0xa2, 0x9b, 0x0a, 0xb1, 0x72, 0x25, 0x08, 0x01, 0x00, 0x0e, 0, 0, 0 }, /* String Ensemble 1 */ { 0xa1, 0x21, 0x98, 0x09, 0x7f, 0x3f, 0x03, 0x07, 0x01, 0x01, 0x00, 0, 0, 0 }, /* String Ensemble 2 */ { 0xa1, 0x61, 0x93, 0x09, 0xc1, 0x4f, 0x12, 0x05, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* SynthStrings 1 */ { 0x21, 0x61, 0x18, 0x09, 0xc1, 0x4f, 0x22, 0x05, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* SynthStrings 2 */ { 0x31, 0x72, 0x5b, 0x8c, 0xf4, 0x8a, 0x15, 0x05, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Choir Aahs */ { 0xa1, 0x61, 0x90, 0x09, 0x74, 0x71, 0x39, 0x67, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Voice Oohs */ { 0x71, 0x72, 0x57, 0x09, 0x54, 0x7a, 0x05, 0x05, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Synth Voice */ { 0x90, 0x41, 0x00, 0x09, 0x54, 0xa5, 0x63, 0x45, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Orchestra Hit */ { 0x21, 0x21, 0x92, 0x0a, 0x85, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Trumpet */ { 0x21, 0x21, 0x94, 0x0e, 0x75, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Trombone */ { 0x21, 0x61, 0x94, 0x09, 0x76, 0x82, 0x15, 0x37, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Tuba */ { 0x31, 0x21, 0x43, 0x09, 0x9e, 0x62, 0x17, 0x2c, 0x01, 0x01, 0x02, 0, 0, 0 }, /* Muted Trumpet */ { 0x21, 0x21, 0x9b, 0x09, 0x61, 0x7f, 0x6a, 0x0a, 0x00, 0x00, 0x02, 0, 0, 0 }, /* French Horn */ { 0x61, 0x22, 0x8a, 0x0f, 0x75, 0x74, 0x1f, 0x0f, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Brass Section */ { 0xa1, 0x21, 0x86, 0x8c, 0x72, 0x71, 0x55, 0x18, 0x01, 0x00, 0x00, 0, 0, 0 }, /* SynthBrass 1 */ { 0x21, 0x21, 0x4d, 0x09, 0x54, 0xa6, 0x3c, 0x1c, 0x00, 0x00, 0x08, 0, 0, 0 }, /* SynthBrass 2 */ { 0x31, 0x61, 0x8f, 0x09, 0x93, 0x72, 0x02, 0x0b, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Soprano Sax */ { 0x31, 0x61, 0x8e, 0x09, 0x93, 0x72, 0x03, 0x09, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Alto Sax */ { 0x31, 0x61, 0x91, 0x09, 0x93, 0x82, 0x03, 0x09, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Tenor Sax */ { 0x31, 0x61, 0x8e, 0x09, 0x93, 0x72, 0x0f, 0x0f, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Baritone Sax */ { 0x21, 0x21, 0x4b, 0x09, 0xaa, 0x8f, 0x16, 0x0a, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Oboe */ { 0x31, 0x21, 0x90, 0x09, 0x7e, 0x8b, 0x17, 0x0c, 0x01, 0x01, 0x06, 0, 0, 0 }, /* English Horn */ { 0x31, 0x32, 0x81, 0x09, 0x75, 0x61, 0x19, 0x19, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Bassoon */ { 0x32, 0x21, 0x90, 0x09, 0x9b, 0x72, 0x21, 0x17, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Clarinet */ { 0xe1, 0xe1, 0x1f, 0x09, 0x85, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Piccolo */ { 0xe1, 0xe1, 0x46, 0x09, 0x88, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Flute */ { 0xa1, 0x21, 0x9c, 0x09, 0x75, 0x75, 0x1f, 0x0a, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Recorder */ { 0x31, 0x21, 0x8b, 0x09, 0x84, 0x65, 0x58, 0x1a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Pan Flute */ { 0xe1, 0xa1, 0x4c, 0x09, 0x66, 0x65, 0x56, 0x26, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Blown Bottle */ { 0x62, 0xa1, 0xcb, 0x09, 0x76, 0x55, 0x46, 0x36, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Skakuhachi */ { 0x62, 0xa1, 0xa2, 0x09, 0x57, 0x56, 0x07, 0x07, 0x00, 0x00, 0x0b, 0, 0, 0 }, /* Whistle */ { 0x62, 0xa1, 0x9c, 0x09, 0x77, 0x76, 0x07, 0x07, 0x00, 0x00, 0x0b, 0, 0, 0 }, /* Ocarina */ { 0x22, 0x21, 0x59, 0x09, 0xff, 0xff, 0x03, 0x0f, 0x02, 0x00, 0x00, 0, 0, 0 }, /* Lead 1 (square) */ { 0x21, 0x21, 0x0e, 0x09, 0xff, 0xff, 0x0f, 0x0f, 0x01, 0x01, 0x00, 0, 0, 0 }, /* Lead 2 (sawtooth) */ { 0x22, 0x21, 0x46, 0x89, 0x86, 0x64, 0x55, 0x18, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Lead 3 (calliope) */ { 0x21, 0xa1, 0x45, 0x09, 0x66, 0x96, 0x12, 0x0a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Lead 4 (chiff) */ { 0x21, 0x22, 0x8b, 0x09, 0x92, 0x91, 0x2a, 0x2a, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Lead 5 (charang) */ { 0xa2, 0x61, 0x9e, 0x49, 0xdf, 0x6f, 0x05, 0x07, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Lead 6 (voice) */ { 0x20, 0x60, 0x1a, 0x09, 0xef, 0x8f, 0x01, 0x06, 0x00, 0x02, 0x00, 0, 0, 0 }, /* Lead 7 (fifths) */ { 0x21, 0x21, 0x8f, 0x86, 0xf1, 0xf4, 0x29, 0x09, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Lead 8 (bass+lead) */ { 0x77, 0xa1, 0xa5, 0x09, 0x53, 0xa0, 0x94, 0x05, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Pad 1 (new age) */ { 0x61, 0xb1, 0x1f, 0x89, 0xa8, 0x25, 0x11, 0x03, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Pad 2 (warm) */ { 0x61, 0x61, 0x17, 0x09, 0x91, 0x55, 0x34, 0x16, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Pad 3 (polysynth) */ { 0x71, 0x72, 0x5d, 0x09, 0x54, 0x6a, 0x01, 0x03, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Pad 4 (choir) */ { 0x21, 0xa2, 0x97, 0x09, 0x21, 0x42, 0x43, 0x35, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Pad 5 (bowed) */ { 0xa1, 0x21, 0x1c, 0x09, 0xa1, 0x31, 0x77, 0x47, 0x01, 0x01, 0x00, 0, 0, 0 }, /* Pad 6 (metallic) */ { 0x21, 0x61, 0x89, 0x0c, 0x11, 0x42, 0x33, 0x25, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Pad 7 (halo) */ { 0xa1, 0x21, 0x15, 0x09, 0x11, 0xcf, 0x47, 0x07, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Pad 8 (sweep) */ { 0x3a, 0x51, 0xce, 0x09, 0xf8, 0x86, 0xf6, 0x02, 0x00, 0x00, 0x02, 0, 0, 0 }, /* FX 1 (rain) */ { 0x21, 0x21, 0x15, 0x09, 0x21, 0x41, 0x23, 0x13, 0x01, 0x00, 0x00, 0, 0, 0 }, /* FX 2 (soundtrack) */ { 0x06, 0x01, 0x5b, 0x09, 0x74, 0xa5, 0x95, 0x72, 0x00, 0x00, 0x00, 0, 0, 0 }, /* FX 3 (crystal) */ { 0x22, 0x61, 0x92, 0x8c, 0xb1, 0xf2, 0x81, 0x26, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* FX 4 (atmosphere) */ { 0x41, 0x42, 0x4d, 0x09, 0xf1, 0xf2, 0x51, 0xf5, 0x01, 0x00, 0x00, 0, 0, 0 }, /* FX 5 (brightness) */ { 0x61, 0xa3, 0x94, 0x89, 0x11, 0x11, 0x51, 0x13, 0x01, 0x00, 0x06, 0, 0, 0 }, /* FX 6 (goblins) */ { 0x61, 0xa1, 0x8c, 0x89, 0x11, 0x1d, 0x31, 0x03, 0x00, 0x00, 0x06, 0, 0, 0 }, /* FX 7 (echoes) */ { 0xa4, 0x61, 0x4c, 0x09, 0xf3, 0x81, 0x73, 0x23, 0x01, 0x00, 0x04, 0, 0, 0 }, /* FX 8 (sci-fi) */ { 0x02, 0x07, 0x85, 0x0c, 0xd2, 0xf2, 0x53, 0xf6, 0x00, 0x01, 0x00, 0, 0, 0 }, /* Sitar */ { 0x11, 0x13, 0x0c, 0x89, 0xa3, 0xa2, 0x11, 0xe5, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Banjo */ { 0x11, 0x11, 0x06, 0x09, 0xf6, 0xf2, 0x41, 0xe6, 0x01, 0x02, 0x04, 0, 0, 0 }, /* Shamisen */ { 0x93, 0x91, 0x91, 0x09, 0xd4, 0xeb, 0x32, 0x11, 0x00, 0x01, 0x08, 0, 0, 0 }, /* Koto */ { 0x04, 0x01, 0x4f, 0x09, 0xfa, 0xc2, 0x56, 0x05, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Kalimba */ { 0x21, 0x22, 0x49, 0x09, 0x7c, 0x6f, 0x20, 0x0c, 0x00, 0x01, 0x06, 0, 0, 0 }, /* Bagpipe */ { 0x31, 0x21, 0x85, 0x09, 0xdd, 0x56, 0x33, 0x16, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Fiddle */ { 0x20, 0x21, 0x04, 0x8a, 0xda, 0x8f, 0x05, 0x0b, 0x02, 0x00, 0x06, 0, 0, 0 }, /* Shanai */ { 0x05, 0x03, 0x6a, 0x89, 0xf1, 0xc3, 0xe5, 0xe5, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Tinkle Bell */ { 0x07, 0x02, 0x15, 0x09, 0xec, 0xf8, 0x26, 0x16, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Agogo */ { 0x05, 0x01, 0x9d, 0x09, 0x67, 0xdf, 0x35, 0x05, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Steel Drums */ { 0x18, 0x12, 0x96, 0x09, 0xfa, 0xf8, 0x28, 0xe5, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Woodblock */ { 0x10, 0x00, 0x86, 0x0c, 0xa8, 0xfa, 0x07, 0x03, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Taiko Drum */ { 0x11, 0x10, 0x41, 0x0c, 0xf8, 0xf3, 0x47, 0x03, 0x02, 0x00, 0x04, 0, 0, 0 }, /* Melodic Tom */ { 0x01, 0x10, 0x8e, 0x09, 0xf1, 0xf3, 0x06, 0x02, 0x02, 0x00, 0x0e, 0, 0, 0 }, /* Synth Drum */ { 0x0e, 0xc0, 0x00, 0x09, 0x1f, 0x1f, 0x00, 0xff, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Reverse Cymbal */ { 0x06, 0x03, 0x80, 0x91, 0xf8, 0x56, 0x24, 0x84, 0x00, 0x02, 0x0e, 0, 0, 0 }, /* Guitar Fret Noise */ { 0x0e, 0xd0, 0x00, 0x0e, 0xf8, 0x34, 0x00, 0x04, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Breath Noise */ { 0x0e, 0xc0, 0x00, 0x09, 0xf6, 0x1f, 0x00, 0x02, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Seashore */ { 0xd5, 0xda, 0x95, 0x49, 0x37, 0x56, 0xa3, 0x37, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Bird Tweet */ { 0x35, 0x14, 0x5c, 0x11, 0xb2, 0xf4, 0x61, 0x15, 0x02, 0x00, 0x0a, 0, 0, 0 }, /* Telephone ring */ { 0x0e, 0xd0, 0x00, 0x09, 0xf6, 0x4f, 0x00, 0xf5, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Helicopter */ { 0x26, 0xe4, 0x00, 0x09, 0xff, 0x12, 0x01, 0x16, 0x00, 0x01, 0x0e, 0, 0, 0 }, /* Applause */ { 0x00, 0x00, 0x00, 0x09, 0xf3, 0xf6, 0xf0, 0xc9, 0x00, 0x02, 0x0e, 0, 0, 0 } /* Gunshot */ #else /* This alternative patch set was taken from the MID-KIT library by * John Pollard. These sounds were used by Allegro versions 2.2 and * earlier. */ { 0x21, 0x31, 0x4F, 0x00, 0xF2, 0xD2, 0x52, 0x73, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Acoustic Grand */ { 0x01, 0x11, 0x4F, 0x00, 0xF1, 0xD2, 0x53, 0x74, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Bright Acoustic */ { 0x13, 0x11, 0xC6, 0x00, 0xF2, 0xF1, 0xF5, 0xF5, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Electric Grand */ { 0x31, 0x31, 0x8E, 0x80, 0xF1, 0xF3, 0xF9, 0xF9, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Honky-Tonk */ { 0x01, 0x01, 0x4F, 0x04, 0xF1, 0xD2, 0x50, 0x7C, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Electric Piano 1 */ { 0x02, 0x02, 0x22, 0x00, 0xF2, 0xF5, 0x13, 0x43, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Electric Piano 2 */ { 0x31, 0x32, 0x8E, 0x80, 0xF1, 0xF3, 0xF9, 0xF9, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Harpsichord */ { 0x01, 0x11, 0x49, 0x00, 0xF1, 0xF1, 0x53, 0x74, 0x01, 0x02, 0x06, 0, 0, 0 }, /* Clav */ { 0x17, 0x12, 0x4F, 0x08, 0xF2, 0xF2, 0x61, 0x74, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Celesta */ { 0x07, 0x12, 0x4F, 0x0A, 0xF2, 0xF2, 0x60, 0x72, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Glockenspiel */ { 0x17, 0x12, 0x4F, 0x08, 0xF2, 0xF1, 0x61, 0xB2, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Music Box */ { 0x93, 0x91, 0x97, 0x80, 0xAA, 0xAC, 0x12, 0x21, 0x02, 0x00, 0x0E, 0, 0, 0 }, /* Vibraphone */ { 0x05, 0x01, 0x4E, 0x00, 0xDA, 0xF9, 0x25, 0x15, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Marimba */ { 0x06, 0xC4, 0x00, 0x00, 0xFF, 0xF8, 0xF0, 0xB5, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Xylophone */ { 0x17, 0x02, 0x4F, 0x10, 0xF2, 0xF2, 0x60, 0x72, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Tubular Bells */ { 0x03, 0x17, 0x0F, 0x0B, 0xF1, 0xF2, 0x53, 0x74, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Dulcimer */ { 0x64, 0x21, 0x86, 0x80, 0xFF, 0xFF, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0, 0, 0 }, /* Drawbar Organ */ { 0x24, 0x22, 0x80, 0x40, 0xFF, 0xFF, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0, 0, 0 }, /* Percussive Organ */ { 0x01, 0x31, 0x4F, 0x00, 0xF0, 0x90, 0xFF, 0x0F, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Rock Organ */ { 0xB2, 0xB0, 0xC0, 0x80, 0x9F, 0xB4, 0x06, 0x0F, 0x01, 0x01, 0x09, 0, 0, 0 }, /* Church Organ */ { 0x01, 0x33, 0x4F, 0x08, 0xF0, 0x90, 0xFF, 0x0F, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Reed Organ */ { 0x24, 0x31, 0x4F, 0x10, 0xF2, 0x92, 0x0B, 0x0B, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Accoridan */ { 0x21, 0x62, 0x15, 0x80, 0x51, 0x72, 0x03, 0x67, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Harmonica */ { 0xE0, 0xE1, 0xCE, 0x00, 0xF5, 0xF4, 0xAF, 0x0F, 0x01, 0x01, 0x0C, 0, 0, 0 }, /* Tango Accordian */ { 0x13, 0x11, 0x93, 0x80, 0xFF, 0xFF, 0x21, 0x03, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Acoustic Guitar(nylon) */ { 0x11, 0x11, 0x8B, 0x80, 0xFF, 0xFF, 0x01, 0x03, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Acoustic Guitar(steel) */ { 0x03, 0x11, 0x5E, 0x00, 0xF5, 0xF2, 0x71, 0x83, 0x01, 0x00, 0x0E, 0, 0, 0 }, /* Electric Guitar(jazz) */ { 0x21, 0x06, 0x40, 0x80, 0xF1, 0xF4, 0x31, 0x44, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Guitar(clean) */ { 0x01, 0x01, 0x11, 0x00, 0xF2, 0xF5, 0x1F, 0x88, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Electric Guitar(muted) */ { 0x31, 0x32, 0x48, 0x00, 0xF1, 0xF2, 0x53, 0x27, 0x00, 0x02, 0x06, 0, 0, 0 }, /* Overdriven Guitar */ { 0x62, 0xE6, 0x40, 0x03, 0x91, 0xC1, 0x1A, 0x1A, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Distortion Guitar */ { 0xE1, 0xE7, 0x16, 0x40, 0x71, 0xF0, 0xAE, 0x7E, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Guitar Harmonics */ { 0x01, 0x00, 0x00, 0x00, 0x94, 0x83, 0xB6, 0x26, 0x00, 0x00, 0x01, 0, 0, 0 }, /* Acoustic Bass */ { 0x00, 0x01, 0x23, 0x00, 0xC1, 0xF3, 0xEE, 0xDE, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Electric Bass(finger) */ { 0x50, 0x00, 0x00, 0x00, 0xFB, 0xF3, 0x71, 0xB9, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Bass(pick) */ { 0x30, 0x20, 0x1E, 0x00, 0xF2, 0xF5, 0xEF, 0x78, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Fretless Bass */ { 0x00, 0x11, 0x40, 0x00, 0x95, 0xFF, 0x88, 0x03, 0x01, 0x00, 0x06, 0, 0, 0 }, /* Slap Bass 1 */ { 0x00, 0x00, 0x10, 0x00, 0xF5, 0xF5, 0xF7, 0xF7, 0x01, 0x02, 0x00, 0, 0, 0 }, /* Slap Bass 2 */ { 0x11, 0x31, 0x05, 0x00, 0xF9, 0xF1, 0x25, 0x34, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Synth Bass 1 */ { 0x00, 0x11, 0x4F, 0x00, 0xD5, 0xB3, 0x21, 0x01, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Synth Bass 2 */ { 0x70, 0x20, 0x1C, 0x00, 0x51, 0xB4, 0x03, 0x67, 0x02, 0x02, 0x0E, 0, 0, 0 }, /* Violin */ { 0xF0, 0xF1, 0xD0, 0x40, 0x52, 0x91, 0x11, 0xFE, 0x02, 0x01, 0x00, 0, 0, 0 }, /* Viola */ { 0xB0, 0xB1, 0xC5, 0x80, 0x52, 0x71, 0x11, 0xFE, 0x01, 0x01, 0x00, 0, 0, 0 }, /* Cello */ { 0xB0, 0xB0, 0xC5, 0x84, 0x52, 0x80, 0x11, 0xCF, 0x00, 0x01, 0x08, 0, 0, 0 }, /* Contrabass */ { 0xB1, 0x61, 0x8B, 0x40, 0x71, 0x62, 0x11, 0x15, 0x00, 0x01, 0x06, 0, 0, 0 }, /* Tremolo Strings */ { 0x31, 0x31, 0x9C, 0x80, 0xF1, 0xF5, 0xF9, 0xD5, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Pizzicato Strings */ { 0x91, 0x61, 0x4F, 0x40, 0xB3, 0xF7, 0x23, 0x06, 0x01, 0x01, 0x06, 0, 0, 0 }, /* Orchestral Strings */ { 0x10, 0x10, 0x25, 0x80, 0xF0, 0xD0, 0x05, 0x04, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Timpani */ { 0x30, 0x20, 0x1C, 0x00, 0x51, 0x64, 0x00, 0x65, 0x02, 0x02, 0x0E, 0, 0, 0 }, /* String Ensemble 1 */ { 0xB1, 0x61, 0x8B, 0x40, 0x71, 0x42, 0x11, 0x15, 0x00, 0x01, 0x06, 0, 0, 0 }, /* String Ensemble 2 */ { 0x31, 0x62, 0x1C, 0x02, 0x75, 0x54, 0x03, 0x44, 0x01, 0x01, 0x0E, 0, 0, 0 }, /* SynthStrings 1 */ { 0x21, 0x23, 0x16, 0x00, 0xB0, 0xD3, 0x81, 0x2C, 0x00, 0x01, 0x0C, 0, 0, 0 }, /* SynthStrings 2 */ { 0x41, 0xC2, 0x4F, 0x40, 0x71, 0x62, 0x53, 0x7C, 0x08, 0x00, 0x00, 0, 0, 0 }, /* Choir Aahs */ { 0x60, 0xE2, 0xA7, 0x81, 0x22, 0x10, 0xD6, 0x75, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Voice Oohs */ { 0x41, 0x42, 0x4F, 0x03, 0xF1, 0xF2, 0x73, 0x74, 0x01, 0x01, 0x06, 0, 0, 0 }, /* Synth Voice */ { 0x00, 0x00, 0x0F, 0x00, 0x91, 0x82, 0x05, 0x06, 0x00, 0x03, 0x00, 0, 0, 0 }, /* Orchestra Hit */ { 0x31, 0x62, 0x1C, 0x80, 0x41, 0xC2, 0x0B, 0x3B, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Trumpet */ { 0xB1, 0x61, 0x1C, 0x80, 0x41, 0xB2, 0x1F, 0x3B, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Trombone */ { 0x00, 0x21, 0x1D, 0x00, 0x52, 0xA3, 0x65, 0x76, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Tuba */ { 0x21, 0x22, 0x19, 0x80, 0x43, 0xA5, 0x8C, 0x2F, 0x00, 0x01, 0x0C, 0, 0, 0 }, /* Muted Trumpet */ { 0x21, 0x21, 0x9F, 0x80, 0x53, 0xBA, 0x5A, 0x1A, 0x00, 0x01, 0x0C, 0, 0, 0 }, /* French Horn */ { 0xE1, 0xE1, 0x55, 0x0A, 0x91, 0xA1, 0xAE, 0x9E, 0x01, 0x00, 0x0E, 0, 0, 0 }, /* Brass Section */ { 0x21, 0x61, 0x8E, 0x80, 0xBB, 0xB0, 0x29, 0x0A, 0x00, 0x00, 0x08, 0, 0, 0 }, /* SynthBrass 1 */ { 0xE1, 0xE1, 0x16, 0x06, 0x71, 0xA1, 0xAE, 0x9E, 0x00, 0x01, 0x0A, 0, 0, 0 }, /* SynthBrass 2 */ { 0xE0, 0xE2, 0x23, 0x00, 0x71, 0xA1, 0xAE, 0x9E, 0x02, 0x01, 0x0A, 0, 0, 0 }, /* Soprano Sax */ { 0x01, 0x12, 0x4F, 0x00, 0x71, 0x92, 0x53, 0x7C, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Alto Sax */ { 0x20, 0x32, 0x4E, 0x00, 0x71, 0x92, 0x68, 0x5E, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Tenor Sax */ { 0x10, 0x50, 0x4F, 0x00, 0x71, 0x92, 0x5B, 0x7B, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Baritone Sax */ { 0x21, 0x24, 0x96, 0x00, 0xF0, 0xC0, 0x09, 0x0A, 0x00, 0x01, 0x0A, 0, 0, 0 }, /* Oboe */ { 0xB1, 0xA2, 0xC5, 0x00, 0x6E, 0xDB, 0x17, 0x0E, 0x00, 0x01, 0x02, 0, 0, 0 }, /* English Horn */ { 0x30, 0x72, 0x4D, 0x00, 0xD5, 0x91, 0x19, 0x0A, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Bassoon */ { 0x32, 0x61, 0x9A, 0x02, 0x51, 0xB2, 0x1B, 0x3B, 0x00, 0x00, 0x0C, 0, 0, 0 }, /* Clarinet */ { 0x20, 0x22, 0x5B, 0x00, 0x00, 0xB0, 0x16, 0x15, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Piccolo */ { 0x21, 0xA1, 0x83, 0x40, 0x74, 0xA5, 0x17, 0x17, 0x00, 0x01, 0x07, 0, 0, 0 }, /* Flute */ { 0xE1, 0x60, 0xDB, 0x00, 0x7E, 0x86, 0x8F, 0x2A, 0x01, 0x00, 0x0E, 0, 0, 0 }, /* Recorder */ { 0x20, 0xE1, 0x5B, 0x40, 0x00, 0x60, 0x16, 0x15, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Pan Flute */ { 0x53, 0x00, 0x85, 0x00, 0x3F, 0x7E, 0x06, 0x07, 0x01, 0x00, 0x06, 0, 0, 0 }, /* Blown Bottle */ { 0xE0, 0x61, 0xEC, 0x00, 0x6E, 0xA6, 0x8F, 0x2A, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Skakuhachi */ { 0xF5, 0xF4, 0x9A, 0x40, 0x0C, 0x80, 0xC7, 0xA5, 0x00, 0x00, 0x0D, 0, 0, 0 }, /* Whistle */ { 0x02, 0x11, 0x4F, 0x00, 0x71, 0x72, 0x53, 0x7C, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Ocarina */ { 0x04, 0x02, 0x08, 0x00, 0xF8, 0xB2, 0x07, 0x74, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Lead 1 (square) */ { 0x60, 0x60, 0x0B, 0x00, 0xF6, 0xA6, 0x4F, 0x0F, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Lead 2 (sawtooth) */ { 0x82, 0xF1, 0x90, 0x00, 0x68, 0xC7, 0x08, 0x08, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Lead 3 (calliope) */ { 0x50, 0x01, 0x80, 0x00, 0x55, 0x56, 0xF5, 0xE6, 0x00, 0x01, 0x08, 0, 0, 0 }, /* Lead 4 (chiff) */ { 0x61, 0x22, 0x00, 0x00, 0x96, 0x65, 0x33, 0x2B, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Lead 5 (charang) */ { 0x61, 0x22, 0x07, 0x00, 0xF6, 0xF6, 0x03, 0x16, 0x03, 0x00, 0x04, 0, 0, 0 }, /* Lead 6 (voice) */ { 0x11, 0x01, 0x85, 0x00, 0xB3, 0xA1, 0xE1, 0xE4, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Lead 7 (fifths) */ { 0x50, 0x71, 0x41, 0x00, 0xF2, 0xF2, 0xE2, 0xB2, 0x01, 0x00, 0x0A, 0, 0, 0 }, /* Lead 8 (bass+lead) */ { 0xB4, 0xF6, 0x87, 0x00, 0xA4, 0x85, 0x02, 0x42, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Pad 1 (new age) */ { 0xF0, 0xB0, 0xC0, 0x00, 0x41, 0xB2, 0x90, 0x05, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Pad 2 (warm) */ { 0x51, 0x00, 0x03, 0x01, 0xFF, 0xFF, 0x02, 0x04, 0x01, 0x01, 0x04, 0, 0, 0 }, /* Pad 3 (polysynth) */ { 0xE1, 0xE0, 0xD0, 0x00, 0xF5, 0xF4, 0xAF, 0x0F, 0x00, 0x02, 0x0C, 0, 0, 0 }, /* Pad 4 (choir) */ { 0xF4, 0xF1, 0x02, 0x00, 0x33, 0x53, 0x11, 0x2E, 0x02, 0x03, 0x03, 0, 0, 0 }, /* Pad 5 (bowed) */ { 0x05, 0x43, 0x40, 0x00, 0xB3, 0xF2, 0xD3, 0x25, 0x00, 0x01, 0x02, 0, 0, 0 }, /* Pad 6 (metallic) */ { 0x31, 0x10, 0x4D, 0x00, 0x72, 0x51, 0xCF, 0xEE, 0x03, 0x01, 0x02, 0, 0, 0 }, /* Pad 7 (halo) */ { 0x00, 0x10, 0x12, 0x00, 0x10, 0x50, 0xFF, 0xFF, 0x00, 0x00, 0x0A, 0, 0, 0 }, /* Pad 8 (sweep) */ { 0x7E, 0x61, 0x1A, 0x00, 0xFF, 0x6F, 0x0F, 0x0F, 0x00, 0x01, 0x0E, 0, 0, 0 }, /* FX 1 (rain) */ { 0xF0, 0xF0, 0x41, 0x40, 0x31, 0x22, 0x11, 0x12, 0x00, 0x01, 0x02, 0, 0, 0 }, /* FX 2 (soundtrack) */ { 0xB6, 0xF1, 0x4B, 0x00, 0xE5, 0x45, 0x03, 0x42, 0x02, 0x01, 0x06, 0, 0, 0 }, /* FX 3 (crystal) */ { 0x72, 0x20, 0x18, 0x40, 0x58, 0x26, 0x00, 0x02, 0x01, 0x00, 0x06, 0, 0, 0 }, /* FX 4 (atmosphere) */ { 0x50, 0xC5, 0x90, 0x00, 0xF9, 0xFF, 0x02, 0x01, 0x02, 0x00, 0x04, 0, 0, 0 }, /* FX 5 (brightness) */ { 0x20, 0x00, 0x03, 0x00, 0x4D, 0xFF, 0x0F, 0x05, 0x00, 0x01, 0x02, 0, 0, 0 }, /* FX 6 (goblins) */ { 0x35, 0xA2, 0xD7, 0x00, 0x7F, 0x35, 0x42, 0x21, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* FX 7 (echoes) */ { 0x7C, 0x30, 0x40, 0x00, 0xF1, 0xF1, 0x03, 0x01, 0x03, 0x00, 0x06, 0, 0, 0 }, /* FX 8 (sci-fi) */ { 0x01, 0x28, 0x40, 0x80, 0xF1, 0xF1, 0x53, 0x53, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Sitar */ { 0x31, 0x13, 0x87, 0x80, 0xA1, 0x8D, 0x11, 0x43, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Banjo */ { 0x01, 0x37, 0x4F, 0x00, 0xF1, 0xF2, 0x53, 0x74, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Shamisen */ { 0x01, 0x21, 0x0B, 0x00, 0xF2, 0xF5, 0x1F, 0x88, 0x00, 0x01, 0x00, 0, 0, 0 }, /* Koto */ { 0x02, 0x01, 0x99, 0x80, 0xF5, 0xF6, 0x55, 0x53, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Kalimba */ { 0x31, 0xA1, 0x43, 0x00, 0x6E, 0xAB, 0x17, 0x0C, 0x01, 0x01, 0x02, 0, 0, 0 }, /* Bagpipe */ { 0x31, 0x62, 0x19, 0x00, 0x55, 0x84, 0x03, 0x44, 0x02, 0x01, 0x0A, 0, 0, 0 }, /* Fiddle */ { 0x81, 0x93, 0x4B, 0x00, 0x78, 0x85, 0x42, 0x55, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Shanai */ { 0x07, 0x18, 0x46, 0x00, 0xF1, 0xFC, 0x72, 0x04, 0x02, 0x01, 0x00, 0, 0, 0 }, /* Tinkle Bell */ { 0x0E, 0x0E, 0x00, 0x00, 0xF8, 0xF8, 0xF6, 0xF6, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Agogo */ { 0x03, 0x02, 0xC0, 0x00, 0x8F, 0x9F, 0x07, 0x05, 0x01, 0x01, 0x0A, 0, 0, 0 }, /* Steel Drums */ { 0x02, 0x02, 0x00, 0x00, 0xC8, 0xF8, 0x97, 0x97, 0x00, 0x00, 0x01, 0, 0, 0 }, /* Woodblock */ { 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x07, 0x07, 0x00, 0x01, 0x05, 0, 0, 0 }, /* Taiko Drum */ { 0x01, 0x01, 0x00, 0x00, 0xD8, 0xD8, 0x96, 0x96, 0x0A, 0x00, 0x00, 0, 0, 0 }, /* Melodic Tom */ { 0x09, 0x00, 0x00, 0x00, 0xF1, 0xF6, 0xB3, 0xB4, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Synth Drum */ { 0x01, 0x00, 0x80, 0x00, 0x5F, 0x5F, 0x0B, 0x0F, 0x00, 0x03, 0x06, 0, 0, 0 }, /* Reverse Cymbal */ { 0x51, 0x42, 0x00, 0x00, 0x66, 0x66, 0x05, 0x06, 0x02, 0x02, 0x02, 0, 0, 0 }, /* Guitar Fret Noise */ { 0x54, 0x40, 0x0A, 0x00, 0x5F, 0x7F, 0x66, 0x07, 0x03, 0x00, 0x04, 0, 0, 0 }, /* Breath Noise */ { 0x0E, 0x0E, 0x00, 0x00, 0x20, 0x21, 0x00, 0x01, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Seashore */ { 0xC0, 0xFB, 0x51, 0x00, 0xF1, 0x94, 0x05, 0x23, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Bird Tweet */ { 0xFC, 0xF0, 0xC0, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x01, 0x03, 0x00, 0, 0, 0 }, /* Telephone ring */ { 0xF0, 0xE2, 0x00, 0xC0, 0x1E, 0x11, 0x11, 0x11, 0x01, 0x01, 0x08, 0, 0, 0 }, /* Helicopter */ { 0x7E, 0x6E, 0x00, 0x00, 0xFF, 0x5F, 0x0F, 0x0F, 0x00, 0x00, 0x0E, 0, 0, 0 }, /* Applause */ { 0x0A, 0x86, 0x00, 0x00, 0xA0, 0xC5, 0xF0, 0x75, 0x00, 0x00, 0x0E, 0, 0, 0 } /* Gunshot */ #endif }; allegro-4.4.3.1/src/misc/test.cpp0000664000175000017500000000002613437077643015503 0ustar siegesiegeclass foo {foo() {}}; allegro-4.4.3.1/src/misc/ccolconv.c0000664000175000017500000007322013437077643016000 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * C routines for software color conversion. * * By Angelo Mottola, based on x86 asm versions by Isaac Cruz, * Eric Botcazou and Robert J. Ohannessian. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" extern int *_colorconv_indexed_palette; /* for conversion from 8-bit */ extern int *_colorconv_rgb_scale_5x35; /* for conversion from 15/16-bit */ extern unsigned char *_colorconv_rgb_map; /* for conversion from 8/12-bit to 8-bit */ #ifdef ALLEGRO_NO_ASM #ifdef ALLEGRO_COLOR8 void _colorconv_blit_8_to_8(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int dest_data; width = src_rect->width; src_feed = src_rect->pitch - width; dest_feed = dest_rect->pitch - width; src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 2; x; x--) { src_data = *(unsigned int *)src; dest_data = _colorconv_rgb_map[src_data & 0xff]; dest_data |= (_colorconv_rgb_map[(src_data >> 8) & 0xff] << 8); dest_data |= (_colorconv_rgb_map[(src_data >> 16) & 0xff] << 16); dest_data |= (_colorconv_rgb_map[src_data >> 24] << 24); *(unsigned int *)dest = dest_data; src += 4; dest += 4; } if (width & 0x2) { src_data = *(unsigned short *)src; dest_data = _colorconv_rgb_map[src_data & 0xff]; dest_data |= (_colorconv_rgb_map[src_data >> 8] << 8); *(unsigned short *)dest = (unsigned short)dest_data; src += 2; dest += 2; } if (width & 0x1) { src_data = *(unsigned char *)src; dest_data = _colorconv_rgb_map[src_data]; *(unsigned char *)dest = (unsigned char)dest_data; src++; dest++; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_8_to_15(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { _colorconv_blit_8_to_16(src_rect, dest_rect); } void _colorconv_blit_8_to_16(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int dest_data; width = src_rect->width; src_feed = src_rect->pitch - width; dest_feed = dest_rect->pitch - (width << 1); src = src_rect->data; dest = dest_rect->data; #ifdef ALLEGRO_ARM /* ARM requires strict alignment for memory access. So this ARM branch of code * takes it into account. Combining data into 32-bit values when writing to * memory really adds about 20% extra performance on Nokia 770. An interesting * thing is that this branch of code is not only correct, but also actually * a bit faster than the other one. * * TODO: Check performance of this code path on other architectures. If it * is reasonably similar or better to the non-aligned code path then we can * remove this #ifdef. */ #ifdef ALLEGRO_LITTLE_ENDIAN #define FILL_DEST_DATA() \ dest_data = _colorconv_indexed_palette[src[0]]; \ dest_data |= _colorconv_indexed_palette[256 + src[1]]; \ src += 2; #else #define FILL_DEST_DATA() \ dest_data = _colorconv_indexed_palette[256 + src[0]]; \ dest_data |= _colorconv_indexed_palette[src[1]]; \ src += 2; #endif if (width <= 0) return; y = src_rect->height; if (width & 0x1) { width >>= 1; while (--y >= 0) { if ((int)dest & 0x3) { *(unsigned short *)(dest) = _colorconv_indexed_palette[*src++]; dest += 2; x = width; while (--x >= 0) { FILL_DEST_DATA(); *(unsigned int *)dest = dest_data; dest += 4; } } else { x = width; while (--x >= 0) { FILL_DEST_DATA(); *(unsigned int *)dest = dest_data; dest += 4; } *(unsigned short *)(dest) = _colorconv_indexed_palette[*src++]; dest += 2; } src += src_feed; dest += dest_feed; } } else { width >>= 1; while (--y >= 0) { if ((int)dest & 0x3) { *(unsigned short *)(dest) = _colorconv_indexed_palette[*src++]; dest += 2; x = width; while (--x > 0) { FILL_DEST_DATA(); *(unsigned int *)dest = dest_data; dest += 4; } *(unsigned short *)(dest) = _colorconv_indexed_palette[*src++]; dest += 2; } else { x = width; while (--x >= 0) { FILL_DEST_DATA(); *(unsigned int *)dest = dest_data; dest += 4; } } src += src_feed; dest += dest_feed; } } #else /* !ALLEGRO_ARM */ for (y = src_rect->height; y; y--) { for (x = width >> 2; x; x--) { src_data = *(unsigned int *)src; #ifdef ALLEGRO_LITTLE_ENDIAN dest_data = _colorconv_indexed_palette[src_data & 0xff]; dest_data |= _colorconv_indexed_palette[256 + ((src_data >> 8) & 0xff)]; *(unsigned int *)dest = dest_data; dest_data = _colorconv_indexed_palette[(src_data >> 16) & 0xff]; dest_data |= _colorconv_indexed_palette[256 + (src_data >> 24)]; *(unsigned int *)(dest + 4) = dest_data; #else dest_data = _colorconv_indexed_palette[256 + (src_data >> 24)]; dest_data |= _colorconv_indexed_palette[((src_data >> 16) & 0xff)]; *(unsigned int *)dest = dest_data; dest_data = _colorconv_indexed_palette[256 + ((src_data >> 8) & 0xff)]; dest_data |= _colorconv_indexed_palette[(src_data & 0xff)]; *(unsigned int *)(dest + 4) = dest_data; #endif src += 4; dest += 8; } if (width & 0x2) { src_data = *(unsigned short *)src; #ifdef ALLEGRO_LITTLE_ENDIAN dest_data = _colorconv_indexed_palette[src_data & 0xff]; dest_data |= _colorconv_indexed_palette[256 + (src_data >> 8)]; *(unsigned int *)dest = dest_data; #else dest_data = _colorconv_indexed_palette[src_data >> 8]; dest_data |= _colorconv_indexed_palette[256 + (src_data & 0xff)]; *(unsigned int *)dest = dest_data; #endif src += 2; dest += 4; } if (width & 0x1) { src_data = *(unsigned char *)src; dest_data = _colorconv_indexed_palette[src_data]; *(unsigned short *)dest = (unsigned short)dest_data; src++; dest += 2; } src += src_feed; dest += dest_feed; } #endif /* !ALLEGRO_ARM */ } void _colorconv_blit_8_to_24(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int temp1, temp2, temp3, temp4; width = src_rect->width; src_feed = src_rect->pitch - width; dest_feed = dest_rect->pitch - (width * 3); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 2; x; x--) { src_data = *(unsigned int *)src; #ifdef ALLEGRO_LITTLE_ENDIAN temp1 = _colorconv_indexed_palette[src_data & 0xff]; temp2 = _colorconv_indexed_palette[256 + ((src_data >> 8) & 0xff)]; temp3 = _colorconv_indexed_palette[512 + ((src_data >> 16) & 0xff)]; temp4 = _colorconv_indexed_palette[768 + (src_data >> 24)]; #else temp1 = _colorconv_indexed_palette[768 + (src_data >> 24)]; temp2 = _colorconv_indexed_palette[512 + ((src_data >> 16) & 0xff)]; temp3 = _colorconv_indexed_palette[256 + ((src_data >> 8) & 0xff)]; temp4 = _colorconv_indexed_palette[src_data & 0xff]; #endif *(unsigned int *)dest = temp1 | (temp2 & 0xff000000); *(unsigned int *)(dest + 4) = (temp2 & 0xffff) | (temp3 & 0xffff0000); *(unsigned int *)(dest + 8) = temp4 | (temp3 & 0xff); src += 4; dest += 12; } if (width & 0x2) { src_data = *(unsigned short *)src; #ifdef ALLEGRO_LITTLE_ENDIAN temp1 = _colorconv_indexed_palette[src_data & 0xff]; temp2 = _colorconv_indexed_palette[src_data >> 8]; #else temp1 = _colorconv_indexed_palette[src_data >> 8]; temp2 = _colorconv_indexed_palette[src_data & 0xff]; #endif *(unsigned int *)dest = temp1; *(unsigned short *)(dest + 3) = (unsigned short)(temp2 & 0xffff); *(unsigned char *)(dest + 5) = (unsigned char)(temp2 >> 16); src += 2; dest += 6; } if (width & 0x1) { src_data = *(unsigned char *)src; temp1 = _colorconv_indexed_palette[src_data]; *(unsigned short *)dest = (unsigned short)(temp1 & 0xffff); *(unsigned char *)(dest + 2) = (unsigned char)(temp1 >> 16); src++; dest += 3; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_8_to_32(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int dest_data; width = src_rect->width; src_feed = src_rect->pitch - width; dest_feed = dest_rect->pitch - (width << 2); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 2; x; x--) { src_data = *(unsigned int *)src; #ifdef ALLEGRO_LITTLE_ENDIAN dest_data = _colorconv_indexed_palette[src_data & 0xff]; *(unsigned int *)(dest) = dest_data; dest_data = _colorconv_indexed_palette[(src_data >> 8) & 0xff]; *(unsigned int *)(dest + 4) = dest_data; dest_data = _colorconv_indexed_palette[(src_data >> 16) & 0xff]; *(unsigned int *)(dest + 8) = dest_data; dest_data = _colorconv_indexed_palette[(src_data >> 24) & 0xff]; *(unsigned int *)(dest + 12) = dest_data; #else dest_data = _colorconv_indexed_palette[(src_data >> 24) & 0xff]; *(unsigned int *)(dest) = dest_data; dest_data = _colorconv_indexed_palette[(src_data >> 16) & 0xff]; *(unsigned int *)(dest + 4) = dest_data; dest_data = _colorconv_indexed_palette[(src_data >> 8) & 0xff]; *(unsigned int *)(dest + 8) = dest_data; dest_data = _colorconv_indexed_palette[src_data & 0xff]; *(unsigned int *)(dest + 12) = dest_data; #endif src += 4; dest += 16; } if (width & 0x2) { src_data = *(unsigned short *)src; #ifdef ALLEGRO_LITTLE_ENDIAN dest_data = _colorconv_indexed_palette[src_data & 0xff]; *(unsigned int *)(dest) = dest_data; dest_data = _colorconv_indexed_palette[src_data >> 8]; *(unsigned int *)(dest + 4) = dest_data; #else dest_data = _colorconv_indexed_palette[src_data >> 8]; *(unsigned int *)(dest) = dest_data; dest_data = _colorconv_indexed_palette[src_data & 0xff]; *(unsigned int *)(dest + 4) = dest_data; #endif src += 2; dest += 8; } if (width & 0x1) { src_data = *(unsigned char *)src; *(unsigned int *)dest = _colorconv_indexed_palette[src_data]; src++; dest += 4; } src += src_feed; dest += dest_feed; } } #endif #ifdef ALLEGRO_COLOR16 void _colorconv_blit_15_to_8(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned short dest_data; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width << 1); dest_feed = dest_rect->pitch - width; src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { src_data = *(unsigned int *)src; #ifdef ALLEGRO_LITTLE_ENDIAN temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x03c0) >> 2) | ((src_data & 0x7800) >> 3); dest_data = _colorconv_rgb_map[temp]; src_data >>= 16; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x03c0) >> 2) | ((src_data & 0x7800) >> 3); dest_data |= ((unsigned short)_colorconv_rgb_map[temp] << 8); #else temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x03c0) >> 2) | ((src_data & 0x7800) >> 3); dest_data = ((unsigned short)_colorconv_rgb_map[temp] << 8); src_data >>= 16; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x03c0) >> 2) | ((src_data & 0x7800) >> 3); dest_data |= (unsigned short)_colorconv_rgb_map[temp]; #endif *(unsigned short *)dest = dest_data; src += 4; dest += 2; } if (width & 0x1) { src_data = *(unsigned short *)src; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x03c0) >> 2) | ((src_data & 0x7800) >> 3); *(unsigned char *)dest = _colorconv_rgb_map[temp]; src += 2; dest++; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_15_to_16(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width << 1); dest_feed = dest_rect->pitch - (width << 1); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { src_data = *(unsigned int *)src; temp = ((src_data & 0x7fe07fe0) << 1) | (src_data & 0x001f001f); *(unsigned int *)dest = (temp | 0x00200020); src += 4; dest += 4; } if (width & 0x1) { src_data = *(unsigned short *)src; temp = ((src_data & 0x7fe0) << 1) | (src_data & 0x001f); *(unsigned short *)dest = (unsigned short)(temp | 0x0020); src += 2; dest += 2; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_15_to_24(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int temp1, temp2, temp3, temp4; width = src_rect->width; src_feed = src_rect->pitch - (width << 1); dest_feed = dest_rect->pitch - (width * 3); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 2; x; x--) { #ifdef ALLEGRO_LITTLE_ENDIAN src_data = *(unsigned int *)src; temp1 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[(src_data >> 8) & 0xff]; temp2 = _colorconv_rgb_scale_5x35[768 + ((src_data >> 16) & 0xff)] + _colorconv_rgb_scale_5x35[512 + (src_data >> 24)]; src_data = *(unsigned int *)(src + 4); temp3 = _colorconv_rgb_scale_5x35[1280 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[1024 + ((src_data >> 8) & 0xff)]; temp4 = _colorconv_rgb_scale_5x35[src_data >> 24] + _colorconv_rgb_scale_5x35[256 + ((src_data >> 16) & 0xff)]; #else src_data = *(unsigned int *)src; temp4 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[(src_data >> 8) & 0xff]; temp3 = _colorconv_rgb_scale_5x35[768 + ((src_data >> 16) & 0xff)] + _colorconv_rgb_scale_5x35[512 + (src_data >> 24)]; src_data = *(unsigned int *)(src + 4); temp2 = _colorconv_rgb_scale_5x35[1280 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[1024 + ((src_data >> 8) & 0xff)]; temp1 = _colorconv_rgb_scale_5x35[src_data >> 24] + _colorconv_rgb_scale_5x35[256 + ((src_data >> 16) & 0xff)]; #endif *(unsigned int *)dest = temp1 | (temp2 & 0xff000000); *(unsigned int *)(dest + 4) = (temp2 & 0xffff) | (temp3 & 0xffff0000); *(unsigned int *)(dest + 8) = (temp3 & 0xff) | (temp4 << 8); src += 8; dest += 12; } if (width & 0x2) { src_data = *(unsigned int *)src; #ifdef ALLEGRO_LITTLE_ENDIAN temp1 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[(src_data >> 8) & 0xff]; temp2 = _colorconv_rgb_scale_5x35[256 + ((src_data >> 16) & 0xff)] + _colorconv_rgb_scale_5x35[src_data >> 24]; #else temp2 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[(src_data >> 8) & 0xff]; temp1 = _colorconv_rgb_scale_5x35[256 + ((src_data >> 16) & 0xff)] + _colorconv_rgb_scale_5x35[src_data >> 24]; #endif *(unsigned int *)dest = temp1; *(unsigned short *)(dest + 3) = (unsigned short)(temp2 & 0xffff); *(unsigned char *)(dest + 5) = (unsigned char)(temp2 >> 16); src += 4; dest += 6; } if (width & 0x1) { src_data = *(unsigned short *)src; temp1 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[src_data >> 8]; *(unsigned short *)dest = (unsigned short)(temp1 & 0xffff); *(unsigned char *)(dest + 2) = (unsigned char)(temp1 >> 16); src += 2; dest += 3; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_15_to_32(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int temp1, temp2; width = src_rect->width; src_feed = src_rect->pitch - (width << 1); dest_feed = dest_rect->pitch - (width << 2); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { src_data = *(unsigned int *)src; temp1 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[(src_data >> 8) & 0xff]; temp2 = _colorconv_rgb_scale_5x35[256 + ((src_data >> 16) & 0xff)] + _colorconv_rgb_scale_5x35[src_data >> 24]; #ifdef ALLEGRO_LITTLE_ENDIAN *(unsigned int *)dest = temp1; *(unsigned int *)(dest + 4) = temp2; #else *(unsigned int *)dest = temp2; *(unsigned int *)(dest + 4) = temp1; #endif src += 4; dest += 8; } if (width & 0x1) { src_data = *(unsigned short *)src; temp1 = _colorconv_rgb_scale_5x35[256 + (src_data & 0xff)] + _colorconv_rgb_scale_5x35[src_data >> 8]; *(unsigned int *)dest = temp1; src += 2; dest += 4; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_16_to_8(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned short dest_data; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width << 1); dest_feed = dest_rect->pitch - width; src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { #ifdef ALLEGRO_LITTLE_ENDIAN src_data = *(unsigned int *)src; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x0780) >> 3) | ((src_data & 0xf000) >> 4); dest_data = _colorconv_rgb_map[temp]; src_data >>= 16; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x0780) >> 3) | ((src_data & 0xf000) >> 4); dest_data |= ((unsigned short)_colorconv_rgb_map[temp] << 8); *(unsigned short *)dest = dest_data; #else src_data = *(unsigned int *)src; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x0780) >> 3) | ((src_data & 0xf000) >> 4); dest_data = ((unsigned short)_colorconv_rgb_map[temp] << 8); src_data >>= 16; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x0780) >> 3) | ((src_data & 0xf000) >> 4); dest_data |= (unsigned short)_colorconv_rgb_map[temp]; *(unsigned short *)dest = dest_data; #endif src += 4; dest += 2; } if (width & 0x1) { src_data = *(unsigned short *)src; temp = ((src_data & 0x001e) >> 1) | ((src_data & 0x0780) >> 3) | ((src_data & 0xf000) >> 4); *(unsigned char *)dest = _colorconv_rgb_map[temp]; src += 2; dest++; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_16_to_15(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int src_data; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width << 1); dest_feed = dest_rect->pitch - (width << 1); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { src_data = *(unsigned int *)src; temp = ((src_data & 0xffc0ffc0) >> 1) | (src_data & 0x001f001f); *(unsigned int *)dest = temp; src += 4; dest += 4; } if (width & 0x1) { src_data = *(unsigned short *)src; temp = ((src_data & 0xffc0) >> 1) | (src_data & 0x001f); *(unsigned short *)dest = (unsigned short)temp; src += 2; dest += 2; } src += src_feed; dest += dest_feed; } } void _colorconv_blit_16_to_24(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { _colorconv_blit_15_to_24(src_rect, dest_rect); } void _colorconv_blit_16_to_32(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { _colorconv_blit_15_to_32(src_rect, dest_rect); } #endif #if (defined ALLEGRO_COLOR24 || defined ALLEGRO_COLOR32) static void colorconv_blit_true_to_8(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect, int bpp) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width * bpp); dest_feed = dest_rect->pitch - width; src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width; x; x--) { temp = ((*(unsigned char *)src) >> 4) | ((*(unsigned char *)(src + 1)) & 0xf0) | (((*(unsigned char *)(src + 2)) & 0xf0) << 4); *(unsigned char *)dest = _colorconv_rgb_map[temp]; src += bpp; dest++; } src += src_feed; dest += dest_feed; } } static void colorconv_blit_true_to_15(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect, int bpp) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width * bpp); dest_feed = dest_rect->pitch - (width << 1); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { #ifdef ALLEGRO_LITTLE_ENDIAN temp = ((*(unsigned char *)(src + bpp)) >> 3) | (((*(unsigned char *)(src + bpp + 1)) << 2) & 0x03e0) | (((*(unsigned char *)(src + bpp + 2)) << 7) & 0x7c00); temp <<= 16; temp |= ((*(unsigned char *)(src)) >> 3) | (((*(unsigned char *)(src + 1)) << 2) & 0x03e0) | (((*(unsigned char *)(src + 2)) << 7) & 0x7c00); #else temp = ((*(unsigned char *)(src + bpp - 1)) >> 3) | (((*(unsigned char *)(src + bpp - 2)) << 2) & 0x03e0) | (((*(unsigned char *)(src + bpp - 3)) << 7) & 0x7c00); temp <<= 16; temp |= ((*(unsigned char *)(src + bpp + bpp - 1)) >> 3) | (((*(unsigned char *)(src + bpp + bpp - 2)) << 2) & 0x03e0) | (((*(unsigned char *)(src + bpp + bpp - 3)) << 7) & 0x7c00); #endif *(unsigned int *)dest = temp; src += (bpp << 1); dest += 4; } if (width & 0x1) { #ifdef ALLEGRO_LITTLE_ENDIAN temp = ((*(unsigned char *)(src)) >> 3) | (((*(unsigned char *)(src + 1)) << 2) & 0x03e0) | (((*(unsigned char *)(src + 2)) << 7) & 0x7c00); #else temp = ((*(unsigned char *)(src + bpp - 1)) >> 3) | (((*(unsigned char *)(src + bpp - 2)) << 2) & 0x03e0) | (((*(unsigned char *)(src + bpp - 3)) << 7) & 0x7c00); #endif *(unsigned short *)dest = (unsigned short)temp; src += bpp; dest += 2; } src += src_feed; dest += dest_feed; } } static void colorconv_blit_true_to_16(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect, int bpp) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width * bpp); dest_feed = dest_rect->pitch - (width << 1); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 1; x; x--) { #ifdef ALLEGRO_LITTLE_ENDIAN temp = ((*(unsigned char *)(src + bpp)) >> 3) | (((*(unsigned char *)(src + bpp + 1)) << 3) & 0x07e0) | (((*(unsigned char *)(src + bpp + 2)) << 8) & 0xf800); temp <<= 16; temp |= ((*(unsigned char *)(src)) >> 3) | (((*(unsigned char *)(src + 1)) << 3) & 0x07e0) | (((*(unsigned char *)(src + 2)) << 8) & 0xf800); #else temp = ((*(unsigned char *)(src + 3)) >> 3) | (((*(unsigned char *)(src + 2)) << 3) & 0x07e0) | (((*(unsigned char *)(src + 1)) << 8) & 0xf800); temp <<= 16; temp |= ((*(unsigned char *)(src + bpp + 3)) >> 3) | (((*(unsigned char *)(src + bpp + 2)) << 3) & 0x07e0) | (((*(unsigned char *)(src + bpp + 1)) << 8) & 0xf800); #endif *(unsigned int *)dest = temp; src += (bpp << 1); dest += 4; } if (width & 0x1) { #ifdef ALLEGRO_LITTLE_ENDIAN temp = ((*(unsigned char *)(src)) >> 3) | (((*(unsigned char *)(src + 1)) << 3) & 0x07e0) | (((*(unsigned char *)(src + 2)) << 8) & 0xf800); #else temp = ((*(unsigned char *)(src + 3)) >> 3) | (((*(unsigned char *)(src + 2)) << 3) & 0x07e0) | (((*(unsigned char *)(src + 1)) << 8) & 0xf800); #endif *(unsigned short *)dest = (unsigned short)temp; src += bpp; dest += 2; } src += src_feed; dest += dest_feed; } } #endif #ifdef ALLEGRO_COLOR24 void _colorconv_blit_24_to_8(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorconv_blit_true_to_8(src_rect, dest_rect, 3); } void _colorconv_blit_24_to_15(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorconv_blit_true_to_15(src_rect, dest_rect, 3); } void _colorconv_blit_24_to_16(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorconv_blit_true_to_16(src_rect, dest_rect, 3); } void _colorconv_blit_24_to_32(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width * 3); dest_feed = dest_rect->pitch - (width << 2); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width; x; x--) { #ifdef ALLEGRO_LITTLE_ENDIAN temp = (*(unsigned char *)src) | ((*(unsigned char *)(src + 1)) << 8) | ((*(unsigned char *)(src + 2)) << 16); #else temp = (*(unsigned char *)(src + 2)) | ((*(unsigned char *)(src + 1)) << 8) | ((*(unsigned char *)(src)) << 16); #endif *(unsigned int *)dest = temp; src += 3; dest += 4; } src += src_feed; dest += dest_feed; } } #endif #ifdef ALLEGRO_COLOR32 void _colorconv_blit_32_to_8(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorconv_blit_true_to_8(src_rect, dest_rect, 4); } void _colorconv_blit_32_to_15(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorconv_blit_true_to_15(src_rect, dest_rect, 4); } void _colorconv_blit_32_to_16(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorconv_blit_true_to_16(src_rect, dest_rect, 4); } void _colorconv_blit_32_to_24(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; unsigned int temp; width = src_rect->width; src_feed = src_rect->pitch - (width << 2); dest_feed = dest_rect->pitch - (width * 3); src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width; x; x--) { temp = *(unsigned int *)src; #ifdef ALLEGRO_LITTLE_ENDIAN *(unsigned char *)dest = (unsigned char)(temp & 0xff); *(unsigned char *)(dest + 1) = (unsigned char)(temp >> 8) & 0xff; *(unsigned char *)(dest + 2) = (unsigned char)(temp >> 16) & 0xff; #else *(unsigned char *)(dest + 2) = (unsigned char)(temp & 0xff); *(unsigned char *)(dest + 1) = (unsigned char)(temp >> 8) & 0xff; *(unsigned char *)dest = (unsigned char)(temp >> 16) & 0xff; #endif src += 4; dest += 3; } src += src_feed; dest += dest_feed; } } #endif #ifndef ALLEGRO_NO_COLORCOPY static void colorcopy(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect, int bpp) { unsigned char *src; unsigned char *dest; int width; int src_feed; int dest_feed; int y, x; width = src_rect->width * bpp; src_feed = src_rect->pitch - width; dest_feed = dest_rect->pitch - width; src = src_rect->data; dest = dest_rect->data; for (y = src_rect->height; y; y--) { for (x = width >> 2; x; x--) { *(unsigned int *)dest = *(unsigned int *)src; src += 4; dest += 4; } if (width & 0x2) { *(unsigned short *)dest = *(unsigned short *)src; src += 2; dest += 2; } if (width & 0x1) { *(unsigned char *)dest = *(unsigned char *)src; src++; dest++; } src += src_feed; dest += dest_feed; } } void _colorcopy_blit_15_to_15(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorcopy(src_rect, dest_rect, 2); } void _colorcopy_blit_16_to_16(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorcopy(src_rect, dest_rect, 2); } void _colorcopy_blit_24_to_24(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorcopy(src_rect, dest_rect, 3); } void _colorcopy_blit_32_to_32(struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect) { colorcopy(src_rect, dest_rect, 4); } #endif #endif allegro-4.4.3.1/src/misc/modexgfx.s0000664000175000017500000013205113437077643016031 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Mode-X drawing functions. * * By Shawn Hargreaves. * * Dominique Biesmans wrote the mode-X <-> linear blitting routines * and the mode-X version of draw_sprite(). * * Linear -> mode-X blit optimised by Ettore Perazzoli. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" .text #if (!defined ALLEGRO_LINUX) || ((defined ALLEGRO_LINUX_VGA) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))) /* _x_bank_switch: * Cunning trickey for emulating linear access to mode-X screens, by * copying the image into a temporary buffer and letting the client * write to that in place of the real screen. */ FUNC(_x_bank_switch) cmpl $0, GLOBL(_x_magic_screen_addr) jz no_previous_magic call GLOBL(_x_unbank_switch) no_previous_magic: pushl %ecx /* save registers */ pushl %edx pushl %esi pushl %edi pushl %es movl BMP_CR(%edx), %ecx /* store off the width and screen address */ addl $3, %ecx shrl $2, %ecx movl %ecx, GLOBL(_x_magic_screen_width) movl BMP_LINE(%edx, %eax, 4), %esi movl %esi, GLOBL(_x_magic_screen_addr) movl $0, %ecx /* plane counter in ecx */ movw BMP_SEG(%edx), %es bank_plane_loop: movb %cl, %ah /* select write plane */ movb $4, %al movl $0x3CE, %edx outw %ax, %dx movl GLOBL(_x_magic_screen_addr), %esi movl GLOBL(_x_magic_buffer_addr), %edi movl GLOBL(_x_magic_screen_width), %edx addl %ecx, %edi bank_pixel_loop: movb %es:(%esi), %al /* read pixel */ movb %al, %es:(%edi) /* write pixel */ incl %esi /* advance pointers */ addl $4, %edi decl %edx /* next pixel */ jg bank_pixel_loop incl %ecx /* next plane */ cmpl $4, %ecx jl bank_plane_loop popl %es /* restore registers */ popl %edi popl %esi popl %edx popl %ecx movl GLOBL(_x_magic_buffer_addr), %eax ret /* _x_unbank_switch: * Updates the real screen from the linear emulation buffer. */ FUNC(_x_unbank_switch) cmpl $0, GLOBL(_x_magic_screen_addr) je unbank_done pushl %eax /* save registers */ pushl %ecx pushl %edx pushl %esi pushl %edi pushl %es movl $0, %ecx /* plane counter in ecx */ movw BMP_SEG(%edx), %es unbank_plane_loop: movb $1, %ah /* select write plane */ shlb %cl, %ah movb $2, %al movl $0x3C4, %edx outw %ax, %dx movl GLOBL(_x_magic_buffer_addr), %esi movl GLOBL(_x_magic_screen_addr), %edi movl GLOBL(_x_magic_screen_width), %edx addl %ecx, %esi unbank_pixel_loop: movb %es:(%esi), %al /* read pixel */ movb %al, %es:(%edi) /* write pixel */ addl $4, %esi /* advance pointers */ incl %edi decl %edx /* next pixel */ jg unbank_pixel_loop incl %ecx /* next plane */ cmpl $4, %ecx jl unbank_plane_loop movl $0, GLOBL(_x_magic_screen_addr) popl %es /* restore registers */ popl %edi popl %esi popl %edx popl %ecx popl %eax unbank_done: ret /* put this here so both the above routines will get locked */ FUNC(_x_bank_switch_end) ret /* void _x_clear_to_color(BITMAP *bitmap, int color); * Clears a mode-X bitmap to the specified color. */ FUNC(_x_clear_to_color) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi pushw %es movl $0x0F02, %eax /* enable all planes */ movl $0x3C4, %edx outw %ax, %dx movl ARG1, %edx /* edx = bmp */ movl BMP_CT(%edx), %ebx /* line to start at */ movw BMP_SEG(%edx), %es /* select segment */ movl BMP_CR(%edx), %esi /* width to clear */ subl BMP_CL(%edx), %esi shrl $2, %esi cld movb ARG2, %al /* duplicate color 4 times */ movb %al, %ah shll $16, %eax movb ARG2, %al movb %al, %ah _align_ clear_loop: movl BMP_CL(%edx), %edi /* get line address */ shrl $2, %edi addl BMP_LINE(%edx, %ebx, 4), %edi movl %esi, %ecx /* width to clear */ shrl $1, %ecx /* halve for 16 bit clear */ jnc clear_no_byte stosb /* clear an odd byte */ clear_no_byte: shrl $1, %ecx /* halve again for 32 bit clear */ jnc clear_no_word stosw /* clear an odd word */ clear_no_word: jz clear_no_long _align_ clear_x_loop: rep ; stosl /* clear the line */ clear_no_long: incl %ebx cmpl %ebx, BMP_CB(%edx) jg clear_loop /* and loop */ popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_clear_to_color() */ /* void _x_putpixel(BITMAP *bmp, int x, int y, int color); * Draws a pixel onto a mode-X bitmap. */ FUNC(_x_putpixel) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %ebx /* ebx = y */ cmpl $0, BMP_CLIP(%edx) /* test clip flag */ je xputpix_noclip cmpl %ecx, BMP_CL(%edx) /* test cl */ jg xputpix_done cmpl %ecx, BMP_CR(%edx) /* test cr */ jle xputpix_done cmpl %ebx, BMP_CT(%edx) /* test ct */ jg xputpix_done cmpl %ebx, BMP_CB(%edx) /* test cb */ jle xputpix_done xputpix_noclip: movl $0x102, %eax /* set the write plane */ andb $3, %cl shlb %cl, %ah movl $0x3C4, %edx outw %ax, %dx movl ARG2, %ecx /* reload ecx = x */ movl ARG1, %edx /* reload edx = bmp */ movw BMP_SEG(%edx), %es cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je xputpix_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) je xputpix_xor_mode /* XOR? */ cmpl $DRAW_TRANS, GLOBL(_drawing_mode) je xputpix_trans_mode /* translucent? */ LOOKUP_PATTERN_POS(%ecx, %ebx, %eax) movb (%ebx, %ecx), %al /* read pixel from pattern bitmap */ movl ARG2, %ecx /* reload clobbered registers */ movl ARG3, %ebx cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je xputpix_draw_it /* draw the pattern pixel? */ testb %al, %al /* test the pattern pixel */ jz xputpix_zero_pattern jmp xputpix_solid_mode _align_ xputpix_zero_pattern: cmpl $DRAW_MASKED_PATTERN, GLOBL(_drawing_mode) je xputpix_done /* skip zero pixels in masked mode */ jmp xputpix_draw_it /* draw zero pixels in solid mode */ _align_ xputpix_xor_mode: movb $4, %al /* set the read plane */ movb %cl, %ah andb $3, %ah movl $0x3CE, %edx outw %ax, %dx movl ARG4, %eax /* eax = color */ shrl $2, %ecx /* divide x by 4 */ movl ARG1, %edx /* reload edx = bmp */ movl BMP_LINE(%edx, %ebx, 4), %ebx xorb %al, %es:(%ebx, %ecx) /* XOR */ jmp xputpix_done _align_ xputpix_trans_mode: movb $4, %al /* set the read plane */ movb %cl, %ah andb $3, %ah movl $0x3CE, %edx outw %ax, %dx xorl %eax, %eax movb ARG4, %ah /* ah = color being drawn */ shrl $2, %ecx /* divide x by 4 */ movl ARG1, %edx /* reload edx = bmp */ movl BMP_LINE(%edx, %ebx, 4), %ebx movb %es:(%ebx, %ecx), %al /* al = existing color */ movl GLOBL(color_map), %edx /* color map in edx */ movb (%edx, %eax), %al /* lookup color in table */ movb %al, %es:(%ebx, %ecx) /* write the pixel */ jmp xputpix_done _align_ xputpix_solid_mode: movl ARG4, %eax /* eax = color */ xputpix_draw_it: shrl $2, %ecx /* divide x by 4 */ movl BMP_LINE(%edx, %ebx, 4), %ebx movb %al, %es:(%ebx, %ecx) /* store the pixel */ xputpix_done: popw %es popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_putpixel() */ /* int _x_getpixel(BITMAP *bmp, int x, int y); * Reads a pixel from a mode-X bitmap. */ FUNC(_x_getpixel) pushl %ebp movl %esp, %ebp pushl %ebx pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ecx /* ecx = x */ movl ARG3, %ebx /* ebx = y */ testl %ecx, %ecx /* test that we are on the bitmap */ jl xgetpix_skip cmpl %ecx, BMP_W(%edx) jle xgetpix_skip testl %ebx, %ebx jl xgetpix_skip cmpl %ebx, BMP_H(%edx) jg xgetpix_ok _align_ xgetpix_skip: /* return -1 if we are off the edge */ movl $-1, %eax jmp xgetpix_done _align_ xgetpix_ok: movb $4, %al /* set the correct plane */ movb %cl, %ah andb $3, %ah movl $0x3CE, %edx outw %ax, %dx shrl $2, %ecx /* divide x by 4 */ movl ARG1, %edx /* reload edx = bmp */ movw BMP_SEG(%edx), %es movl BMP_LINE(%edx, %ebx, 4), %ebx xorl %eax, %eax movb %es:(%ebx, %ecx), %al /* get the pixel */ xgetpix_done: popw %es popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_getpixel() */ /* void _x_hline(BITMAP *bmp, int x1, int y, int x2, int color); * Draws a horizontal line onto a mode-X bitmap. * * Patterned drawing could probably be done slightly faster by using the * latch registers, but I don't think very much faster: there would be so * much overhead due to the extra code complexity that it would only pay * off for very long lines... */ /* helper for patterned and xor lines, loops through each plane */ #define HLINE_LOOP(name, putter) \ movl %ecx, COUNTER ; \ movl %ebx, START_X ; \ movl %edi, SCREEN_ADDR ; \ movl $4, PLANE_COUNTER ; \ ; \ _align_ ; \ xhline_##name##_loop: ; \ movl $0x102, %eax /* set the write plane */ ; \ movb START_X, %cl ; \ andb $3, %cl ; \ shlb %cl, %ah ; \ movl $0x3C4, %edx ; \ outw %ax, %dx ; \ ; \ SETUP ; \ ; \ movl COUNTER, %edx ; \ addl $3, %edx ; \ shrl $2, %edx /* edx = the number of bytes to alter */ ; \ ; \ movl SCREEN_ADDR, %esi /* esi = the place to write it */ ; \ ; \ _align_ ; \ xhline_##name##_x_loop: ; \ putter /* write the pixel */ ; \ incl %esi ; \ decl %edx ; \ jg xhline_##name##_x_loop ; \ ; \ incl START_X /* next plane */ ; \ testl $3, START_X ; \ jnz xhline_##name##_no_plane_wrap ; \ incl SCREEN_ADDR ; \ xhline_##name##_no_plane_wrap: ; \ decl COUNTER ; \ jle xhline_done ; \ ; \ decl PLANE_COUNTER ; \ jg xhline_##name##_loop /* repeat for each plane */ FUNC(_x_hline) pushl %ebp movl %esp, %ebp subl $16, %esp /* 4 local variables: */ #define COUNTER -4(%ebp) #define START_X -8(%ebp) #define SCREEN_ADDR -12(%ebp) #define PLANE_COUNTER -16(%ebp) pushl %ebx pushl %esi pushl %edi pushw %es movl ARG1, %edx /* edx = bmp */ movl ARG2, %ebx /* ebx = x1 */ movl ARG3, %eax /* eax = y */ movl ARG4, %ecx /* ecx = x2 */ cmpl %ebx, %ecx jge xhline_no_xswap xchgl %ecx, %ebx _align_ xhline_no_xswap: cmpl $0, BMP_CLIP(%edx) /* test bmp->clip */ je xhline_noclip cmpl BMP_CT(%edx), %eax /* test bmp->ct */ jl xhline_done cmpl BMP_CB(%edx), %eax /* test bmp->cb */ jge xhline_done cmpl BMP_CL(%edx), %ebx /* test x1, bmp->cl */ jge xhline_x1_ok cmpl BMP_CL(%edx), %ecx /* test x2, bmp->cl */ jl xhline_done movl BMP_CL(%edx), %ebx /* clip x1 */ _align_ xhline_x1_ok: cmpl BMP_CR(%edx), %ecx /* test x2, bmp->cr */ jl xhline_noclip cmpl BMP_CR(%edx), %ebx /* test x1, bmp->cr */ jge xhline_done movl BMP_CR(%edx), %ecx /* clip x2 */ decl %ecx xhline_noclip: subl %ebx, %ecx /* loop counter */ incl %ecx movw BMP_SEG(%edx), %es /* segment selector */ cld movl %ebx, %edi /* dest address in edi */ shrl $2, %edi addl BMP_LINE(%edx, %eax, 4), %edi cmpl $DRAW_SOLID, GLOBL(_drawing_mode) je xhline_solid_mode /* solid draw? */ cmpl $DRAW_XOR, GLOBL(_drawing_mode) jne xhline_not_xor /* XOR? */ /* helper to set up an XOR mode draw */ #define SETUP \ movb $4, %al /* set the read plane */ ; \ movb %cl, %ah ; \ movl $0x3CE, %edx ; \ outw %ax, %dx ; \ ; \ movb ARG5, %al /* al = color */ #define LOOP_PUTTER \ xorb %al, %es:(%esi) HLINE_LOOP(xor, LOOP_PUTTER) #undef LOOP_PUTTER jmp xhline_done #undef SETUP _align_ xhline_not_xor: cmpl $DRAW_TRANS, GLOBL(_drawing_mode) jne xhline_not_trans /* translucent? */ /* helper to set up a translucent draw */ #define SETUP \ movb $4, %al /* set the read plane */ ; \ movb %cl, %ah ; \ movl $0x3CE, %edx ; \ outw %ax, %dx ; \ ; \ xorl %eax, %eax ; \ movb ARG5, %ah /* ah = color */ ; \ ; \ movl GLOBL(color_map), %ecx /* color map in ecx */ #define LOOP_PUTTER \ movb %es:(%esi), %al ; /* read existing color */ \ movb (%ecx, %eax), %al ; /* lookup color in table */ \ movb %al, %es:(%esi) /* write pixel */ HLINE_LOOP(trans, LOOP_PUTTER) #undef LOOP_PUTTER jmp xhline_done #undef SETUP _align_ xhline_not_trans: /* helper to set up a patterned draw */ #define SETUP \ movl START_X, %edi /* edi = pattern x */ ; \ movl ARG3, %ebx /* ebx = pattern y */ ; \ LOOKUP_PATTERN_POS(%edi, %ebx, %eax) ; \ movl GLOBL(_drawing_x_mask), %ecx ; \ movb ARG5, %ah /* color in ah */ cmpl $DRAW_COPY_PATTERN, GLOBL(_drawing_mode) je xhline_copy_pattern cmpl $DRAW_SOLID_PATTERN, GLOBL(_drawing_mode) je xhline_solid_pattern #define LOOP_PUTTER \ movb (%ebx, %edi), %al ; /* read pixel from pattern bitmap */ \ testb %al, %al ; /* test it */ \ jz xhline_masked_zero ; \ movb %ah, %es:(%esi) ; /* write solid pixel */ \ xhline_masked_zero: \ addl $4, %edi ; \ andl %ecx, %edi /* advance through pattern bitmap */ HLINE_LOOP(masked_pattern, LOOP_PUTTER) #undef LOOP_PUTTER jmp xhline_done _align_ xhline_solid_pattern: #define LOOP_PUTTER \ movb (%ebx, %edi), %al ; /* read pixel from pattern bitmap */ \ testb %al, %al ; /* test it */ \ jz xhline_solid_zero ; \ movb %ah, %al ; /* select a colored pixel */ \ xhline_solid_zero: \ movb %al, %es:(%esi) ; /* write pixel */ \ addl $4, %edi ; \ andl %ecx, %edi /* advance through pattern bitmap */ HLINE_LOOP(solid_pattern, LOOP_PUTTER) #undef LOOP_PUTTER jmp xhline_done _align_ xhline_copy_pattern: #define LOOP_PUTTER \ movb (%ebx, %edi), %al ; /* read pixel from pattern bitmap */ \ movb %al, %es:(%esi) ; /* write pixel */ \ addl $4, %edi ; \ andl %ecx, %edi /* advance through pattern bitmap */ HLINE_LOOP(copy_pattern, LOOP_PUTTER) #undef LOOP_PUTTER jmp xhline_done _align_ xhline_solid_mode: /* draw the line in a solid color */ movl $0x3C4, %edx /* preload port address */ andl $3, %ebx /* draw odd pixels on the left? */ jz xhline_laligned negl %ebx /* how many pixels to draw on the left? */ addl $4, %ebx subl %ebx, %ecx jge xhline_l_make_mask negl %ecx /* special case for very short lines */ subl %ecx, %ebx movb GLOBL(_x_left_mask_table)(%ebx), %ah shrb %cl, %ah xorl %ecx, %ecx jmp xhline_l_made_mask _align_ xhline_l_make_mask: movb GLOBL(_x_left_mask_table)(%ebx), %ah xhline_l_made_mask: movb $2, %al outw %ax, %dx /* select planes */ movb ARG5, %al /* get color */ stosb /* write odd pixels on the left */ test %ecx, %ecx jle xhline_done xhline_laligned: movl $0x0F02, %eax /* select all four planes */ outw %ax, %dx movb ARG5, %bl /* get color */ movb %bl, %bh shrdl $16, %ebx, %eax movw %bx, %ax /* get four copies of the color */ movl %ecx, %esi /* store width in esi */ shrl $2, %ecx /* divide by four for multi-plane writes */ jle xhline_no_block shrl $1, %ecx /* halve for 16 bit writes */ jnc xhline_no_byte stosb /* write an odd byte (four pixels) */ xhline_no_byte: jle xhline_no_block shrl $1, %ecx /* halve again for 32 bit writes */ jnc xhline_no_word stosw /* write an odd word (eight pixels) */ xhline_no_word: jle xhline_no_block rep ; stosl /* write 32 bit values (16 pixels each) */ _align_ xhline_no_block: andl $3, %esi /* draw odd pixels on the right? */ jz xhline_done movb GLOBL(_x_right_mask_table)(%esi), %ah movb $2, %al outw %ax, %dx /* select planes */ movb ARG5, %al /* get color */ stosb /* write odd pixels on the right */ _align_ xhline_done: popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_hline() */ #define SOURCE ARG1 /* parameters to the blitting functions */ #define DEST ARG2 #define SOURCE_X ARG3 #define SOURCE_Y ARG4 #define DEST_X ARG5 #define DEST_Y ARG6 #define WIDTH ARG7 #define HEIGHT ARG8 #define S_ADDR -4(%ebp) #define D_ADDR -8(%ebp) #define COUNT -4(%ebp) /* void _x_blit_from_memory(BITMAP *source, *dest, int source_x, source_y, * int dest_x, int dest_y, int width, int height); * Blits from a memory bitmap to a mode-X screen. The area will already have * been clipped when this routine is called. */ FUNC(_x_blit_from_memory) pushl %ebp movl %esp, %ebp subl $8, %esp /* 2 local variables (S_ADDR and D_ADDR) */ pushl %ebx pushl %esi pushl %edi pushw %es movl DEST, %eax movw BMP_SEG(%eax), %es /* load segment selector */ cld _align_ x_blit_from_mem_y_loop: /* for each line... */ movl SOURCE, %esi movl SOURCE_Y, %eax movl BMP_LINE(%esi, %eax, 4), %eax addl SOURCE_X, %eax movl %eax, S_ADDR /* got the source address */ movl DEST, %esi movl DEST_Y, %eax movl DEST_X, %ecx movl %ecx, %ebx shrl $2, %ebx addl BMP_LINE(%esi, %eax, 4), %ebx movl %ebx, D_ADDR /* got the dest address */ andb $3, %cl movl $0x1102, %eax shlb %cl, %ah /* write plane mask in ax */ xorl %ebx, %ebx /* ebx = plane counter */ _align_ x_blit_from_mem_plane_loop: /* for each plane... */ movl S_ADDR, %esi movl D_ADDR, %edi movl WIDTH, %ecx /* calculate width */ addl $3, %ecx subl %ebx, %ecx shrl $2, %ecx jz x_blit_from_mem_skip_plane movl $0x3C4, %edx outw %ax, %dx /* select the write plane */ pushl %ecx /* save registers for 8-byte loop */ pushl %eax shrl $3, %ecx /* calculate count value for 8-byte loop */ jz x_blit_resume_from_loop8 /* if zero, only do the 1-byte loop */ /* 8-byte loop: copy in 8-byte chunks */ _align_ x_blit_from_mem_x_loop8: movb 12(%esi), %ah movb 28(%esi), %dh movb 8(%esi), %al movb 24(%esi), %dl shll $16, %eax shll $16, %edx movb 4(%esi), %ah movb 20(%esi), %dh movb (%esi), %al movb 16(%esi), %dl movl %eax, %es:(%edi) movl %edx, %es:4(%edi) addl $32, %esi /* 8 bytes planar -> 32 bytes linear */ addl $8, %edi decl %ecx jnz x_blit_from_mem_x_loop8 x_blit_resume_from_loop8: popl %eax /* restore registers after 8-byte loop */ popl %ecx andl $7, %ecx /* calculate count for 1-byte loop */ jz x_blit_from_mem_skip_plane /* if zero, we are done */ /* 1-byte loop */ _align_ x_blit_from_mem_x_loop: movsb /* copy a pixel */ addl $3, %esi /* fix up linear memory pointer */ decl %ecx jg x_blit_from_mem_x_loop x_blit_from_mem_skip_plane: rolb $1, %ah /* advance the plane position */ adcl $0, D_ADDR incl S_ADDR incl %ebx /* next plane */ cmpl $4, %ebx jl x_blit_from_mem_plane_loop incl SOURCE_Y /* next line */ incl DEST_Y decl HEIGHT jg x_blit_from_mem_y_loop /* loop */ popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_blit_from_memory() */ FUNC(_x_blit_from_memory_end) ret /* void _x_blit_to_memory(BITMAP *source, *dest, int source_x, source_y, * int dest_x, int dest_y, int width, int height); * Blits to a memory bitmap from a mode-X screen. The area will already have * been clipped when this routine is called. */ FUNC(_x_blit_to_memory) pushl %ebp movl %esp, %ebp subl $8, %esp /* 2 local variables (S_ADDR and D_ADDR) */ pushl %ebx pushl %esi pushl %edi pushw %ds movl $0x3CE, %edx /* load port address into edx */ movl SOURCE, %eax movw %es:BMP_SEG(%eax), %ds /* load segment selector */ cld _align_ x_blit_to_mem_y_loop: /* for each line... */ movl DEST, %edi movl DEST_Y, %eax movl %es:BMP_LINE(%edi, %eax, 4), %eax addl DEST_X, %eax movl %eax, D_ADDR /* got the dest address */ movl SOURCE, %esi movl SOURCE_Y, %eax movl SOURCE_X, %ecx movl %ecx, %ebx shrl $2, %ebx addl %es:BMP_LINE(%esi, %eax, 4), %ebx movl %ebx, S_ADDR /* got the source address */ movb $4, %al /* set the correct plane */ movb %cl, %ah andb $3, %ah xorl %ebx, %ebx /* ebx = plane counter */ _align_ x_blit_to_mem_plane_loop: /* for each plane... */ movl S_ADDR, %esi movl D_ADDR, %edi movl WIDTH, %ecx /* calculate width */ addl $3, %ecx subl %ebx, %ecx shrl $2, %ecx jz x_blit_to_mem_skip_plane outw %ax, %dx /* select the read plane */ _align_ x_blit_to_mem_x_loop: movsb /* copy a pixel */ addl $3, %edi /* fix up linear memory pointer */ decl %ecx jg x_blit_to_mem_x_loop x_blit_to_mem_skip_plane: addb $1, %ah /* advance the plane position */ test $4, %ah jz x_blit_to_mem_no_add incl S_ADDR xor %ah, %ah x_blit_to_mem_no_add: incl D_ADDR incl %ebx /* next plane */ cmpl $4, %ebx jl x_blit_to_mem_plane_loop incl SOURCE_Y /* next line */ incl DEST_Y decl HEIGHT jg x_blit_to_mem_y_loop /* loop */ popw %ds popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_blit_to_memory() */ FUNC(_x_blit_to_memory_end) ret /* void x_latched_blit(BITMAP *source, BITMAP *dest, int source_x, source_y, int dest_x, int dest_y, int width, int height); * Blits from one part of a mode-X screen to another, using the VGA latch * registers. It should only be called when the two regions have the same * plane alignment, and the area should already have been clipped. */ _align_ x_latched_blit: subl $8, %esp /* 2 local variables: */ #define LMASK -4(%ebp) #define RMASK -8(%ebp) pushl %ebx pushl %esi pushl %edi pushw %es pushw %ds movl $0, LMASK movl $0, RMASK movl WIDTH, %ecx /* ecx = width */ movl SOURCE_X, %eax /* eax = source x */ andl $3, %eax jz x_latched_blit_laligned negl %eax /* how many odd pixels on the left? */ addl $4, %eax subl %eax, %ecx /* adjust width */ jge x_latched_blit_make_lmask negl %ecx /* special case for very narrow blits */ subl %ecx, %eax movb GLOBL(_x_left_mask_table)(%eax), %ah shrb %cl, %ah xorl %ecx, %ecx jmp x_latched_blit_made_lmask _align_ x_latched_blit_make_lmask: movb GLOBL(_x_left_mask_table)(%eax), %ah x_latched_blit_made_lmask: movb $2, %al /* store left edge mask */ movw %ax, LMASK _align_ x_latched_blit_laligned: movl %ecx, %eax shrl $2, %ecx movl %ecx, %ebx /* store main loop counter in ebx */ andl $3, %eax /* how many odd pixels on the right? */ jz x_latched_blit_raligned movb GLOBL(_x_right_mask_table)(%eax), %ah movb $2, %al movw %ax, RMASK _align_ x_latched_blit_raligned: movl DEST, %edx /* load segment selectors */ movl BMP_SEG(%edx), %eax movw %ax, %ds movw %ax, %es cld movl $0x3CE, %edx movb $5, %al outb %al, %dx /* 3CE index 5 */ incl %edx inb %dx, %al /* read+alter */ andb $0xFC, %al orb $1, %al outb %al, %dx /* enable the latches */ shrl $2, SOURCE_X /* adjust the x offsets */ shrl $2, DEST_X movl $0x3C4, %edx /* preload port address for plane enables */ _align_ x_latched_blit_loop: movl SOURCE, %ecx movl SOURCE_Y, %eax /* get source address in esi */ movl %ss:BMP_LINE(%ecx, %eax, 4), %esi addl SOURCE_X, %esi movl DEST, %ecx movl DEST_Y, %eax /* get dest address in edi */ movl %ss:BMP_LINE(%ecx, %eax, 4), %edi addl DEST_X, %edi movl LMASK, %eax /* copy odd pixels on the left? */ orl %eax, %eax jz x_latched_no_left_pixels outw %ax, %dx /* copy on the left */ movsb _align_ x_latched_no_left_pixels: orl %ebx, %ebx /* main copy loop? */ movl %ebx, %ecx jz x_latched_no_middle_pixels movl $0x0F02, %eax /* enable all planes */ outw %ax, %dx rep ; movsb /* do the bulk of the copy */ x_latched_no_middle_pixels: movl RMASK, %eax /* copy odd pixels on the right? */ orl %eax, %eax jz x_latched_no_right_pixels outw %ax, %dx /* copy on the right */ movsb _align_ x_latched_no_right_pixels: incl SOURCE_Y /* next line */ incl DEST_Y decl HEIGHT jg x_latched_blit_loop /* loop */ movl $0x3CE, %edx movb $5, %al /* 3CE index 5 */ outb %al, %dx incl %edx inb %dx, %al /* read+alter */ andb $0xFC, %al outb %al, %dx /* disable the latches */ popw %ds popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of x_latched_blit() */ /* void _x_blit(BITMAP *source, BITMAP *dest, int source_x, source_y, int dest_x, int dest_y, int width, int height); * Blits from one part of a mode-X screen to another, drawing plane-by-plane * (only safe when the two areas don't overlap). The area will already have * been clipped when this routine is called. */ FUNC(_x_blit) pushl %ebp movl %esp, %ebp movl SOURCE_X, %eax /* use latches if the areas are aligned */ andl $3, %eax movl DEST_X, %edx andl $3, %edx cmpl %eax, %edx je x_latched_blit pushl %ebx pushl %esi pushl %edi pushw %es pushw %ds movl DEST, %edx /* load segment selectors */ movl BMP_SEG(%edx), %eax movw %ax, %ds movw %ax, %es cld _align_ x_blit_loop: xorl %ebx, %ebx /* ebx = current plane */ _align_ x_blit_next_plane: movl SOURCE_X, %esi addl %ebx, %esi /* esi = source_x coordinate */ movl %esi, %ecx andb $3, %cl movb %cl, %ah movb $4, %al movl $0x3CE, %edx outw %ax, %dx /* set the read plane */ movl DEST_X, %edi addl %ebx, %edi /* edi = dest_x coordinate */ movl %edi, %ecx andb $3, %cl movl $0x102, %eax shlb %cl, %ah movl $0x3C4, %edx outw %ax, %dx /* set the write plane */ shrl $2, %esi /* get source address in esi */ movl SOURCE, %edx movl SOURCE_Y, %eax addl %ss:BMP_LINE(%edx, %eax, 4), %esi shrl $2, %edi /* get dest address in edi */ movl DEST, %edx movl DEST_Y, %eax addl %ss:BMP_LINE(%edx, %eax, 4), %edi movl WIDTH, %ecx /* get counter in ecx */ addl $3, %ecx subl %ebx, %ecx shrl $2, %ecx jz x_blit_skip_plane shrl $1, %ecx /* halve for word copy */ jnc x_blit_no_byte movsb /* copy an odd byte? */ _align_ x_blit_no_byte: shrl $1, %ecx /* halve again for long copy */ jnc x_blit_no_word movsw /* copy an odd word? */ _align_ x_blit_no_word: jz x_blit_skip_plane rep ; movsl; /* copy a plane of data */ x_blit_skip_plane: incl %ebx /* next plane */ cmpl $4, %ebx jl x_blit_next_plane incl SOURCE_Y /* next line */ incl DEST_Y decl HEIGHT jg x_blit_loop /* loop */ popw %ds popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_blit() */ /* void _x_blit_forward(BITMAP *source, BITMAP *dest, int source_x, source_y, int dest_x, int dest_y, int width, int height); * Blits from one part of a mode-X screen to another, drawing from top to * bottom (much slower than doing it plane-by-plane, but sometimes required * if the regions overlap). The area will already have been clipped when * this routine is called. */ FUNC(_x_blit_forward) pushl %ebp movl %esp, %ebp movl SOURCE_X, %eax /* use latches if the areas are aligned */ andl $3, %eax movl DEST_X, %edx andl $3, %edx cmpl %eax, %edx je x_latched_blit subl $4, %esp /* 1 local variable (COUNT) */ pushl %ebx pushl %esi pushl %edi pushw %es movl DEST, %edx /* load segment selector */ movl BMP_SEG(%edx), %eax movl %eax, %es _align_ x_blit_forward_y_loop: movl WIDTH, %eax /* initialise x loop counter */ movl %eax, COUNT movl SOURCE_X, %esi /* esi = source_x coordinate */ movl DEST_X, %edi /* edi = dest_x coordinate */ movl %esi, %ebx /* get read plane mask in bx */ andb $3, %bl movb %bl, %bh movb $4, %bl movl %edi, %ecx /* get write plane mask in cx */ andb $3, %cl movb $0x11, %ch shlb %cl, %ch movb $2, %cl shrl $2, %esi /* get source address in esi */ movl SOURCE, %edx movl SOURCE_Y, %eax addl BMP_LINE(%edx, %eax, 4), %esi shrl $2, %edi /* get dest address in edi */ movl DEST, %edx movl DEST_Y, %eax addl BMP_LINE(%edx, %eax, 4), %edi _align_ x_blit_forward_x_loop: movl $0x3CE, %edx /* set the read plane */ movl %ebx, %eax outw %ax, %dx movl $0x3C4, %edx /* set the write plane */ movl %ecx, %eax outw %ax, %dx movb %es:(%esi), %al /* copy a pixel */ movb %al, %es:(%edi) incb %bh /* advance the read position */ testb $4, %bh jz x_blit_forward_no_read_wrap xorb %bh, %bh /* wraps every four pixels */ incl %esi _align_ x_blit_forward_no_read_wrap: rolb $1, %ch /* advance the write position */ adcl $0, %edi _align_ x_blit_forward_no_write_wrap: decl COUNT jg x_blit_forward_x_loop /* x loop */ incl SOURCE_Y /* move on to the next line */ incl DEST_Y decl HEIGHT jg x_blit_forward_y_loop /* y loop */ popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_blit_forward() */ /* void _x_blit_backward(BITMAP *source, BITMAP *dest, int source_x, source_y, int dest_x, int dest_y, int width, int height); * Blits from one part of a mode-X screen to another, drawing from bottom * to top (much slower than doing it plane-by-plane, but sometimes required * if the regions overlap). The area will already have been clipped when * this routine is called. */ FUNC(_x_blit_backward) pushl %ebp movl %esp, %ebp subl $4, %esp /* 1 local variable (COUNT) */ pushl %ebx pushl %esi pushl %edi pushw %es movl HEIGHT, %eax /* y adjust for starting at the bottom */ decl %eax addl %eax, SOURCE_Y addl %eax, DEST_Y movl WIDTH, %eax /* x adjust for starting at the right */ decl %eax addl %eax, SOURCE_X addl %eax, DEST_X movl DEST, %edx /* load segment selector */ movl BMP_SEG(%edx), %eax movl %eax, %es _align_ x_blit_backward_y_loop: movl WIDTH, %eax /* initialise x loop counter */ movl %eax, COUNT movl SOURCE_X, %esi /* esi = source_x coordinate */ movl DEST_X, %edi /* edi = dest_x coordinate */ movl %esi, %ebx /* get read plane mask in bx */ andb $3, %bl movb %bl, %bh movb $4, %bl movl %edi, %ecx /* get write plane mask in cx */ andb $3, %cl movb $0x11, %ch shlb %cl, %ch movb $2, %cl shrl $2, %esi /* get source address in esi */ movl SOURCE, %edx movl SOURCE_Y, %eax addl BMP_LINE(%edx, %eax, 4), %esi shrl $2, %edi /* get dest address in edi */ movl DEST, %edx movl DEST_Y, %eax addl BMP_LINE(%edx, %eax, 4), %edi _align_ x_blit_backward_x_loop: movl $0x3CE, %edx /* set the read plane */ movl %ebx, %eax outw %ax, %dx movl $0x3C4, %edx /* set the write plane */ movl %ecx, %eax outw %ax, %dx movb %es:(%esi), %al /* copy a pixel */ movb %al, %es:(%edi) decb %bh /* advance the read position */ jge x_blit_backward_no_read_wrap movb $3, %bh /* wraps every four pixels */ decl %esi _align_ x_blit_backward_no_read_wrap: rorb $1, %ch /* advance the write position */ sbbl $0, %edi _align_ x_blit_backward_no_write_wrap: decl COUNT jg x_blit_backward_x_loop /* x loop */ decl SOURCE_Y /* move on to the next line */ decl DEST_Y decl HEIGHT jg x_blit_backward_y_loop /* y loop */ popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_blit_backward() */ /* void _x_masked_blit(BITMAP *source, *dest, int source_x, source_y, * int dest_x, int dest_y, int width, int height); * Blits from a memory bitmap to a mode-X screen, skipping zero pixels. * The area will already have been clipped when this routine is called. */ FUNC(_x_masked_blit) pushl %ebp movl %esp, %ebp subl $8, %esp /* 2 local variables (S_ADDR and D_ADDR) */ pushl %ebx pushl %esi pushl %edi pushw %es movl $0x3C4, %edx /* load port address into edx */ movl DEST, %eax movw BMP_SEG(%eax), %es /* load segment selector */ cld _align_ x_masked_blit_y_loop: /* for each line... */ movl SOURCE, %esi movl SOURCE_Y, %eax movl BMP_LINE(%esi, %eax, 4), %eax addl SOURCE_X, %eax movl %eax, S_ADDR /* got the source address */ movl DEST, %esi movl DEST_Y, %eax movl DEST_X, %ecx movl %ecx, %ebx shrl $2, %ebx addl BMP_LINE(%esi, %eax, 4), %ebx movl %ebx, D_ADDR /* got the dest address */ andb $3, %cl movl $0x1102, %eax shlb %cl, %ah /* write plane mask in ax */ xorl %ebx, %ebx /* ebx = plane counter */ _align_ x_masked_blit_plane_loop: /* for each plane... */ movl S_ADDR, %esi movl D_ADDR, %edi movl WIDTH, %ecx /* calculate width */ addl $3, %ecx subl %ebx, %ecx shrl $2, %ecx jz x_masked_blit_skip_plane outw %ax, %dx /* select the write plane */ pushl %eax _align_ x_masked_blit_x_loop: lodsb /* read a pixel */ orb %al, %al /* test it */ jz x_masked_blit_skip_pixel stosb /* write the pixel */ addl $3, %esi /* fix up linear memory pointer */ decl %ecx jg x_masked_blit_x_loop jmp x_masked_blit_loop_done _align_ x_masked_blit_skip_pixel: incl %edi addl $3, %esi /* fix up linear memory pointer */ decl %ecx jg x_masked_blit_x_loop x_masked_blit_loop_done: popl %eax x_masked_blit_skip_plane: rolb $1, %ah /* advance the plane position */ adcl $0, D_ADDR incl S_ADDR incl %ebx /* next plane */ cmpl $4, %ebx jl x_masked_blit_plane_loop incl SOURCE_Y /* next line */ incl DEST_Y decl HEIGHT jg x_masked_blit_y_loop /* loop */ popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_masked_blit() */ #undef SOURCE #undef DEST #undef SOURCE_X #undef SOURCE_Y #undef DEST_X #undef DEST_Y #undef WIDTH #undef HEIGHT #undef S_ADDR #undef D_ADDR #define DEST ARG1 /* parameters to the sprite draw functions */ #define SOURCE ARG2 #define DEST_X ARG3 #define DEST_Y ARG4 #define S_ADDR -4(%ebp) #define D_ADDR -8(%ebp) #define SOURCE_Y -12(%ebp) #define WIDTH -16(%ebp) #define HEIGHT -20(%ebp) #define SOURCE_X -24(%ebp) /* void _x_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y); * Draws a sprite onto a mode-X screen. */ FUNC(_x_draw_sprite) pushl %ebp movl %esp, %ebp subl $24, %esp /* 6 local variables */ pushl %ebx pushl %esi pushl %edi pushw %es movl $0x3C4, %edx /* load port address into edx */ movl DEST, %eax movw BMP_SEG(%eax), %es /* load segment selector */ cld movl SOURCE, %esi movl BMP_W(%esi), %eax movl %eax, WIDTH movl BMP_H(%esi), %eax movl %eax, HEIGHT movl $0, SOURCE_X movl $0, SOURCE_Y /* set source variables */ movl DEST, %esi cmpl $0, BMP_CLIP(%esi) /* clipping -> ... */ jz x_draw_sprite_noclip movl BMP_CL(%esi), %eax subl DEST_X, %eax jle x_drspr_noclip_lx addl %eax, DEST_X addl %eax, SOURCE_X subl %eax, WIDTH jle x_draw_sprite_not x_drspr_noclip_lx: movl BMP_CR(%esi), %eax subl DEST_X, %eax subl WIDTH, %eax jge x_drspr_noclip_rx addl %eax, WIDTH jle x_draw_sprite_not x_drspr_noclip_rx: movl BMP_CT(%esi), %eax subl DEST_Y, %eax jle x_drspr_noclip_ty addl %eax, DEST_Y addl %eax, SOURCE_Y subl %eax, HEIGHT jle x_draw_sprite_not x_drspr_noclip_ty: movl BMP_CB(%esi), %eax subl DEST_Y, %eax subl HEIGHT, %eax jge x_drspr_noclip_by addl %eax, HEIGHT jle x_draw_sprite_not _align_ x_drspr_noclip_by: x_draw_sprite_noclip: /* <--- */ x_draw_sprite_y_loop: /* for each line... */ movl SOURCE, %esi movl SOURCE_Y, %eax movl BMP_LINE(%esi,%eax,4), %eax addl SOURCE_X, %eax movl %eax, S_ADDR /* got the source address */ movl DEST, %esi movl DEST_Y, %eax movl DEST_X, %ecx movl %ecx, %ebx shrl $2, %ebx addl BMP_LINE(%esi, %eax, 4), %ebx movl %ebx, D_ADDR /* got the dest address */ andb $3, %cl movb $0x11, %ah shlb %cl, %ah /* write plane mask in ax */ xorl %ebx, %ebx /* ebx = plane counter */ _align_ x_draw_sprite_plane_loop: /* for each plane... */ movl S_ADDR, %esi movl D_ADDR, %edi movl WIDTH, %ecx /* calculate width */ addl $3, %ecx subl %ebx, %ecx shrl $2, %ecx jz x_draw_sprite_skip_plane movb $2, %al outw %ax, %dx /* select the write plane */ _align_ x_draw_sprite_x_loop: lodsb /* load a pixel */ orb %al, %al jz x_draw_sprite_no_draw /* skip if zero */ stosb /* store a pixel */ addl $3, %esi /* fix up linear memory pointer */ decl %ecx jg x_draw_sprite_x_loop jmp x_draw_sprite_skip_plane _align_ x_draw_sprite_no_draw: incl %edi /* skip a pixel */ addl $3, %esi /* fix up linear memory pointer */ decl %ecx jg x_draw_sprite_x_loop x_draw_sprite_skip_plane: rolb $1, %ah /* advance the plane position */ adcl $0, D_ADDR incl S_ADDR incl %ebx /* next plane */ cmpl $4, %ebx jl x_draw_sprite_plane_loop incl SOURCE_Y /* next line */ incl DEST_Y decl HEIGHT jg x_draw_sprite_y_loop /* loop */ x_draw_sprite_not: popw %es popl %edi popl %esi popl %ebx movl %ebp, %esp popl %ebp ret /* end of _x_draw_sprite() */ FUNC(_x_draw_sprite_end) ret .section .note.GNU-stack,"",@progbits #endif /* (!defined ALLEGRO_LINUX) || ((defined ALLEGRO_LINUX_VGA) && ... */ allegro-4.4.3.1/src/misc/fm_emu.h0000664000175000017500000001321713437077643015447 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The OSS driver does not support percussion mode, so we have to * "emulate" the percussion instruments using normal "melodic" mode. * Some of these come from the SBTimbre package, others I (Peter Wang) * tweaked manually. Please feel free to make these sound good. */ static FM_INSTRUMENT fm_emulated_drum[47] = { { 0x11, 0x10, 0x90, 0x00, 0xF8, 0xF6, 0xA5, 0xA5, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* ACOUBASS */ { 0x00, 0x00, 0x0B, 0x0B, 0xA8, 0xD6, 0x4C, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* BASSDRM1 */ { 0x02, 0x00, 0xA1, 0x00, 0xCA, 0xBB, 0x76, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* SIDESTIC */ { 0x10, 0x00, 0x03, 0x03, 0xF1, 0xF6, 0xF5, 0xB5, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* ACOUSNAR */ { 0x66, 0x57, 0x0A, 0x08, 0xB1, 0xB4, 0x45, 0x05, 0x02, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* HANDCLAP */ { 0x06, 0x00, 0x08, 0x00, 0xF0, 0xF6, 0xC0, 0x66, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* ELECSNAR */ { 0x00, 0x90, 0x02, 0x55, 0xC6, 0xF6, 0x77, 0x87, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* LFTOM */ { 0x06, 0x17, 0x10, 0x12, 0xB1, 0xB4, 0x45, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* CLSHIHAT */ { 0x00, 0x30, 0x02, 0x52, 0xC7, 0xF7, 0x75, 0xF5, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* HFTOM */ { 0x06, 0x17, 0x0E, 0x17, 0xB0, 0xB3, 0x45, 0x16, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* PDLHIHAT */ { 0x01, 0x10, 0x0D, 0x15, 0xD3, 0xF4, 0x12, 0x15, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00 }, /* LOWTOM */ { 0x06, 0x17, 0x0F, 0x15, 0xB0, 0xB3, 0x45, 0x14, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* OPNHIHAT */ { 0x90, 0x32, 0x0E, 0x46, 0x83, 0xD5, 0x95, 0x98, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* LMIDTOM */ { 0x90, 0x33, 0x0E, 0x46, 0x84, 0xD5, 0x96, 0x98, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* HMIDTOM */ { 0xA7, 0x36, 0x03, 0x04, 0x90, 0xF4, 0xD6, 0xC6, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00 }, /* CRSCYM1 */ { 0x11, 0x11, 0x11, 0x00, 0xA4, 0xB6, 0x46, 0x27, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00 }, /* HIGHTOM */ { 0xA7, 0x36, 0x03, 0x12, 0x90, 0xF4, 0xD6, 0xC6, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00 }, /* RIDECYM1 */ { 0xA7, 0x36, 0x03, 0x04, 0x90, 0xF4, 0xD6, 0xC6, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00 }, /* CHCYM1 */ { 0xA7, 0x36, 0x03, 0x0D, 0x90, 0xF4, 0xD6, 0xC6, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00 }, /* RIDEBELL */ { 0x06, 0x16, 0x06, 0x00, 0xA2, 0xA4, 0x35, 0x33, 0x02, 0x02, 0x0E, 0x00, 0x00, 0x00 }, /* TAMB */ { 0xA7, 0x36, 0x03, 0x04, 0x90, 0xF4, 0xD6, 0xC6, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00 }, /* SPLSHCYM */ { 0x16, 0x11, 0x10, 0x00, 0x90, 0xB7, 0x54, 0x06, 0x04, 0x05, 0x0E, 0x00, 0x00, 0x00 }, /* COWBELL */ { 0xA7, 0x36, 0x03, 0x04, 0x90, 0xF4, 0xD6, 0xC6, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x00 }, /* CRSHCYM2 */ { 0x40, 0x81, 0x52, 0x02, 0x80, 0x92, 0x98, 0x08, 0x06, 0x00, 0x0A, 0x00, 0x00, 0x00 }, /* VIBRASLP */ { 0x40, 0x81, 0x52, 0x02, 0x80, 0x92, 0x98, 0x08, 0x06, 0x00, 0x0A, 0x00, 0x00, 0x00 }, /* RIDECYM2 */ { 0x91, 0xD1, 0x12, 0x0D, 0x95, 0xD2, 0x60, 0x14, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00 }, /* HIBONGO */ { 0x91, 0xD1, 0x12, 0x0D, 0x95, 0xD2, 0x60, 0x14, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00 }, /* LOWBONGO */ { 0x10, 0x11, 0x11, 0x00, 0xA4, 0xC5, 0x47, 0x25, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* MHICONGA */ { 0x20, 0x11, 0x11, 0x00, 0xA5, 0xC8, 0x46, 0x24, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* OHICONGA */ { 0x20, 0x11, 0x11, 0x00, 0xA5, 0xC8, 0x46, 0x24, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* LOWCONGA */ { 0x02, 0xC1, 0x00, 0x0D, 0xFE, 0xF6, 0xF0, 0xB5, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* HIGHTIMB */ { 0x00, 0xC0, 0x0D, 0x0D, 0x9E, 0x96, 0xF0, 0xB5, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* LOWTIMB */ { 0x44, 0x54, 0x4D, 0x4D, 0xB5, 0xD5, 0x54, 0x27, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00 }, /* HIAGOGO */ { 0x43, 0x53, 0x4D, 0x4D, 0xB5, 0xD5, 0x54, 0x27, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00 }, /* LOWAGOGO */ { 0x06, 0x00, 0x00, 0x0B, 0xF1, 0xF9, 0xBA, 0xBA, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* CABASA */ { 0x06, 0x00, 0x00, 0x0D, 0xF1, 0xF9, 0xBA, 0xBA, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }, /* MARACAS */ { 0x5D, 0x5D, 0x4D, 0x40, 0xB5, 0xD9, 0x54, 0x27, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00 }, /* SHWHISTL */ { 0x5D, 0x5D, 0x4D, 0x40, 0xB4, 0xD8, 0x55, 0x26, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00 }, /* LNGWHIST */ { 0x20, 0x3B, 0x13, 0x8D, 0xA4, 0x46, 0xE9, 0xEA, 0x04, 0x05, 0x0E, 0x00, 0x00, 0x00 }, /* SHGUIRO */ { 0x20, 0x3A, 0x13, 0x8D, 0xA2, 0x43, 0xE3, 0xE3, 0x04, 0x05, 0x0E, 0x00, 0x00, 0x00 }, /* LNGUIRO */ { 0x13, 0x16, 0x11, 0x0D, 0xA5, 0xC5, 0xA3, 0x27, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00 }, /* CLAVES */ { 0x03, 0x04, 0xA1, 0x09, 0xCA, 0xA9, 0x76, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* HIGHWOOD */ { 0x01, 0x02, 0xA1, 0x08, 0xC8, 0xA8, 0x75, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* LOWWOOD */ { 0x20, 0x3B, 0x13, 0x8D, 0xA4, 0x4A, 0xE9, 0xEA, 0x04, 0x05, 0x0E, 0x00, 0x00, 0x00 }, /* MUTECUIC */ { 0x20, 0x3B, 0x13, 0x8D, 0xA4, 0x46, 0xE9, 0xE9, 0x04, 0x05, 0x0E, 0x00, 0x00, 0x00 }, /* OPENCUIC */ { 0xBE, 0x4F, 0x00, 0x48, 0xF7, 0xF8, 0xFD, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }, /* MUTETRIG */ { 0xBE, 0x4F, 0x00, 0x48, 0xF4, 0xE5, 0xA6, 0xB5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 } /* OPENTRIG */ }; allegro-4.4.3.1/src/misc/modexsms.h0000664000175000017500000000005513437077643016032 0ustar siegesiegeextern void (*_split_modex_screen_ptr)(int); allegro-4.4.3.1/src/misc/vbeaf.c0000664000175000017500000023624013437077643015260 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video driver using the VBE/AF 2.0 hardware accelerator API, * plus extensions added by the FreeBE/AF project. * * This driver provides accelerated support for: * * - scanline fills (solid, XOR, and patterned) * - area fills (solid, XOR, and patterned) * - line drawing (solid and XOR) * - triangle drawing (solid and XOR) * - monochrome character expansion * - blitting within the video memory * - masked blitting within the video memory * - blits from system memory * - masked blits from system memory * - hardware mouse cursors * * The FreeBE/AF project (http://www.talula.demon.co.uk/freebe/) * has defined a number of API extensions, of which this driver * implements: * * FAFEXT_INIT - extension init and new driver relocation mechanism * FAFEXT_HWPTR - farptr access to video memory (no more Fat DS hack) * FAFEXT_LIBC - exports a bunch of callback functions from libc * FAFEXT_PMODE - exports the SciTech pmode API callback functions * * On the subject of VBE/AF in general: * * Kendall Bennett and Tom Ryan of SciTech software deserve * significant thanks for coming up with such a magnificent API and * then helping me write this driver, after the VESA people (may they * be smitten with plagues of locusts and then develop subtle memory * leaks in their code :-) decided to charge stupid sums of money for * copies of the /AF specification. Unfortunately, SciTech have * subsequently abandoned VBE/AF in favour of a closed, proprietary * system called Nucleus. Ah well, I'm sure that this makes sense * for them in commercial terms, even if it is something of a * disappointment for us idealistic hacker types... * * The problem with Nucleus is that the spec is only available under * NDA, so I cannot support it directly in Allegro. The plan, * therefore, is to write a Nucleus to VBE/AF wrapper driver. * This requires a few callback routines that stock VBE/AF doesn't * provide, hence the Nucleus-specific extensions in this file. It * doesn't provide direct Nucleus support, but hopefully will enable * someone (whether us or SciTech) to add that support in the future * via an external driver binary. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #if (defined ALLEGRO_DOS) || (defined ALLEGRO_LINUX_VBEAF) #include "allegro/internal/aintern.h" #ifdef ALLEGRO_INTERNAL_HEADER #include ALLEGRO_INTERNAL_HEADER #endif #if (defined ALLEGRO_DJGPP) && (!defined SCAN_DEPEND) #include #include #include #endif /* main driver routines */ static BITMAP *vbeaf_init(int w, int h, int v_w, int v_h, int color_depth); static void vbeaf_exit(BITMAP *b); static void vbeaf_save(void); static void vbeaf_restore(void); static GFX_MODE_LIST *vbeaf_fetch_mode_list(void); static void vbeaf_vsync(void); static int vbeaf_scroll(int x, int y); static void vbeaf_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync); static int vbeaf_request_scroll(int x, int y); static int vbeaf_poll_scroll(void); static int vbeaf_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus); static int vbeaf_show_mouse(BITMAP *bmp, int x, int y); static void vbeaf_hide_mouse(void); static void vbeaf_move_mouse(int x, int y); static void vbeaf_drawing_mode(void); static int vbeaf_locate_driver(void); static int vbeaf_lowlevel_init(void); /* accelerated drawing functions */ static void vbeaf_hline(BITMAP *bmp, int x1, int y, int x2, int color); static void vbeaf_vline_a(BITMAP *bmp, int x, int y1, int y2, int color); static void vbeaf_vline_b(BITMAP *bmp, int x, int y1, int y2, int color); static void vbeaf_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); static void vbeaf_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); static void vbeaf_triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color); static void vbeaf_draw_glyph(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg); static void vbeaf_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y); static void vbeaf_blit_from_memory(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void vbeaf_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void vbeaf_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void vbeaf_clear_to_color(BITMAP *bitmap, int color); #ifdef ALLEGRO_DOS static void vbeaf_move_mouse_end(void); static void vbeaf_draw_sprite_end(void); static void vbeaf_blit_from_memory_end(void); #endif /* original software drawing functions */ static void (*orig_vline)(BITMAP *bmp, int x, int y1, int y2, int color); static void (*orig_hline)(BITMAP *bmp, int x1, int y, int x2, int color); static void (*orig_line)(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); static void (*orig_rectfill)(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); static void (*orig_draw_glyph)(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg); static void (*orig_draw_sprite)(BITMAP *bmp, BITMAP *sprite, int x, int y); static void (*orig_masked_blit)(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static char vbeaf_desc[256] = EMPTY_STRING; /* the video driver structure */ GFX_DRIVER gfx_vbeaf = { GFX_VBEAF, empty_string, empty_string, "VBE/AF", vbeaf_init, vbeaf_exit, vbeaf_scroll, vbeaf_vsync, vbeaf_set_palette_range, vbeaf_request_scroll, vbeaf_poll_scroll, NULL, /* enable triple buffer */ NULL, NULL, NULL, NULL, /* no video bitmaps */ NULL, NULL, /* no system bitmaps */ NULL, NULL, NULL, NULL, /* no hardware cursor (yet) */ NULL, /* no drawing mode hook */ vbeaf_save, vbeaf_restore, NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ vbeaf_fetch_mode_list, /* fetch mode hook */ 0, 0, FALSE, 0, 0, 0, 0, FALSE }; typedef struct AF_FIX_POINT /* fixed point coordinate pair */ { fixed x; fixed y; } AF_FIX_POINT; typedef struct AF_TRAP /* trapezium information block */ { long y; long count; fixed x1; fixed x2; fixed slope1; fixed slope2; } AF_TRAP; typedef struct AF_CURSOR /* hardware cursor description */ { unsigned long xorMask[32]; unsigned long andMask[32]; unsigned long hotx; unsigned long hoty; } AF_CURSOR; typedef struct AF_PALETTE /* color value (not in Allegro order) */ { unsigned char blue; unsigned char green; unsigned char red; unsigned char alpha; } AF_PALETTE; #ifdef ALLEGRO_GCC #define __PACKED__ __attribute__ ((packed)) #else #define __PACKED__ #endif #ifdef ALLEGRO_WATCOM #pragma pack (1) #endif typedef struct AF_MODE_INFO /* mode information structure */ { unsigned short Attributes __PACKED__; unsigned short XResolution __PACKED__; unsigned short YResolution __PACKED__; unsigned short BytesPerScanLine __PACKED__; unsigned short BitsPerPixel __PACKED__; unsigned short MaxBuffers __PACKED__; unsigned char RedMaskSize; unsigned char RedFieldPosition; unsigned char GreenMaskSize; unsigned char GreenFieldPosition; unsigned char BlueMaskSize; unsigned char BlueFieldPosition; unsigned char RsvdMaskSize; unsigned char RsvdFieldPosition; unsigned short MaxBytesPerScanLine __PACKED__; unsigned short MaxScanLineWidth __PACKED__; /* VBE/AF 2.0 extensions */ unsigned short LinBytesPerScanLine __PACKED__; unsigned char BnkMaxBuffers; unsigned char LinMaxBuffers; unsigned char LinRedMaskSize; unsigned char LinRedFieldPosition; unsigned char LinGreenMaskSize; unsigned char LinGreenFieldPosition; unsigned char LinBlueMaskSize; unsigned char LinBlueFieldPosition; unsigned char LinRsvdMaskSize; unsigned char LinRsvdFieldPosition; unsigned long MaxPixelClock __PACKED__; unsigned long VideoCapabilities __PACKED__; unsigned short VideoMinXScale __PACKED__; unsigned short VideoMinYScale __PACKED__; unsigned short VideoMaxXScale __PACKED__; unsigned short VideoMaxYScale __PACKED__; unsigned char reserved[76]; } AF_MODE_INFO; #define DC struct AF_DRIVER *dc typedef struct AF_DRIVER /* VBE/AF driver structure */ { /* driver header */ char Signature[12]; unsigned long Version __PACKED__; unsigned long DriverRev __PACKED__; char OemVendorName[80]; char OemCopyright[80]; unsigned short *AvailableModes __PACKED__; unsigned long TotalMemory __PACKED__; unsigned long Attributes __PACKED__; unsigned long BankSize __PACKED__; unsigned long BankedBasePtr __PACKED__; unsigned long LinearSize __PACKED__; unsigned long LinearBasePtr __PACKED__; unsigned long LinearGranularity __PACKED__; unsigned short *IOPortsTable __PACKED__; unsigned long IOMemoryBase[4] __PACKED__; unsigned long IOMemoryLen[4] __PACKED__; unsigned long LinearStridePad __PACKED__; unsigned short PCIVendorID __PACKED__; unsigned short PCIDeviceID __PACKED__; unsigned short PCISubSysVendorID __PACKED__; unsigned short PCISubSysID __PACKED__; unsigned long Checksum __PACKED__; unsigned long res2[6] __PACKED__; /* near pointers mapped by the application */ void *IOMemMaps[4] __PACKED__; void *BankedMem __PACKED__; void *LinearMem __PACKED__; unsigned long res3[5] __PACKED__; /* driver state variables */ unsigned long BufferEndX __PACKED__; unsigned long BufferEndY __PACKED__; unsigned long OriginOffset __PACKED__; unsigned long OffscreenOffset __PACKED__; unsigned long OffscreenStartY __PACKED__; unsigned long OffscreenEndY __PACKED__; unsigned long res4[10] __PACKED__; /* relocatable 32 bit bank switch routine, for Windows (ugh!) */ unsigned long SetBank32Len __PACKED__; void *SetBank32 __PACKED__; /* callback functions provided by the application */ void *Int86 __PACKED__; void *CallRealMode __PACKED__; /* main driver setup routine */ void *InitDriver __PACKED__; /* VBE/AF 1.0 asm interface (obsolete and not supported by Allegro) */ void *af10Funcs[40] __PACKED__; /* VBE/AF 2.0 extensions */ void *PlugAndPlayInit __PACKED__; /* FreeBE/AF extension query function */ void *(*OemExt)(DC, unsigned long id); /* extension hook for implementing additional VESA interfaces */ void *SupplementalExt __PACKED__; /* device driver functions */ long (*GetVideoModeInfo)(DC, short mode, AF_MODE_INFO *modeInfo); long (*SetVideoMode)(DC, short mode, long virtualX, long virtualY, long *bytesPerLine, int numBuffers, void *crtc); void (*RestoreTextMode)(DC); long (*GetClosestPixelClock)(DC, short mode, unsigned long pixelClock); void (*SaveRestoreState)(DC, int subfunc, void *saveBuf); void (*SetDisplayStart)(DC, long x, long y, long waitVRT); void (*SetActiveBuffer)(DC, long index); void (*SetVisibleBuffer)(DC, long index, long waitVRT); int (*GetDisplayStartStatus)(DC); void (*EnableStereoMode)(DC, int enable); void (*SetPaletteData)(DC, AF_PALETTE *pal, long num, long index, long waitVRT); void (*SetGammaCorrectData)(DC, AF_PALETTE *pal, long num, long index); void (*SetBank)(DC, long bank); /* hardware cursor functions */ void (*SetCursor)(DC, AF_CURSOR *cursor); void (*SetCursorPos)(DC, long x, long y); void (*SetCursorColor)(DC, unsigned char red, unsigned char green, unsigned char blue); void (*ShowCursor)(DC, long visible); /* 2D rendering functions */ void (*WaitTillIdle)(DC); void (*EnableDirectAccess)(DC); void (*DisableDirectAccess)(DC); void (*SetMix)(DC, long foreMix, long backMix); void (*Set8x8MonoPattern)(DC, unsigned char *pattern); void (*Set8x8ColorPattern)(DC, int index, unsigned long *pattern); void (*Use8x8ColorPattern)(DC, int index); void (*SetLineStipple)(DC, unsigned short stipple); void (*SetLineStippleCount)(DC, unsigned long count); void (*SetClipRect)(DC, long minx, long miny, long maxx, long maxy); void (*DrawScan)(DC, long color, long y, long x1, long x2); void (*DrawPattScan)(DC, long foreColor, long backColor, long y, long x1, long x2); void (*DrawColorPattScan)(DC, long y, long x1, long x2); void (*DrawScanList)(DC, unsigned long color, long y, long length, short *scans); void (*DrawPattScanList)(DC, unsigned long foreColor, unsigned long backColor, long y, long length, short *scans); void (*DrawColorPattScanList)(DC, long y, long length, short *scans); void (*DrawRect)(DC, unsigned long color, long left, long top, long width, long height); void (*DrawPattRect)(DC, unsigned long foreColor, unsigned long backColor, long left, long top, long width, long height); void (*DrawColorPattRect)(DC, long left, long top, long width, long height); void (*DrawLine)(DC, unsigned long color, fixed x1, fixed y1, fixed x2, fixed y2); void (*DrawStippleLine)(DC, unsigned long foreColor, unsigned long backColor, fixed x1, fixed y1, fixed x2, fixed y2); void (*DrawTrap)(DC, unsigned long color, AF_TRAP *trap); void (*DrawTri)(DC, unsigned long color, AF_FIX_POINT *v1, AF_FIX_POINT *v2, AF_FIX_POINT *v3, fixed xOffset, fixed yOffset); void (*DrawQuad)(DC, unsigned long color, AF_FIX_POINT *v1, AF_FIX_POINT *v2, AF_FIX_POINT *v3, AF_FIX_POINT *v4, fixed xOffset, fixed yOffset); void (*PutMonoImage)(DC, long foreColor, long backColor, long dstX, long dstY, long byteWidth, long srcX, long srcY, long width, long height, unsigned char *image); void (*PutMonoImageLin)(DC, long foreColor, long backColor, long dstX, long dstY, long byteWidth, long srcX, long srcY, long width, long height, long imageOfs); void (*PutMonoImageBM)(DC, long foreColor, long backColor, long dstX, long dstY, long byteWidth, long srcX, long srcY, long width, long height, long imagePhysAddr); void (*BitBlt)(DC, long left, long top, long width, long height, long dstLeft, long dstTop, long op); void (*BitBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op); void (*BitBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op); void (*BitBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op); void (*SrcTransBlt)(DC, long left, long top, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*SrcTransBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*SrcTransBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*SrcTransBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*DstTransBlt)(DC, long left, long top, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*DstTransBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*DstTransBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*DstTransBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent); void (*StretchBlt)(DC, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op); void (*StretchBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op); void (*StretchBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op); void (*StretchBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op); void (*SrcTransStretchBlt)(DC, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*SrcTransStretchBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*SrcTransStretchBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*SrcTransStretchBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*DstTransStretchBlt)(DC, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*DstTransStretchBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*DstTransStretchBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); void (*DstTransStretchBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent); /* hardware video functions */ void (*SetVideoInput)(DC, long width, long height, long format); void *(*SetVideoOutput)(DC, long left, long top, long width, long height); void (*StartVideoFrame)(DC); void (*EndVideoFrame)(DC); } AF_DRIVER; #undef DC /* FreeBE/AF API extensions use 32 bit magic numbers */ #define FAF_ID(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d) /* ID code and magic return value for initialising the extensions */ #define FAFEXT_INIT FAF_ID('I','N','I','T') #define FAFEXT_MAGIC FAF_ID('E','X', 0, 0) /* function exporting extensions (needed for Nucleus compatibility) */ #define FAFEXT_LIBC FAF_ID('L','I','B','C') #define FAFEXT_PMODE FAF_ID('P','M','O','D') /* extension providing a hardware-specific way to access video memory */ #define FAFEXT_HWPTR FAF_ID('H','P','T','R') typedef struct FAF_HWPTR { int sel; unsigned long offset; } FAF_HWPTR; typedef struct FAF_HWPTR_DATA { FAF_HWPTR IOMemMaps[4]; FAF_HWPTR BankedMem; FAF_HWPTR LinearMem; } FAF_HWPTR_DATA; #ifdef ALLEGRO_LINUX #include #include /* quick and dirty Linux emulation of the DOS memory mapping routines */ #define _create_linear_mapping(_addr, _base, _len) \ ({ \ (_addr)->base = _base; \ (_addr)->size = _len; \ (_addr)->perms = PROT_READ | PROT_WRITE; \ __al_linux_map_memory(_addr); \ }) #define _remove_linear_mapping(_addr) \ { \ if ((_addr)->data) \ __al_linux_unmap_memory(_addr); \ } #define _create_selector(sel, addr, len) -1 #define _remove_selector(sel) #define MMAP struct MAPPED_MEMORY #define NOMM { 0, 0, 0, 0 } #define MVAL(a) a.data #else /* DOS version */ #define MMAP unsigned long #define NOMM 0 #define MVAL(a) (void *)((a)-__djgpp_base_address) #endif static AF_DRIVER *af_driver = NULL; /* the VBE/AF driver */ void *_accel_driver = NULL; /* externally visible driver pointer */ int _accel_active = FALSE; /* is the accelerator busy? */ void *_accel_set_bank; /* shortcuts to driver functions */ void *_accel_idle; static int in_af_mode = FALSE; /* true if VBE/AF is in use */ static int faf_id = FALSE; /* true if FreeBE/AF detected */ static int faf_ext = 0; /* FreeBE/AF extensions version */ static FAF_HWPTR_DATA *faf_farptr; /* FreeBE/AF farptr data */ static int vbeaf_xscroll = 0; /* current display start address */ static int vbeaf_yscroll = 0; static int vbeaf_fg_mix = 0; /* current hardware mix mode */ static int vbeaf_bg_mix = 0; static int vbeaf_cur_c1 = -1; /* hardware cursor colors */ static int vbeaf_cur_c2 = -1; static BITMAP *vbeaf_cur_bmp = NULL; /* bitmap showing the cursor */ static int vbeaf_cur_x; /* cursor position */ static int vbeaf_cur_y; static int vbeaf_cur_on; static BITMAP *vbeaf_pattern = NULL; /* currently loaded pattern bitmap */ static MMAP af_memmap[4] = { NOMM, NOMM, NOMM, NOMM }; static MMAP af_banked_mem = NOMM; static MMAP af_linear_mem = NOMM; #ifdef ALLEGRO_DOS static int vbeaf_nearptr = FALSE; /* did we enable nearptrs ourselves? */ #endif #ifdef ALLEGRO_LINUX int _vbeaf_selector = 0; /* Linux version of __djgpp_ds_alias */ #endif static int saved_mode; /* state info for console switches */ static int saved_vw; static int saved_vh; static int saved_wret; extern void _af_int86(void), _af_call_rm(void), _af_wrapper(void), _af_wrapper_end(void); #ifdef ALLEGRO_DJGPP /* djgpp wrapper to disable exceptions during critical operations */ #define SAFE_CALL(FUNC) \ { \ int _ds, _es, _ss; \ \ asm volatile ( \ " movw %%ds, %w0 ; " \ " movw %%es, %w1 ; " \ " movw %%ss, %w2 ; " \ " movw %w3, %%ds ; " \ " movw %w3, %%es ; " \ " movw %w3, %%ss ; " \ \ : "=&q" (_ds), \ "=&q" (_es), \ "=&q" (_ss) \ \ : "q" (__djgpp_ds_alias) \ ); \ \ FUNC \ \ asm volatile ( \ "movw %w0, %%ds ; " \ "movw %w1, %%es ; " \ "movw %w2, %%ss ; " \ : \ : "q" (_ds), \ "q" (_es), \ "q" (_ss) \ ); \ } #define SAFISH_CALL(FUNC) FUNC #elif defined ALLEGRO_LINUX /* Linux wrapper to disable console switches during critical operations */ #define SAFE_CALL(FUNC) \ { \ __al_linux_switching_blocked++; \ \ FUNC \ \ __al_linux_release_bitmap(NULL); \ } #define SAFISH_CALL(FUNC) SAFE_CALL(FUNC) #else #define SAFE_CALL(FUNC) FUNC #define SAFISH_CALL(FUNC) FUNC #endif /* bswap: * Toggles the endianess of a 32 bit integer. */ static unsigned long bswap(unsigned long n) { unsigned long a = n & 0xFF; unsigned long b = (n>>8) & 0xFF; unsigned long c = (n>>16) & 0xFF; unsigned long d = (n>>24) & 0xFF; return (a<<24) | (b<<16) | (c<<8) | d; } /* call_vbeaf_asm: * Calls a VBE/AF function using the version 1.0 style asm interface. */ static int call_vbeaf_asm(void *proc) { int ret; proc = (void *)((long)af_driver + (long)proc); #ifdef ALLEGRO_GCC /* use gcc-style inline asm */ asm ( " pushl %%ebx ; " " movl %%ecx, %%ebx ; " " call *%%edx ; " " popl %%ebx ; " : "=&a" (ret) /* return value in eax */ : "c" (af_driver), /* VBE/AF driver in ds:ebx */ "d" (proc) /* function ptr in edx */ : "memory" /* assume everything is clobbered */ ); #elif defined ALLEGRO_WATCOM /* use Watcom-style inline asm */ { int _af(void *func, AF_DRIVER *driver); #pragma aux _af = \ " call esi " \ \ parm [esi] [ebx] \ modify [ecx edx edi] \ value [eax]; ret = _af(proc, af_driver); } #else /* don't know what to do on this compiler */ ret = -1; #endif return ret; } /* vbeaf_no_wait: * Dummy wait-till-idle routine for non-accelerated drivers. */ static void vbeaf_no_wait(void) { } END_OF_STATIC_FUNCTION(vbeaf_no_wait); /* load_vbeaf_driver: * Tries to load the specified VBE/AF driver file, returning TRUE on * success. Allocates memory and reads the driver into it. */ static int load_vbeaf_driver(AL_CONST char *filename) { long size; PACKFILE *f; #ifdef ALLEGRO_LINUX /* on Linux. be paranoid and insist that vbeaf.drv belongs to root */ char tmp[128]; struct stat s; if (stat(uconvert_toascii(filename, tmp), &s) != 0) return 0; if ((s.st_uid != 0) || (s.st_mode & (S_IWGRP | S_IWOTH))) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s must only be writeable by root"), filename); return -1; } size = s.st_size; if (size <= 0) return 0; #else /* simple version for other platforms */ size = file_size_ex(filename); if (size <= 0) return 0; #endif f = pack_fopen(filename, F_READ); if (!f) return 0; af_driver = _accel_driver = _AL_MALLOC(size); if (pack_fread(af_driver, size, f) != size) { _AL_FREE(af_driver); af_driver = _accel_driver = NULL; return 0; } pack_fclose(f); LOCK_DATA(af_driver, size); return 1; } /* initialise_freebeaf_extensions: * Prepares the FreeBE/AF extension functions. */ static void initialise_freebeaf_extensions(void) { typedef unsigned long (*EXT_INIT_FUNC)(AF_DRIVER *af, unsigned long id); EXT_INIT_FUNC ext_init; unsigned long magic; int v1, v2; #ifdef ALLEGRO_DOS void *ptr; #endif /* safety check */ if (!af_driver->OemExt) { faf_ext = 0; return; } /* call the extension init function */ ext_init = (EXT_INIT_FUNC)((long)af_driver + (long)af_driver->OemExt); magic = ext_init(af_driver, FAFEXT_INIT); /* check that it returned a nice magic number */ v1 = (magic>>8)&0xFF; v2 = magic&0xFF; if (((magic&0xFFFF0000) != FAFEXT_MAGIC) || (!uisdigit(v1)) || (!uisdigit(v2))) { faf_ext = 0; return; } faf_ext = (v1-'0')*10 + (v2-'0'); /* export libc and pmode functions if the driver wants them */ #ifdef ALLEGRO_DOS ptr = af_driver->OemExt(af_driver, FAFEXT_LIBC); if (ptr) _fill_vbeaf_libc_exports(ptr); ptr = af_driver->OemExt(af_driver, FAFEXT_PMODE); if (ptr) _fill_vbeaf_pmode_exports(ptr); #endif } /* initialise_vbeaf_driver: * Sets up the DPMI memory mappings required by the VBE/AF driver, * returning zero on success. */ static int initialise_vbeaf_driver(void) { int c; #ifdef ALLEGRO_DJGPP /* query driver for the FreeBE/AF farptr extension */ if (faf_ext > 0) faf_farptr = af_driver->OemExt(af_driver, FAFEXT_HWPTR); else faf_farptr = NULL; #else /* don't use farptr on any other platforms */ faf_farptr = NULL; #endif #ifdef ALLEGRO_DOS if (faf_farptr) { /* use farptr access */ for (c=0; c<4; c++) { faf_farptr->IOMemMaps[c].sel = 0; faf_farptr->IOMemMaps[c].offset = 0; } faf_farptr->BankedMem.sel = 0; faf_farptr->BankedMem.offset = 0; faf_farptr->LinearMem.sel = 0; faf_farptr->LinearMem.offset = 0; vbeaf_nearptr = FALSE; } else { /* enable nearptr access */ if (_crt0_startup_flags & _CRT0_FLAG_NEARPTR) { vbeaf_nearptr = FALSE; } else { if (__djgpp_nearptr_enable() == 0) return -2; vbeaf_nearptr = TRUE; } } #endif /* create mapping for MMIO ports */ for (c=0; c<4; c++) { if (af_driver->IOMemoryBase[c]) { if (_create_linear_mapping(af_memmap+c, af_driver->IOMemoryBase[c], af_driver->IOMemoryLen[c]) != 0) return -1; if (faf_farptr) { /* farptr IO mapping */ if (_create_selector(&faf_farptr->IOMemMaps[c].sel, af_memmap[c], af_driver->IOMemoryLen[c]) != 0) { _remove_linear_mapping(af_memmap+c); return -1; } faf_farptr->IOMemMaps[c].offset = 0; af_driver->IOMemMaps[c] = NULL; } else { /* nearptr IO mapping */ af_driver->IOMemMaps[c] = MVAL(af_memmap[c]); } } } /* create mapping for banked video RAM */ if (af_driver->BankedBasePtr) { if (_create_linear_mapping(&af_banked_mem, af_driver->BankedBasePtr, 0x10000) != 0) return -1; if (faf_farptr) { /* farptr banked vram mapping */ if (_create_selector(&faf_farptr->BankedMem.sel, af_banked_mem, 0x10000) != 0) { _remove_linear_mapping(&af_banked_mem); return -1; } faf_farptr->BankedMem.offset = 0; af_driver->BankedMem = NULL; } else { /* nearptr banked vram mapping */ af_driver->BankedMem = MVAL(af_banked_mem); } } /* create mapping for linear video RAM */ if (af_driver->LinearBasePtr) { if (_create_linear_mapping(&af_linear_mem, af_driver->LinearBasePtr, af_driver->LinearSize*1024) != 0) return -1; if (faf_farptr) { /* farptr linear vram mapping */ if (_create_selector(&faf_farptr->LinearMem.sel, af_linear_mem, af_driver->LinearSize*1024) != 0) { _remove_linear_mapping(&af_linear_mem); return -1; } faf_farptr->LinearMem.offset = 0; af_driver->LinearMem = NULL; } else { /* nearptr linear vram mapping */ af_driver->LinearMem = MVAL(af_linear_mem); } } /* callback functions: why are these needed? ugly, IMHO */ af_driver->Int86 = _af_int86; af_driver->CallRealMode = _af_call_rm; return 0; } /* find_vbeaf_mode: * Tries to find a VBE/AF mode number for the specified screen size. */ static int find_vbeaf_mode(int w, int h, int v_w, int v_h, int color_depth, AF_MODE_INFO *mode_info) { unsigned short *mode; /* search the list of modes */ for (mode = af_driver->AvailableModes; *mode != 0xFFFF; mode++) { /* retrieve the mode information block */ if (af_driver->GetVideoModeInfo(af_driver, *mode, mode_info) == 0) { /* check size and color depth */ if ((mode_info->XResolution == w) && (mode_info->YResolution == h) && (mode_info->BitsPerPixel == color_depth) && (mode_info->MaxScanLineWidth >= v_w)) { /* make sure the mode supports scrolling */ if ((v_w > w) || (v_h > h)) { if (!(mode_info->Attributes & 2)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Hardware scrolling not supported")); return 0; } } /* if it isn't FreeBE/AF, it must be UniVBE, so if we don't * have hardware acceleration we may as well just fail this * call and use VBE 3.0 instead. */ if ((!(mode_info->Attributes & 16)) && (!faf_id)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Hardware acceleration not available")); return 0; } return *mode; } } } ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return 0; } /* set_vbeaf_mode: * Selects a VBE/AF graphics mode. */ static int set_vbeaf_mode(int mode, int w, int h, int v_w, int v_h, int *width, int *scrollable) { long wret = *width; int ret; if (gfx_vbeaf.linear) mode |= 0x4000; /* try to set a large virtual screen */ mode |= 0x1000; *scrollable = TRUE; saved_mode = mode; saved_vw = v_w; saved_vh = v_h; saved_wret = wret; ret = af_driver->SetVideoMode(af_driver, mode, v_w, v_h, &wret, 1, NULL); if ((ret != 0) && (v_w <= w) && (v_h <= h)) { /* if that didn't work, try to set a non-scrolling framebuffer */ mode &= ~0x1000; *scrollable = FALSE; saved_mode = mode; saved_wret = wret; ret = af_driver->SetVideoMode(af_driver, mode, v_w, v_h, &wret, 1, NULL); } *width = wret; return ret; } /* vbeaf_locate_driver: * locates and loads a VBE/AF driver. */ static int vbeaf_locate_driver(void) { static char *possible_filenames[] = { #ifdef ALLEGRO_DOS "c:\\vbeaf.drv", #else "/usr/local/lib/vbeaf.drv", "/usr/lib/vbeaf.drv", "/lib/vbeaf.drv", "/vbeaf.drv", #endif NULL }; char filename[1024], tmp1[1024], tmp2[128]; AL_CONST char *p; int ret, i, attrib; /* look for driver in the config file location */ p = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("vbeaf_driver", tmp2), NULL); if ((p) && (ugetc(p))) { ustrzcpy(filename, sizeof(filename), p); if (ugetc(get_filename(filename)) == 0) { append_filename(filename, filename, uconvert_ascii("vbeaf.drv", tmp1), sizeof(filename)); } else { if (file_exists(filename, FA_DIREC, &attrib)) { if (attrib & FA_DIREC) append_filename(filename, filename, uconvert_ascii("vbeaf.drv", tmp1), sizeof(filename)); } } ret = load_vbeaf_driver(filename); if (ret) goto found_it; } /* look for driver in the same directory as the program */ get_executable_name(tmp1, sizeof(tmp1)); replace_filename(filename, tmp1, uconvert_ascii("vbeaf.drv", tmp2), sizeof(filename)); ret = load_vbeaf_driver(filename); if (ret) goto found_it; /* look for driver in the default location */ for (i=0; possible_filenames[i]; i++) { ret = load_vbeaf_driver(uconvert_ascii(possible_filenames[i], tmp1)); if (ret) goto found_it; } /* check the environment for a location */ p = getenv("VBEAF_PATH"); if (p) { append_filename(filename, uconvert_ascii(p, tmp1), uconvert_ascii("vbeaf.drv", tmp2), sizeof(filename)); ret = load_vbeaf_driver(filename); if (ret) goto found_it; } /* oops, no driver */ ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't find VBEAF.DRV")); ret = FALSE; /* got it! */ found_it: return ret; } /* vbeaf_lowlevel_init: * loads the VBE/AF driver and initializes it. */ static int vbeaf_lowlevel_init(void) { int ret; /* check the driver ID string */ if (strcmp(af_driver->Signature, "VBEAF.DRV") != 0) { vbeaf_exit(NULL); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Bad VBE/AF driver ID string")); return FALSE; } /* check the VBE/AF version number */ if (af_driver->Version < 0x200) { vbeaf_exit(NULL); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Obsolete VBE/AF version (need 2.0 or greater)")); return FALSE; } /* to run on Linux, we need to be God */ #ifdef ALLEGRO_LINUX if (!__al_linux_have_ioperms) { vbeaf_exit(NULL); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("This driver needs root privileges")); return FALSE; } _vbeaf_selector = _default_ds(); #endif /* detect and initialise the FreeBE/AF extensions */ if (strstr(af_driver->OemVendorName, "FreeBE")) { faf_id = TRUE; initialise_freebeaf_extensions(); } else { faf_id = FALSE; faf_ext = 0; } /* special setup for Plug and Play hardware */ if (call_vbeaf_asm(af_driver->PlugAndPlayInit) != 0) { vbeaf_exit(NULL); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE/AF Plug and Play initialisation failed")); return FALSE; } /* deal with all that DPMI memory mapping crap */ ret = initialise_vbeaf_driver(); if (ret != 0) { vbeaf_exit(NULL); if (ret == -2) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE/AF nearptrs not supported on this platform")); else ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't map memory for VBE/AF")); return FALSE; } /* low level driver initialisation */ if (call_vbeaf_asm(af_driver->InitDriver) != 0) { vbeaf_exit(NULL); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE/AF device not present")); return FALSE; } return TRUE; } /* vbeaf_init: * Tries to enter the specified graphics mode, and makes a screen bitmap * for it. */ static BITMAP *vbeaf_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *b; AF_MODE_INFO mode_info; int bpp = BYTES_PER_PIXEL(color_depth); int bytes_per_scanline, width, height; int scrollable, mode; int vseg; int rs, gs, bs; char tmp1[512]; void *vaddr; /* Do not continue if this version of Allegro was built in C-only mode. * The bank switchers assume asm-mode calling conventions, but the * library would try to call them with C calling conventions. */ #ifdef ALLEGRO_NO_ASM return NULL; #endif /* locate and load VBE/AF driver from disk */ if (!vbeaf_locate_driver()) return NULL; LOCK_VARIABLE(af_driver); LOCK_VARIABLE(_accel_driver); LOCK_VARIABLE(_accel_active); LOCK_VARIABLE(_accel_set_bank); LOCK_VARIABLE(_accel_idle); LOCK_VARIABLE(vbeaf_cur_on); LOCK_VARIABLE(vbeaf_cur_x); LOCK_VARIABLE(vbeaf_cur_y); LOCK_FUNCTION(_accel_bank_switch); LOCK_FUNCTION(_accel_bank_stub); LOCK_FUNCTION(_af_wrapper); LOCK_FUNCTION(vbeaf_no_wait); LOCK_FUNCTION(vbeaf_move_mouse); LOCK_FUNCTION(vbeaf_draw_sprite); LOCK_FUNCTION(vbeaf_blit_from_memory); /* init the currently loaded VBE/AF driver */ if (!vbeaf_lowlevel_init()) return NULL; /* bodge to work around bugs in the present (6.51) version of UniVBE */ if ((v_w > w) && (!faf_id)) { vbeaf_exit(NULL); ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("SciTech VBE/AF drivers do not support wide virtual screens")); return NULL; } /* get ourselves a mode number */ mode = find_vbeaf_mode(w, h, v_w, v_h, color_depth, &mode_info); if (mode == 0) { vbeaf_exit(NULL); return NULL; } gfx_vbeaf.vid_mem = af_driver->TotalMemory * 1024; vaddr = NULL; if (mode_info.Attributes & 8) { /* linear framebuffer */ gfx_vbeaf.linear = TRUE; gfx_vbeaf.bank_size = gfx_vbeaf.bank_gran = 0; gfx_vbeaf.vid_phys_base = af_driver->LinearBasePtr; bytes_per_scanline = mode_info.LinBytesPerScanLine; if (faf_farptr) { vaddr = (void *)faf_farptr->LinearMem.offset; vseg = faf_farptr->LinearMem.sel; } else { vaddr = af_driver->LinearMem; vseg = _default_ds(); } } else { /* banked framebuffer */ gfx_vbeaf.linear = FALSE; gfx_vbeaf.bank_size = 65536; gfx_vbeaf.bank_gran = af_driver->BankSize * 1024; gfx_vbeaf.vid_phys_base = af_driver->BankedBasePtr; bytes_per_scanline = mode_info.BytesPerScanLine; if (faf_farptr) { vaddr = (void *)faf_farptr->BankedMem.offset; vseg = faf_farptr->BankedMem.sel; } else { vaddr = af_driver->BankedMem; vseg = _default_ds(); } } width = MAX(bytes_per_scanline, v_w*bpp); height = MAX(h, v_h); _sort_out_virtual_width(&width, &gfx_vbeaf); if (width * height > gfx_vbeaf.vid_mem) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Insufficient video memory")); vbeaf_exit(NULL); return NULL; } /* set the mode */ if (set_vbeaf_mode(mode, w, h, width/bpp, height, &width, &scrollable) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed to set VBE/AF mode")); vbeaf_exit(NULL); return NULL; } in_af_mode = TRUE; _accel_active = FALSE; if (scrollable) height = MAX(height, (int)af_driver->OffscreenEndY+1); if ((width/bpp < v_w) || (width/bpp < w) || (height < v_h) || (height < h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen size too large")); vbeaf_exit(NULL); return NULL; } /* construct the screen bitmap */ b = _make_bitmap(width/bpp, height, (unsigned long)vaddr, &gfx_vbeaf, color_depth, width); if (!b) { vbeaf_exit(NULL); return NULL; } b->seg = vseg; /* set up the /AF driver state */ af_driver->SetActiveBuffer(af_driver, 0); af_driver->SetVisibleBuffer(af_driver, 0, 0); if (af_driver->EnableDirectAccess) af_driver->EnableDirectAccess(af_driver); if (af_driver->SetClipRect) af_driver->SetClipRect(af_driver, 0, 0, b->w-1, b->h-1); _accel_set_bank = af_driver->SetBank; if (af_driver->EnableDirectAccess) _accel_idle = af_driver->EnableDirectAccess; else if (af_driver->WaitTillIdle) _accel_idle = af_driver->WaitTillIdle; else _accel_idle = vbeaf_no_wait; if (gfx_vbeaf.linear) { if (_accel_idle == vbeaf_no_wait) b->write_bank = b->read_bank = _stub_bank_switch; else b->write_bank = b->read_bank = _accel_bank_stub; } else { b->write_bank = b->read_bank = _accel_bank_switch; b->id |= BMP_ID_NOBLIT; } vbeaf_xscroll = vbeaf_yscroll = 0; gfx_vbeaf.w = b->cr = w; gfx_vbeaf.h = b->cb = h; /* set up the truecolor pixel format */ #if (defined ALLEGRO_COLOR16) || (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) if (gfx_vbeaf.linear) { rs = mode_info.LinRedFieldPosition; gs = mode_info.LinGreenFieldPosition; bs = mode_info.LinBlueFieldPosition; } else { rs = mode_info.RedFieldPosition; gs = mode_info.GreenFieldPosition; bs = mode_info.BlueFieldPosition; } switch (color_depth) { #ifdef ALLEGRO_COLOR16 case 15: _rgb_r_shift_15 = rs; _rgb_g_shift_15 = gs; _rgb_b_shift_15 = bs; break; case 16: _rgb_r_shift_16 = rs; _rgb_g_shift_16 = gs; _rgb_b_shift_16 = bs; break; #endif #ifdef ALLEGRO_COLOR24 case 24: _rgb_r_shift_24 = rs; _rgb_g_shift_24 = gs; _rgb_b_shift_24 = bs; break; #endif #ifdef ALLEGRO_COLOR32 case 32: _rgb_r_shift_32 = rs; _rgb_g_shift_32 = gs; _rgb_b_shift_32 = bs; break; #endif } #endif orig_vline = _screen_vtable.vline; orig_hline = _screen_vtable.hline; orig_line = _screen_vtable.line; orig_rectfill = _screen_vtable.rectfill; orig_draw_glyph = _screen_vtable.draw_glyph; orig_draw_sprite = _screen_vtable.draw_sprite; orig_masked_blit = _screen_vtable.masked_blit; /* is triple buffering supported? */ if (mode_info.Attributes & 2048) { gfx_vbeaf.request_scroll = vbeaf_request_scroll; gfx_vbeaf.poll_scroll = vbeaf_poll_scroll; } else { gfx_vbeaf.request_scroll = NULL; gfx_vbeaf.poll_scroll = NULL; } /* are hardware cursors supported? */ if ((mode_info.Attributes & 64) && (af_driver->SetCursor)) { gfx_vbeaf.set_mouse_sprite = vbeaf_set_mouse_sprite; gfx_vbeaf.show_mouse = vbeaf_show_mouse; gfx_vbeaf.hide_mouse = vbeaf_hide_mouse; gfx_vbeaf.move_mouse = vbeaf_move_mouse; } else { gfx_vbeaf.set_mouse_sprite = NULL; gfx_vbeaf.show_mouse = NULL; gfx_vbeaf.hide_mouse = NULL; gfx_vbeaf.move_mouse = NULL; } /* accelerated scanline fills? */ if (af_driver->DrawScan) gfx_capabilities |= (GFX_HW_HLINE | GFX_HW_HLINE_XOR); if (af_driver->DrawPattScan) gfx_capabilities |= GFX_HW_HLINE_SOLID_PATTERN; if (af_driver->DrawColorPattScan) gfx_capabilities |= GFX_HW_HLINE_COPY_PATTERN; /* accelerated line drawing? */ if (af_driver->DrawLine) gfx_capabilities |= (GFX_HW_LINE | GFX_HW_LINE_XOR); /* accelerated rectangle fills? */ if (af_driver->DrawRect) { _screen_vtable.clear_to_color = vbeaf_clear_to_color; gfx_capabilities |= (GFX_HW_FILL | GFX_HW_FILL_XOR); } if (af_driver->DrawPattRect) gfx_capabilities |= GFX_HW_FILL_SOLID_PATTERN; if (af_driver->DrawColorPattRect) gfx_capabilities |= GFX_HW_FILL_COPY_PATTERN; /* accelerated triangle drawing? */ if (af_driver->DrawTrap) gfx_capabilities |= (GFX_HW_TRIANGLE | GFX_HW_TRIANGLE_XOR); /* accelerated monochrome text output? */ if (af_driver->PutMonoImage) { _screen_vtable.draw_glyph = vbeaf_draw_glyph; gfx_capabilities |= GFX_HW_GLYPH; } /* accelerated video memory blits? */ if (af_driver->BitBlt) { _screen_vtable.blit_to_self = vbeaf_blit_to_self; _screen_vtable.blit_to_self_forward = vbeaf_blit_to_self; _screen_vtable.blit_to_self_backward = vbeaf_blit_to_self; gfx_capabilities |= GFX_HW_VRAM_BLIT; } /* accelerated blits from system memory? */ if (af_driver->BitBltSys) { _screen_vtable.blit_from_memory = vbeaf_blit_from_memory; _screen_vtable.blit_from_system = vbeaf_blit_from_memory; gfx_capabilities |= GFX_HW_MEM_BLIT; } /* accelerated masked blits? */ if ((af_driver->SrcTransBlt) || (af_driver->SrcTransBltSys)) { _screen_vtable.masked_blit = vbeaf_masked_blit; _screen_vtable.draw_sprite = vbeaf_draw_sprite; if (_screen_vtable.draw_256_sprite == orig_draw_sprite) _screen_vtable.draw_256_sprite = vbeaf_draw_sprite; if (af_driver->SrcTransBlt) gfx_capabilities |= GFX_HW_VRAM_BLIT_MASKED; if (af_driver->SrcTransBltSys) gfx_capabilities |= GFX_HW_MEM_BLIT_MASKED; } /* set up the VBE/AF description string */ ustrzcpy(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(af_driver->OemVendorName, tmp1)); if (gfx_vbeaf.linear) ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", linear", tmp1)); else ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", banked", tmp1)); if (faf_ext > 0) uszprintf(vbeaf_desc+ustrsize(vbeaf_desc), sizeof(vbeaf_desc) - ustrsize(vbeaf_desc), uconvert_ascii(", FreeBE ex%02d", tmp1), faf_ext); else if (faf_id) ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", FreeBE noex", tmp1)); if (faf_farptr) ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", farptr", tmp1)); /* is this an accelerated or dumb framebuffer mode? */ if (mode_info.Attributes & 16) { gfx_vbeaf.drawing_mode = vbeaf_drawing_mode; vbeaf_drawing_mode(); ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", accel", tmp1)); } else { gfx_vbeaf.drawing_mode = NULL; ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", noaccel", tmp1)); } gfx_vbeaf.desc = vbeaf_desc; #ifdef ALLEGRO_LINUX __al_linux_console_graphics(); b->vtable->acquire = __al_linux_acquire_bitmap; b->vtable->release = __al_linux_release_bitmap; #endif return b; } /* vbeaf_exit: * Shuts down the VBE/AF driver. */ static void vbeaf_exit(BITMAP *b) { int c; /* shut down the driver */ if (in_af_mode) { if (af_driver->EnableDirectAccess) af_driver->EnableDirectAccess(af_driver); else if (af_driver->WaitTillIdle) af_driver->WaitTillIdle(af_driver); af_driver->RestoreTextMode(af_driver); in_af_mode = FALSE; } /* undo memory mappings */ if (faf_farptr) { for (c=0; c<4; c++) _remove_selector(&faf_farptr->IOMemMaps[c].sel); _remove_selector(&faf_farptr->BankedMem.sel); _remove_selector(&faf_farptr->LinearMem.sel); } for (c=0; c<4; c++) _remove_linear_mapping(af_memmap+c); _remove_linear_mapping(&af_banked_mem); _remove_linear_mapping(&af_linear_mem); if (af_driver) { _AL_FREE(af_driver); af_driver = _accel_driver = NULL; } #ifdef ALLEGRO_DOS if (vbeaf_nearptr) { __djgpp_nearptr_disable(); vbeaf_nearptr = FALSE; } #endif #ifdef ALLEGRO_LINUX __al_linux_console_text(); #endif } /* vbeaf_save: * Saves the graphics state. */ static void vbeaf_save(void) { if (af_driver->EnableDirectAccess) af_driver->EnableDirectAccess(af_driver); else if (af_driver->WaitTillIdle) af_driver->WaitTillIdle(af_driver); af_driver->RestoreTextMode(af_driver); in_af_mode = FALSE; } /* vbeaf_restore: * Restores the graphics state. */ static void vbeaf_restore(void) { long wret = saved_wret; af_driver->SetVideoMode(af_driver, saved_mode, saved_vw, saved_vh, &wret, 1, NULL); af_driver->SetActiveBuffer(af_driver, 0); af_driver->SetVisibleBuffer(af_driver, 0, 0); if (af_driver->EnableDirectAccess) af_driver->EnableDirectAccess(af_driver); if (af_driver->SetClipRect) af_driver->SetClipRect(af_driver, 0, 0, SCREEN_W-1, SCREEN_H-1); if (gfx_vbeaf.drawing_mode) gfx_vbeaf.drawing_mode(); vbeaf_scroll(vbeaf_xscroll, vbeaf_yscroll); in_af_mode = TRUE; } /* vbeaf_fetch_mode_list: * Attempts to create a list of valid video modes for the VBE/AF driver. * Returns the mode list on success or NULL on failure. */ static GFX_MODE_LIST *vbeaf_fetch_mode_list(void) { GFX_MODE_LIST *gfx_mode_list; AF_MODE_INFO *mode_info; unsigned short *mode; int vbeaf_was_off; mode_info = _AL_MALLOC(sizeof(AF_MODE_INFO)); if (!mode_info) return NULL; /* make sure VBE/AF interface is enabled! */ if (!af_driver) { if (!vbeaf_locate_driver()) { if (mode_info) _AL_FREE(mode_info); return NULL; } if (!vbeaf_lowlevel_init()) { if (mode_info) _AL_FREE(mode_info); return NULL; } vbeaf_was_off = TRUE; } else vbeaf_was_off = FALSE; /* start building mode-list */ gfx_mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST)); if (!gfx_mode_list) { if (mode_info) _AL_FREE(mode_info); return NULL; } gfx_mode_list->mode = NULL; gfx_mode_list->num_modes = 0; /* create mode list */ for (mode = af_driver->AvailableModes; *mode != 0xFFFF; mode++) { gfx_mode_list->mode = _al_sane_realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1)); if (!gfx_mode_list->mode) { if (mode_info) _AL_FREE(mode_info); if (gfx_mode_list) _AL_FREE(gfx_mode_list); return NULL; } if (af_driver->GetVideoModeInfo(af_driver, *mode, mode_info) != 0) { if (mode_info) _AL_FREE(mode_info); if (gfx_mode_list->mode) _AL_FREE(gfx_mode_list->mode); if (gfx_mode_list) _AL_FREE(gfx_mode_list); return NULL; } gfx_mode_list->mode[gfx_mode_list->num_modes].width = mode_info->XResolution; gfx_mode_list->mode[gfx_mode_list->num_modes].height = mode_info->YResolution; gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = mode_info->BitsPerPixel; gfx_mode_list->num_modes++; } /* terminate mode list */ gfx_mode_list->mode = _al_sane_realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1)); if (!gfx_mode_list->mode) { if (mode_info) _AL_FREE(mode_info); if (gfx_mode_list) _AL_FREE(gfx_mode_list); return NULL; } gfx_mode_list->mode[gfx_mode_list->num_modes].width = 0; gfx_mode_list->mode[gfx_mode_list->num_modes].height = 0; gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = 0; /* shut down VBE/AF interface if it wasn't previously loaded */ if (vbeaf_was_off) vbeaf_exit(NULL); if (mode_info) _AL_FREE(mode_info); return gfx_mode_list; } /* vbeaf_vsync: * VBE/AF vsync routine, needed for cards that don't emulate the VGA * blanking registers. VBE/AF doesn't provide a vsync function, but we * can emulate it by altering the display start address with the vsync * flag set. */ static void vbeaf_vsync(void) { vbeaf_scroll(vbeaf_xscroll, vbeaf_yscroll); } /* vbeaf_scroll: * Hardware scrolling routine. */ static int vbeaf_scroll(int x, int y) { int moved = (vbeaf_xscroll != x) || (vbeaf_yscroll != y); vbeaf_xscroll = x; vbeaf_yscroll = y; SAFISH_CALL( if (_wait_for_vsync && af_driver->WaitTillIdle) af_driver->WaitTillIdle(af_driver); af_driver->SetDisplayStart(af_driver, x, y, 1); ); if ((vbeaf_cur_bmp) && (moved)) vbeaf_move_mouse(vbeaf_cur_x, vbeaf_cur_y); return 0; } /* vbeaf_set_palette_range: * Uses VBE/AF functions to set the palette. */ static void vbeaf_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync) { AF_PALETTE tmp[256]; int c; for (c=from; c<=to; c++) { tmp[c-from].red = p[c].r << 2; tmp[c-from].green = p[c].g << 2; tmp[c-from].blue = p[c].b << 2; tmp[c-from].alpha = 0; } SAFISH_CALL( af_driver->SetPaletteData(af_driver, tmp, to-from+1, from, (vsync ? 1 : 0)); ); } /* vbeaf_request_scroll: * Triple buffering initiate routine. */ static int vbeaf_request_scroll(int x, int y) { vbeaf_xscroll = x; vbeaf_yscroll = y; SAFISH_CALL( if (af_driver->WaitTillIdle) af_driver->WaitTillIdle(af_driver); af_driver->SetDisplayStart(af_driver, x, y, 0); ); if (vbeaf_cur_bmp) vbeaf_move_mouse(vbeaf_cur_x, vbeaf_cur_y); return 0; } /* vbeaf_poll_scroll: * Triple buffering test routine. */ static int vbeaf_poll_scroll(void) { int ret; SAFISH_CALL( ret = af_driver->GetDisplayStartStatus(af_driver); ); return (ret) ? FALSE : TRUE; } /* vbeaf_set_mouse_sprite: * Attempts to download a new hardware cursor graphic, returning zero on * success or non-zero if this image is unsuitable. */ static int vbeaf_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus) { AF_CURSOR cursor; int bpp = bitmap_color_depth(sprite); int c, x, y; int iszero; /* hardware cursors cannot be larger than 32x32 */ if ((sprite->w > 32) || (sprite->h > 32)) return -1; /* clear the cursor data */ for (c=0; c<32; c++) { cursor.andMask[c] = 0; cursor.xorMask[c] = 0; } vbeaf_cur_c1 = -1; vbeaf_cur_c2 = -1; /* scan through the pointer image */ for (y=0; yh; y++) { for (x=0; xw; x++) { c = getpixel(sprite, x, y); if (c == bitmap_mask_color(sprite)) { /* skip masked pixels */ } else if (c == vbeaf_cur_c1) { /* color #1 pixel */ cursor.andMask[y] |= 0x80000000>>x; cursor.xorMask[y] |= 0x80000000>>x; } else if (c == vbeaf_cur_c2) { /* color #2 pixel */ cursor.andMask[y] |= 0x80000000>>x; } else { /* check whether this pixel value is zero */ if (bpp == 8) { iszero = ((getr_depth(bpp, c) == getr_depth(bpp, 0)) && (getg_depth(bpp, c) == getg_depth(bpp, 0)) && (getb_depth(bpp, c) == getb_depth(bpp, 0))); } else { iszero = ((getr_depth(bpp, c) == 0) && (getg_depth(bpp, c) == 0) && (getb_depth(bpp, c) == 0)); } if ((vbeaf_cur_c2 < 0) && (iszero)) { /* zero pixel value = color #2 */ vbeaf_cur_c2 = c; cursor.andMask[y] |= 0x80000000>>x; } else if (vbeaf_cur_c1 < 0) { /* other pixel value = color #1 */ vbeaf_cur_c1 = c; cursor.andMask[y] |= 0x80000000>>x; cursor.xorMask[y] |= 0x80000000>>x; } else { /* it's not cool if there are more than two colors! */ return -1; } } } } /* flip the endianess */ for (c=0; c<32; c++) { cursor.andMask[c] = bswap(cursor.andMask[c]); cursor.xorMask[c] = bswap(cursor.xorMask[c]); } cursor.hotx = xfocus; cursor.hoty = yfocus; /* download to the hardware */ SAFISH_CALL( af_driver->SetCursor(af_driver, &cursor); if ((bpp > 8) && (vbeaf_cur_c1 >= 0)) { af_driver->SetCursorColor(af_driver, getr_depth(bpp, vbeaf_cur_c1), getg_depth(bpp, vbeaf_cur_c1), getb_depth(bpp, vbeaf_cur_c1)); } ); return 0; } /* vbeaf_show_mouse: * Turns on the hardware cursor, returning zero on success. */ static int vbeaf_show_mouse(BITMAP *bmp, int x, int y) { if (bitmap_color_depth(bmp) == 8) { if (vbeaf_cur_c2 >= 0) { /* check that the palette contains a valid zero color */ if ((getr_depth(8, vbeaf_cur_c2) != getr_depth(8, 0)) || (getg_depth(8, vbeaf_cur_c2) != getg_depth(8, 0)) || (getb_depth(8, vbeaf_cur_c2) != getb_depth(8, 0))) return -1; } /* set the cursor color */ if (vbeaf_cur_c1 >= 0) { SAFISH_CALL( af_driver->SetCursorColor(af_driver, vbeaf_cur_c1, 0, 0); ); } } vbeaf_cur_bmp = bmp; vbeaf_cur_on = FALSE; vbeaf_move_mouse(x, y); return 0; } /* vbeaf_hide_mouse: * Gets rid of the hardware cursor. */ static void vbeaf_hide_mouse(void) { SAFISH_CALL( af_driver->ShowCursor(af_driver, 0); ); vbeaf_cur_bmp = NULL; vbeaf_cur_on = FALSE; } /* vbeaf_move_mouse: * Sets the hardware cursor position. */ static void vbeaf_move_mouse(int x, int y) { int hx, hy; int onscreen; hx = x + vbeaf_cur_bmp->x_ofs - vbeaf_xscroll; hy = y + vbeaf_cur_bmp->y_ofs - vbeaf_yscroll; onscreen = (hx >= 0) && (hx < SCREEN_W) && (hy >= 0) && (hy < SCREEN_H); SAFISH_CALL( if (onscreen) { af_driver->SetCursorPos(af_driver, hx, hy); if (!vbeaf_cur_on) { af_driver->ShowCursor(af_driver, 1); vbeaf_cur_on = TRUE; } } else { if (vbeaf_cur_on) { af_driver->ShowCursor(af_driver, 0); vbeaf_cur_on = FALSE; } } ); vbeaf_cur_x = x; vbeaf_cur_y = y; } END_OF_STATIC_FUNCTION(vbeaf_move_mouse); /* vbeaf_drawing_mode: * Hook to tell us that the drawing mode has been changed, so we may need * to alter some of our vtable entries. */ static void vbeaf_drawing_mode(void) { vbeaf_pattern = NULL; if ((_drawing_mode == DRAW_MODE_SOLID) || (_drawing_mode == DRAW_MODE_XOR)) { /* easy, everything supports solid and XOR drawing */ _screen_vtable.hline = (af_driver->DrawScan) ? vbeaf_hline : orig_hline; _screen_vtable.vline = (af_driver->DrawLine) ? vbeaf_vline_a : ((af_driver->DrawRect) ? vbeaf_vline_b : orig_vline); _screen_vtable.line = (af_driver->DrawLine) ? vbeaf_line : orig_line; _screen_vtable.rectfill = (af_driver->DrawRect) ? vbeaf_rectfill : orig_rectfill; _screen_vtable.triangle = (af_driver->DrawTrap) ? vbeaf_triangle : NULL; vbeaf_fg_mix = vbeaf_bg_mix = (_drawing_mode == DRAW_MODE_XOR) ? 3 : 0; SAFISH_CALL( af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix); ); return; } if ((_drawing_mode == DRAW_MODE_COPY_PATTERN) && (_drawing_pattern->w <= 8) && (_drawing_pattern->h <= 8)) { /* color patterns can be done in hardware if they are small enough */ _screen_vtable.hline = (af_driver->DrawColorPattScan) ? vbeaf_hline : orig_hline; _screen_vtable.vline = (af_driver->DrawColorPattRect) ? vbeaf_vline_b : orig_vline; _screen_vtable.line = orig_line; _screen_vtable.rectfill = (af_driver->DrawColorPattRect) ? vbeaf_rectfill : orig_rectfill; _screen_vtable.triangle = NULL; vbeaf_fg_mix = vbeaf_bg_mix = 0; SAFISH_CALL( af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix); ); return; } if (((_drawing_mode == DRAW_MODE_SOLID_PATTERN) || (_drawing_mode == DRAW_MODE_MASKED_PATTERN)) && (_drawing_pattern->w <= 8) && (_drawing_pattern->h <= 8)) { /* mono patterns can be done in hardware if they are small enough */ _screen_vtable.hline = (af_driver->DrawPattScan) ? vbeaf_hline : orig_hline; _screen_vtable.vline = (af_driver->DrawPattRect) ? vbeaf_vline_b : orig_vline; _screen_vtable.line = orig_line; _screen_vtable.rectfill = (af_driver->DrawPattRect) ? vbeaf_rectfill : orig_rectfill; _screen_vtable.triangle = NULL; vbeaf_fg_mix = 0; vbeaf_bg_mix = (_drawing_mode == DRAW_MODE_MASKED_PATTERN) ? 4 : 0; SAFISH_CALL( af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix); ); return; } /* urgh, have to use software drawing functions for this mode */ _screen_vtable.vline = orig_vline; _screen_vtable.hline = orig_hline; _screen_vtable.line = orig_line; _screen_vtable.rectfill = orig_rectfill; _screen_vtable.triangle = NULL; vbeaf_fg_mix = vbeaf_bg_mix = 0; SAFISH_CALL( af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix); ); } /* prepare_color_pattern: * Sets up the hardware ready for a colored pattern drawing operation. */ static void prepare_color_pattern(BITMAP *bmp) { static unsigned long pattern[64]; int x, y, xx, yy, xo, yo; if (vbeaf_pattern != bmp) { xo = _drawing_x_anchor + bmp->x_ofs; yo = _drawing_y_anchor + bmp->y_ofs; switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR8 case 8: for (y=0; y<8; y++) { for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; pattern[y*8+x] = _drawing_pattern->line[yy][xx]; } } break; #endif #ifdef ALLEGRO_COLOR16 case 15: case 16: for (y=0; y<8; y++) { for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; pattern[y*8+x] = ((unsigned short *)_drawing_pattern->line[yy])[xx]; } } break; #endif #ifdef ALLEGRO_COLOR24 case 24: for (y=0; y<8; y++) { for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; pattern[y*8+x] = *((unsigned long *)(_drawing_pattern->line[yy]+xx*3)) & 0xFFFFFF; } } break; #endif #ifdef ALLEGRO_COLOR32 case 32: for (y=0; y<8; y++) { for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; pattern[y*8+x] = ((unsigned long *)_drawing_pattern->line[yy])[xx]; } } break; #endif } af_driver->Set8x8ColorPattern(af_driver, 0, pattern); af_driver->Use8x8ColorPattern(af_driver, 0); vbeaf_pattern = bmp; } } /* prepare_mono_pattern: * Sets up the hardware ready for a mono pattern drawing operation. */ static void prepare_mono_pattern(BITMAP *bmp) { static unsigned char pattern[8]; int x, y, xx, yy, xo, yo; if (vbeaf_pattern != bmp) { xo = _drawing_x_anchor + bmp->x_ofs; yo = _drawing_y_anchor + bmp->y_ofs; switch (bitmap_color_depth(bmp)) { #ifdef ALLEGRO_COLOR16 case 8: for (y=0; y<8; y++) { pattern[y] = 0; for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; if (_drawing_pattern->line[yy][xx]) pattern[y] |= (0x80>>x); } } break; #endif #ifdef ALLEGRO_COLOR16 case 15: case 16: for (y=0; y<8; y++) { pattern[y] = 0; for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; if (((unsigned short *)_drawing_pattern->line[yy])[xx] != bitmap_mask_color(bmp)) pattern[y] |= (0x80>>x); } } break; #endif #ifdef ALLEGRO_COLOR24 case 24: for (y=0; y<8; y++) { pattern[y] = 0; for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; if ((*((unsigned long *)(_drawing_pattern->line[yy]+xx*3)) & 0xFFFFFF) != MASK_COLOR_24) pattern[y] |= (0x80>>x); } } break; #endif #ifdef ALLEGRO_COLOR32 case 32: for (y=0; y<8; y++) { pattern[y] = 0; for (x=0; x<8; x++) { xx = (x-xo) & _drawing_x_mask; yy = (y-yo) & _drawing_y_mask; if (((unsigned long *)_drawing_pattern->line[yy])[xx] != MASK_COLOR_32) pattern[y] |= (0x80>>x); } } break; #endif } af_driver->Set8x8MonoPattern(af_driver, pattern); vbeaf_pattern = bmp; } } /* go_accel: * Prepares the hardware for an accelerated drawing operation. */ static INLINE void go_accel(void) { /* turn on the accelerator */ if (!_accel_active) { if (af_driver->DisableDirectAccess) af_driver->DisableDirectAccess(af_driver); _accel_active = TRUE; } } /* vbeaf_hline: * Accelerated scanline filling routine. */ static void vbeaf_hline(BITMAP *bmp, int x1, int y, int x2, int color) { if (x1 > x2) { int tmp = x1; x1 = x2; x2 = tmp; } if (bmp->clip) { if ((y < bmp->ct) || (y >= bmp->cb)) return; if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; } SAFISH_CALL( go_accel(); switch (_drawing_mode) { case DRAW_MODE_SOLID: case DRAW_MODE_XOR: /* normal scanline fill */ af_driver->DrawScan(af_driver, color, y+bmp->y_ofs, x1+bmp->x_ofs, x2+bmp->x_ofs+1); break; case DRAW_MODE_COPY_PATTERN: /* colored pattern scanline fill */ prepare_color_pattern(bmp); af_driver->DrawColorPattScan(af_driver, y+bmp->y_ofs, x1+bmp->x_ofs, x2+bmp->x_ofs+1); break; case DRAW_MODE_SOLID_PATTERN: case DRAW_MODE_MASKED_PATTERN: /* mono pattern scanline fill */ prepare_mono_pattern(bmp); af_driver->DrawPattScan(af_driver, color, 0, y+bmp->y_ofs, x1+bmp->x_ofs, x2+bmp->x_ofs+1); break; } ); } /* vbeaf_vline_a: * Accelerated vertical line drawer, using the VBE/AF line primitive. */ static void vbeaf_vline_a(BITMAP *bmp, int x, int y1, int y2, int color) { if (y1 > y2) { int tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if ((x < bmp->cl) || (x >= bmp->cr)) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } SAFISH_CALL( go_accel(); af_driver->DrawLine(af_driver, color, itofix(x+bmp->x_ofs), itofix(y1+bmp->y_ofs), itofix(x+bmp->x_ofs), itofix(y2+bmp->y_ofs)); ); } /* vbeaf_vline_b: * Accelerated vertical line drawer, using the VBE/AF rectangle primitive. */ static void vbeaf_vline_b(BITMAP *bmp, int x, int y1, int y2, int color) { if (y1 > y2) { int tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if ((x < bmp->cl) || (x >= bmp->cr)) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } SAFISH_CALL( go_accel(); switch (_drawing_mode) { case DRAW_MODE_SOLID: case DRAW_MODE_XOR: /* mono vertical line */ af_driver->DrawRect(af_driver, color, x+bmp->x_ofs, y1+bmp->y_ofs, 1, y2-y1+1); break; case DRAW_MODE_COPY_PATTERN: /* colored pattern vertical line */ prepare_color_pattern(bmp); af_driver->DrawColorPattRect(af_driver, x+bmp->x_ofs, y1+bmp->y_ofs, 1, y2-y1+1); break; case DRAW_MODE_SOLID_PATTERN: case DRAW_MODE_MASKED_PATTERN: /* mono pattern vertical line */ prepare_mono_pattern(bmp); af_driver->DrawPattRect(af_driver, color, 0, x+bmp->x_ofs, y1+bmp->y_ofs, 1, y2-y1+1); break; } ); } /* vbeaf_line: * Accelerated line drawer. */ static void vbeaf_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { int sx, sy, dx, dy, t; if (bmp->clip) { sx = x1; sy = y1; dx = x2; dy = y2; if (sx > dx) { t = sx; sx = dx; dx = t; } if (sy > dy) { t = sy; sy = dy; dy = t; } if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct)) return; if ((sx < bmp->cl) || (sy < bmp->ct) || (dx >= bmp->cr) || (dy >= bmp->cb)) { orig_line(bmp, x1, y1, x2, y2, color); return; } } SAFISH_CALL( go_accel(); af_driver->DrawLine(af_driver, color, itofix(x1+bmp->x_ofs), itofix(y1+bmp->y_ofs), itofix(x2+bmp->x_ofs), itofix(y2+bmp->y_ofs)); ); } /* vbeaf_rectfill: * Accelerated rectangle filling routine. */ static void vbeaf_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { if (x2 < x1) { int tmp = x1; x1 = x2; x2 = tmp; } if (y2 < y1) { int tmp = y1; y1 = y2; y2 = tmp; } if (bmp->clip) { if (x1 < bmp->cl) x1 = bmp->cl; if (x2 >= bmp->cr) x2 = bmp->cr-1; if (x2 < x1) return; if (y1 < bmp->ct) y1 = bmp->ct; if (y2 >= bmp->cb) y2 = bmp->cb-1; if (y2 < y1) return; } SAFISH_CALL( go_accel(); switch (_drawing_mode) { case DRAW_MODE_SOLID: case DRAW_MODE_XOR: /* mono rectangle fill */ af_driver->DrawRect(af_driver, color, x1+bmp->x_ofs, y1+bmp->y_ofs, x2-x1+1, y2-y1+1); break; case DRAW_MODE_COPY_PATTERN: /* colored pattern rectangle fill */ prepare_color_pattern(bmp); af_driver->DrawColorPattRect(af_driver, x1+bmp->x_ofs, y1+bmp->y_ofs, x2-x1+1, y2-y1+1); break; case DRAW_MODE_SOLID_PATTERN: case DRAW_MODE_MASKED_PATTERN: /* mono pattern rectangle fill */ prepare_mono_pattern(bmp); af_driver->DrawPattRect(af_driver, color, 0, x1+bmp->x_ofs, y1+bmp->y_ofs, x2-x1+1, y2-y1+1); break; } ); } /* vbeaf_triangle: * Hardware accelerated triangle drawing function. */ static void vbeaf_triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) { AF_TRAP trap; /* bounding box test */ if (bmp->clip) { if ((x1 < bmp->cl) || (x2 < bmp->cl) || (x3 < bmp->cl)) { _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color); return; } if ((y1 < bmp->ct) || (y2 < bmp->ct) || (y3 < bmp->ct)) { _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color); return; } if ((x1 >= bmp->cr) || (x2 >= bmp->cr) || (x3 >= bmp->cr)) { _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color); return; } if ((y1 >= bmp->cb) || (y2 >= bmp->cb) || (y3 >= bmp->cb)) { _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color); return; } } /* sort along the vertical axis */ #define TRI_SWAP(a, b) \ { \ int tmp = x##a; \ x##a = x##b; \ x##b = tmp; \ \ tmp = y##a; \ y##a = y##b; \ y##b = tmp; \ } if (y2 < y1) TRI_SWAP(1, 2); if (y3 < y1) { TRI_SWAP(1, 3); TRI_SWAP(2, 3); } else if (y3 < y2) TRI_SWAP(2, 3); SAFISH_CALL( go_accel(); if (y2 > y1) { /* draw the top half of the triangle as one trapezoid */ trap.y = y1+bmp->y_ofs; trap.count = y2-y1; trap.x1 = trap.x2 = itofix(x1+bmp->x_ofs); trap.slope1 = itofix(x2-x1) / (y2-y1); trap.slope2 = itofix(x3-x1) / (y3-y1); if (trap.slope1 < 0) trap.x1 += MIN(trap.slope1+itofix(1), 0); if (trap.slope2 < 0) trap.x2 += MIN(trap.slope2+itofix(1), 0); if (trap.slope1 > trap.slope2) trap.x1 += MAX(ABS(trap.slope1), itofix(1)); else trap.x2 += MAX(ABS(trap.slope2), itofix(1)); af_driver->DrawTrap(af_driver, color, &trap); if (y3 > y2) { /* draw the bottom half as a second trapezoid */ if (trap.slope1 < 0) trap.x1 -= MIN(trap.slope1+itofix(1), 0); if (trap.slope1 > trap.slope2) trap.x1 -= MAX(ABS(trap.slope1), itofix(1)); trap.count = y3-y2; trap.slope1 = itofix(x3-x2) / (y3-y2); if (trap.slope1 < 0) trap.x1 += MIN(trap.slope1+itofix(1), 0); if (trap.x1 > trap.x2) trap.x1 += MAX(ABS(trap.slope1), itofix(1)); af_driver->DrawTrap(af_driver, color, &trap); } } else if (y3 > y2) { /* we can draw the entire thing with a single trapezoid */ trap.y = y1+bmp->y_ofs; trap.count = y3-y2; trap.x1 = itofix(x2+bmp->x_ofs); trap.x2 = itofix(x1+bmp->x_ofs); trap.slope1 = itofix(x3-x2) / (y3-y2); trap.slope2 = (y3 > y1) ? (itofix(x3-x1) / (y3-y1)) : 0; if (trap.slope1 < 0) trap.x1 += MIN(trap.slope1+itofix(1), 0); if (trap.slope2 < 0) trap.x2 += MIN(trap.slope2+itofix(1), 0); if (trap.x1 > trap.x2) trap.x1 += MAX(ABS(trap.slope1), itofix(1)); else trap.x2 += MAX(ABS(trap.slope2), itofix(1)); af_driver->DrawTrap(af_driver, color, &trap); } ); } /* vbeaf_draw_glyph: * Monochrome text plotter. */ static void vbeaf_draw_glyph(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg) { AL_CONST unsigned char *data = glyph->dat; int w = glyph->w; int h = glyph->h; int stride = (w+7)/8; int d; /* give up if we can't draw this */ if ((x < bmp->cl) || (x+w >= bmp->cr) || ((w&7) && (bg >= 0))) { orig_draw_glyph(bmp, glyph, x, y, color, bg); return; } /* clip the top */ if (y < bmp->ct) { d = bmp->ct - y; h -= d; if (h <= 0) return; data += d*stride; y = bmp->ct; } /* clip the bottom */ if (y+h >= bmp->cb) { h = bmp->cb - y; if (h <= 0) return; } SAFE_CALL( /* set the mix mode */ if (bg >= 0) { af_driver->SetMix(af_driver, 0, 0); d = bg; } else { af_driver->SetMix(af_driver, 0, 4); d = 0; } /* draw the letter */ go_accel(); af_driver->PutMonoImage(af_driver, color, d, x+bmp->x_ofs, y+bmp->y_ofs, stride, 0, 0, stride*8, h, (unsigned char *)data); af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix); ); } /* vbeaf_draw_sprite: * Accelerated sprite drawing routine. */ static void vbeaf_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) { int sx, sy, w, h; int pitch; if (((sprite->vtable == &_screen_vtable) && (af_driver->SrcTransBlt)) || ((sprite->vtable != &_screen_vtable) && (af_driver->SrcTransBltSys))) { /* this sprite can be drawn in hardware */ sx = sprite->x_ofs; sy = sprite->y_ofs; w = sprite->w; h = sprite->h; if (bmp->clip) { if (x < bmp->cl) { sx += bmp->cl-x; w -= bmp->cl-x; x = bmp->cl; } if (y < bmp->ct) { sy += bmp->ct-y; h -= bmp->ct-y; y = bmp->ct; } if (x+w > bmp->cr) w = bmp->cr-x; if (w <= 0) return; if (y+h > bmp->cb) h = bmp->cb-y; if (h <= 0) return; } if (sprite->vtable == &_screen_vtable) { /* hardware blit within the video memory */ SAFISH_CALL( go_accel(); af_driver->SrcTransBlt(af_driver, sx, sy, w, h, x+bmp->x_ofs, y+bmp->y_ofs, 0, sprite->vtable->mask_color); ); } else { /* hardware blit from system memory */ if (sprite->h > 1) pitch = (long)sprite->line[1] - (long)sprite->line[0]; else pitch = sprite->w; SAFE_CALL( go_accel(); af_driver->SrcTransBltSys(af_driver, sprite->line[0], pitch, sx, sy, w, h, x+bmp->x_ofs, y+bmp->y_ofs, 0, sprite->vtable->mask_color); ); } } else { /* have to use the original software version */ orig_draw_sprite(bmp, sprite, x, y); } } END_OF_STATIC_FUNCTION(vbeaf_draw_sprite); /* vbeaf_blit_from_memory: * Accelerated system memory -> vram blitting routine. */ static void vbeaf_blit_from_memory(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { int pitch; if (source->h > 1) pitch = (long)source->line[1] - (long)source->line[0]; else pitch = source->w; SAFE_CALL( go_accel(); af_driver->BitBltSys(af_driver, source->line[0], pitch, source_x, source_y, width, height, dest_x+dest->x_ofs, dest_y+dest->y_ofs, 0); ); } END_OF_STATIC_FUNCTION(vbeaf_blit_from_memory); /* vbeaf_blit_to_self: * Accelerated vram -> vram blitting routine. */ static void vbeaf_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { SAFISH_CALL( go_accel(); af_driver->BitBlt(af_driver, source_x+source->x_ofs, source_y+source->y_ofs, width, height, dest_x+dest->x_ofs, dest_y+dest->y_ofs, 0); ); } /* vbeaf_masked_blit: * Accelerated masked blitting routine. */ static void vbeaf_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { int pitch; if ((source->vtable == &_screen_vtable) && (af_driver->SrcTransBlt)) { /* hardware blit within the video memory */ SAFISH_CALL( go_accel(); af_driver->SrcTransBlt(af_driver, source_x+source->x_ofs, source_y+source->y_ofs, width, height, dest_x+dest->x_ofs, dest_y+dest->y_ofs, 0, source->vtable->mask_color); ); } else if (af_driver->SrcTransBltSys) { /* hardware blit from system memory */ if (source->h > 1) pitch = (long)source->line[1] - (long)source->line[0]; else pitch = source->w; SAFE_CALL( go_accel(); af_driver->SrcTransBltSys(af_driver, source->line[0], pitch, source_x, source_y, width, height, dest_x+dest->x_ofs, dest_y+dest->y_ofs, 0, source->vtable->mask_color); ); } else { /* have to use the original software version */ orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height); } } /* vbeaf_clear_to_color: * Accelerated screen clear routine. */ static void vbeaf_clear_to_color(BITMAP *bitmap, int color) { SAFISH_CALL( go_accel(); if ((vbeaf_fg_mix != 0) || (vbeaf_bg_mix != 0)) af_driver->SetMix(af_driver, 0, 0); af_driver->DrawRect(af_driver, color, bitmap->cl+bitmap->x_ofs, bitmap->ct+bitmap->y_ofs, bitmap->cr-bitmap->cl, bitmap->cb-bitmap->ct); if ((vbeaf_fg_mix != 0) || (vbeaf_bg_mix != 0)) af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix); ); } #endif /* ifdef VBE/AF is cool on this platform */ allegro-4.4.3.1/src/misc/fm_drum.h0000664000175000017500000001331513437077643015627 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * This set of GM percussion patches was provided partly by Jorrit Rouwe, * and partly taken from the SBTimbre utility... */ static FM_INSTRUMENT fm_drum[47] = { { 0x10, 0x11, 0x22, 0x0b, 0xf8, 0xf3, 0x77, 0x06, 0x02, 0x00, 0x38, 0x87, 0x06, FM_BD }, /* Acoustic Bass Drum */ { 0x10, 0x11, 0x22, 0x0b, 0xf8, 0xf3, 0x77, 0x06, 0x02, 0x00, 0x38, 0x87, 0x06, FM_BD }, /* Bass Drum 1 */ { 0x02, 0x11, 0x07, 0x0b, 0xf9, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x38, 0x60, 0x0b, FM_TT }, /* Side Stick */ { 0x00, 0x00, 0x00, 0x0b, 0xfc, 0xfa, 0x05, 0x17, 0x02, 0x00, 0x3e, 0xad, 0x0a, FM_SD }, /* Acoustic Snare */ { 0x00, 0x01, 0x02, 0x0b, 0xff, 0xff, 0x07, 0x08, 0x00, 0x00, 0x30, 0x63, 0x0e, FM_SD }, /* Hand Clap */ { 0x00, 0x00, 0x00, 0x0b, 0xfc, 0xfa, 0x05, 0x17, 0x02, 0x00, 0x3e, 0xad, 0x0e, FM_SD }, /* Electric Snare */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0x57, 0x0d, FM_TT }, /* Low Floor Tom */ { 0x01, 0x01, 0x03, 0x03, 0xb8, 0xb8, 0xb5, 0xb5, 0x01, 0x01, 0x0d, 0x57, 0x11, FM_CY }, /* Closed Hi-Hat */ { 0x01, 0x01, 0x00, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0xb0, 0x0d, FM_TT }, /* High Floor Tom */ { 0x01, 0x01, 0x08, 0x08, 0x88, 0x88, 0xa5, 0xa5, 0x01, 0x01, 0x03, 0x57, 0x11, FM_CY }, /* Pedal Hi-Hat */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0x02, 0x0e, FM_TT }, /* Low Tom */ { 0x01, 0x01, 0x09, 0x09, 0x86, 0x86, 0xa5, 0xa5, 0x01, 0x01, 0x03, 0x57, 0x11, FM_CY }, /* Open Hi-Hat */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0x57, 0x11, FM_TT }, /* Low-Mid Tom */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0xb0, 0x11, FM_TT }, /* Hi-Mid Tom */ { 0xb7, 0x01, 0x41, 0x00, 0x37, 0xff, 0x90, 0x06, 0x01, 0x00, 0x00, 0x57, 0x11, FM_CY }, /* Crash Cymbal 1 */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0x02, 0x12, FM_TT }, /* High Tom */ { 0x01, 0x01, 0x82, 0x82, 0xf6, 0xf6, 0xd5, 0xd5, 0x01, 0x01, 0x03, 0x57, 0x11, FM_CY }, /* Ride Cymbal 1 */ { 0xb7, 0x01, 0x41, 0x00, 0x37, 0xff, 0x90, 0x06, 0x01, 0x00, 0x00, 0x57, 0x11, FM_CY }, /* Chinese Cymbal */ { 0x0e, 0x0e, 0x07, 0x07, 0xb5, 0xb5, 0x15, 0x15, 0x01, 0x01, 0x0b, 0x57, 0x11, FM_CY }, /* Ride Bell */ { 0x01, 0x01, 0x07, 0x07, 0x77, 0x77, 0x73, 0x73, 0x01, 0x01, 0x0b, 0x57, 0x11, FM_CY }, /* Tambourine */ { 0xb7, 0x01, 0x41, 0x00, 0x37, 0xff, 0x90, 0x06, 0x01, 0x00, 0x00, 0x57, 0x11, FM_CY }, /* Splash Cymbal */ { 0x10, 0x10, 0x00, 0x00, 0x96, 0x96, 0x67, 0x67, 0x00, 0x00, 0x0a, 0xb0, 0x11, FM_SD }, /* Cowbell */ { 0xb7, 0x01, 0x41, 0x00, 0x37, 0xff, 0x90, 0x06, 0x01, 0x00, 0x00, 0x57, 0x11, FM_CY }, /* Crash Cymbal 2 */ { 0x01, 0x01, 0x07, 0x07, 0xf9, 0xf9, 0xb5, 0xb5, 0x00, 0x00, 0x0b, 0x57, 0x11, FM_SD }, /* Vibraslap */ { 0xd1, 0xd1, 0x05, 0x05, 0xe7, 0xe7, 0x65, 0x65, 0x01, 0x01, 0x0d, 0x57, 0x11, FM_SD }, /* Ride Cymbal 2 */ { 0x01, 0x01, 0x00, 0x00, 0xe7, 0xe7, 0x94, 0x94, 0x00, 0x00, 0x03, 0x02, 0x12, FM_TT }, /* Hi Bongo */ { 0x01, 0x01, 0x00, 0x00, 0xe7, 0xe7, 0x94, 0x94, 0x00, 0x00, 0x0b, 0x81, 0x11, FM_TT }, /* Low Bongo */ { 0x01, 0x01, 0x00, 0x00, 0x96, 0x96, 0x67, 0x67, 0x00, 0x00, 0x0a, 0x02, 0x12, FM_TT }, /* Mute Hi Conga */ { 0x01, 0x01, 0x00, 0x00, 0xb4, 0xb4, 0x26, 0x26, 0x00, 0x00, 0x0a, 0x02, 0x12, FM_TT }, /* Open Hi Conga */ { 0x01, 0x01, 0x00, 0x00, 0xb4, 0xb4, 0x26, 0x26, 0x00, 0x00, 0x0a, 0x57, 0x11, FM_TT }, /* Low Conga */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0x57, 0x11, FM_TT }, /* High Timbale */ { 0x01, 0x01, 0x08, 0x08, 0xc6, 0xc6, 0x98, 0x98, 0x00, 0x00, 0x05, 0x02, 0x0e, FM_TT }, /* Low Timbale */ { 0x05, 0xa7, 0x00, 0x7f, 0xf6, 0x33, 0x56, 0x90, 0x00, 0x03, 0x00, 0x63, 0x0e, FM_TT }, /* High Agogo */ { 0x05, 0xa7, 0x00, 0x7f, 0xf6, 0x33, 0x56, 0x90, 0x00, 0x03, 0x00, 0x93, 0x0b, FM_TT }, /* Low Agogo */ { 0x00, 0x00, 0x2e, 0x2e, 0x8a, 0x8a, 0xec, 0xec, 0x02, 0x02, 0x0a, 0x57, 0x11, FM_HH }, /* Cabasa */ { 0x00, 0x00, 0x2e, 0x2e, 0x8b, 0x8b, 0xe6, 0xe6, 0x02, 0x02, 0x0a, 0x57, 0x11, FM_HH }, /* Maracas */ { 0x52, 0x52, 0x27, 0x27, 0x59, 0x59, 0x15, 0x15, 0x03, 0x03, 0x0b, 0x82, 0x16, FM_TT }, /* Short Whistle */ { 0x52, 0x52, 0x27, 0x27, 0x48, 0x48, 0x14, 0x14, 0x03, 0x03, 0x0b, 0x82, 0x16, FM_TT }, /* Long Whistle */ { 0x00, 0x00, 0x0e, 0x0e, 0x5a, 0x5a, 0xd6, 0xd6, 0x01, 0x01, 0x0a, 0x57, 0x11, FM_HH }, /* Short Guiro */ { 0x10, 0x10, 0x0e, 0x0e, 0x53, 0x53, 0x9f, 0x9f, 0x01, 0x01, 0x0a, 0x57, 0x11, FM_HH }, /* Long Guiro */ { 0x11, 0x11, 0x00, 0x00, 0xf5, 0xf5, 0x75, 0x75, 0x00, 0x00, 0x02, 0x02, 0x1a, FM_TT }, /* Claves */ { 0x04, 0x04, 0x00, 0x00, 0xf8, 0xf8, 0xb6, 0xb6, 0x01, 0x01, 0x03, 0x57, 0x11, FM_TT }, /* Hi Wood Block */ { 0x04, 0x04, 0x00, 0x00, 0xf8, 0xf8, 0xb7, 0xb7, 0x01, 0x01, 0x03, 0xca, 0x0d, FM_TT }, /* Low Wood Block */ { 0x01, 0x01, 0x0b, 0x0b, 0x5e, 0x5e, 0xdc, 0xdc, 0x01, 0x01, 0x0a, 0x57, 0x11, FM_HH }, /* Mute Cuica */ { 0x00, 0x00, 0x07, 0x07, 0x5c, 0x5c, 0xdc, 0xdc, 0x01, 0x01, 0x0a, 0x57, 0x11, FM_HH }, /* Open Cuica */ { 0xc5, 0xd5, 0x4f, 0x10, 0xf6, 0xf6, 0x84, 0x84, 0x00, 0x00, 0x08, 0x02, 0x16, FM_BD }, /* Mute Triangle */ { 0xc5, 0xd5, 0x4f, 0x10, 0xf6, 0xf6, 0x84, 0x72, 0x00, 0x00, 0x08, 0x02, 0x16, FM_BD } /* Open Triangle */ }; allegro-4.4.3.1/src/misc/vbeafs.s0000664000175000017500000001136213437077643015457 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * VBE/AF bank switchers and assorted helper functions. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "../i386/asmdefs.inc" #if (defined ALLEGRO_DOS) || (defined ALLEGRO_LINUX_VBEAF) .text #ifdef ALLEGRO_DOS #define VBEAF_SELECTOR GLOBL(__djgpp_ds_alias) #else #define VBEAF_SELECTOR GLOBL(_vbeaf_selector) #endif /* memory locking marker */ FUNC(_af_wrapper) /* callback for VBE/AF to access real mode interrupts (DPMI 0x300) */ FUNC(_af_int86) #ifdef ALLEGRO_DOS pushal pushw %es pushw %ds popw %es xorb %bh, %bh xorl %ecx, %ecx movl $0x300, %eax int $0x31 popw %es popal #endif ret /* callback for VBE/AF to access real mode functions (DPMI 0x301) */ FUNC(_af_call_rm) #ifdef ALLEGRO_DOS pushal pushw %es pushw %ds popw %es xorb %bh, %bh xorl %ecx, %ecx movl $0x301, %eax int $0x31 popw %es popal #endif ret /* memory locking marker */ FUNC(_af_wrapper_end) /* helper for accelerated driver bank switches, which arbitrates between * hardware and cpu control over the video memory. */ #define DISABLE_ACCEL(name) \ cmpl $0, GLOBL(_accel_active) ; \ jz name##_inactive ; \ ; \ pushl %eax /* save registers */ ; \ pushl %ebx ; \ pushl %ecx ; \ pushl %edx ; \ ; \ movw %es, %bx /* make %es be valid */ ; \ movw VBEAF_SELECTOR, %dx ; \ movw %dx, %es ; \ ; \ movl GLOBL(_accel_driver), %ecx ; \ movl GLOBL(_accel_idle), %edx ; \ pushl %ecx ; \ call *%edx /* turn off the graphics hardware */ ; \ addl $4, %esp ; \ ; \ movw %bx, %es /* restore registers */ ; \ ; \ popl %edx ; \ popl %ecx ; \ popl %ebx ; \ popl %eax ; \ ; \ movl $0, GLOBL(_accel_active) ; \ ; \ _align_ ; \ name##_inactive: /* stub for linear accelerated graphics modes */ FUNC(_accel_bank_stub) DISABLE_ACCEL(accel_bank_stub) movl BMP_LINE(%edx, %eax, 4), %eax ret FUNC(_accel_bank_stub_end) ret /* bank switcher for accelerated graphics modes */ FUNC(_accel_bank_switch) DISABLE_ACCEL(accel_bank_switch) pushl %eax addl BMP_YOFFSET(%edx), %eax /* lookup which bank */ shll $2, %eax addl GLOBL(_gfx_bank), %eax movl (%eax), %eax cmpl GLOBL(_last_bank_1), %eax /* need to change? */ je accel_bank_switch_done movl %eax, GLOBL(_last_bank_1) /* store the new bank */ pushl %ebx /* store registers */ pushl %ecx pushl %edx movw %es, %bx /* make %es be valid */ movw VBEAF_SELECTOR, %dx movw %dx, %es movl GLOBL(_accel_driver), %ecx /* switch banks */ movl GLOBL(_accel_set_bank), %edx pushl %eax pushl %ecx call *%edx addl $8, %esp movw %bx, %es /* restore registers */ popl %edx popl %ecx popl %ebx _align_ accel_bank_switch_done: popl %eax movl BMP_LINE(%edx, %eax, 4), %eax /* load line address */ ret FUNC(_accel_bank_switch_end) ret #endif /* ifdef VBE/AF is cool on this platform */ allegro-4.4.3.1/src/misc/icolconv.s0000664000175000017500000033117213437077643016031 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Asm routines for software color conversion. * Suggestions to make it faster are welcome :) * * By Isaac Cruz. * * 24-bit color support and non MMX routines by Eric Botcazou. * * Support for rectangles of any width, 8-bit destination color * and cross-conversion between 15-bit and 16-bit colors, * additional MMX and color copy routines by Robert J. Ohannessian. * * See readme.txt for copyright information. */ #include "src/i386/asmdefs.inc" /* Better keep the stack pointer 16-byte aligned on modern CPUs */ #if !defined(__GNUC__) || (__GNUC__ < 3) #define SLOTS_TO_BYTES(n) (n*4) #else #define SLOTS_TO_BYTES(n) (((n*4+15)>>4)*16) #endif .text #ifdef ALLEGRO_MMX /* it seems pand is broken in GAS 2.8.1 */ #define PAND(src, dst) \ .byte 0x0f, 0xdb ; \ .byte 0xc0 + 8*dst + src /* mod field */ /* local variables */ #define RESERVE_LOCALS(n) subl $SLOTS_TO_BYTES(n), %esp #define CLEANUP_LOCALS(n) addl $SLOTS_TO_BYTES(n), %esp #define LOCAL1 0(%esp) #define LOCAL2 4(%esp) #define LOCAL3 8(%esp) #define LOCAL4 12(%esp) /* helper macros */ #define INIT_CONVERSION_1(mask_red, mask_green, mask_blue) \ /* init register values */ ; \ ; \ movl mask_green, %esi ; \ movd %esi, %mm3 ; \ punpckldq %mm3, %mm3 ; \ movl mask_red, %esi ; \ movd %esi, %mm4 ; \ punpckldq %mm4, %mm4 ; \ movl mask_blue, %esi ; \ movd %esi, %mm5 ; \ punpckldq %mm5, %mm5 ; \ ; \ movl ARG1, %esi /* esi = src_rect */ ; \ movl GFXRECT_WIDTH(%esi), %ecx /* ecx = src_rect->width */ ; \ movl GFXRECT_HEIGHT(%esi), %edx /* edx = src_rect->height */ ; \ movl GFXRECT_PITCH(%esi), %eax /* eax = src_rect->pitch */ ; \ movl GFXRECT_DATA(%esi), %esi /* esi = src_rect->data */ ; \ shll $2, %ecx /* ecx = SCREEN_W * 4 */ ; \ subl %ecx, %eax /* eax = (src_rect->pitch) - ecx */ ; \ ; \ movl ARG2, %edi /* edi = dest_rect */ ; \ shrl $1, %ecx /* ecx = SCREEN_W * 2 */ ; \ movl GFXRECT_PITCH(%edi), %ebx /* ebx = dest_rect->pitch */ ; \ movl GFXRECT_DATA(%edi), %edi /* edi = dest_rect->data */ ; \ subl %ecx, %ebx /* ebx = (dest_rect->pitch) - ecx */ ; \ shrl $1, %ecx /* ecx = SCREEN_W */ ; \ movl %ecx, %ebp #define INIT_CONVERSION_2(mask_red, mask_green, mask_blue) \ /* init register values */ ; \ ; \ movl mask_green, %esi ; \ movd %esi, %mm3 ; \ punpckldq %mm3, %mm3 ; \ movl mask_red, %esi ; \ movd %esi, %mm4 ; \ punpckldq %mm4, %mm4 ; \ movl mask_blue, %esi ; \ movd %esi, %mm5 ; \ punpckldq %mm5, %mm5 ; \ ; \ movl ARG1, %esi /* esi = src_rect */ ; \ movl GFXRECT_WIDTH(%esi), %ecx /* ecx = src_rect->width */ ; \ movl GFXRECT_HEIGHT(%esi), %edx /* edx = src_rect->height */ ; \ movl GFXRECT_PITCH(%esi), %eax /* eax = src_rect->pitch */ ; \ movl GFXRECT_DATA(%esi), %esi /* esi = src_rect->data */ ; \ addl %ecx, %ecx /* ecx = SCREEN_W * 2 */ ; \ subl %ecx, %eax /* eax = (src_rect->pitch) - ecx */ ; \ ; \ movl ARG2, %edi /* edi = dest_rect */ ; \ addl %ecx, %ecx /* ecx = SCREEN_W * 4 */ ; \ movl GFXRECT_PITCH(%edi), %ebx /* ebx = dest_rect->pitch */ ; \ movl GFXRECT_DATA(%edi), %edi /* edi = dest_rect->data */ ; \ subl %ecx, %ebx /* ebx = (dest_rect->pitch) - ecx */ ; \ shrl $2, %ecx /* ecx = SCREEN_W */ ; \ movl %ecx, %ebp #ifdef ALLEGRO_COLOR8 /* void _colorconv_blit_8_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT dest_rect) */ /* void _colorconv_blit_8_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT dest_rect) */ FUNC (_colorconv_blit_8_to_15) FUNC (_colorconv_blit_8_to_16) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_8_to_16_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi RESERVE_LOCALS(4) /* init register values */ movl ARG1, %esi /* esi = src_rect */ movl GFXRECT_WIDTH(%esi), %ecx /* ecx = src_rect->width */ movl GFXRECT_HEIGHT(%esi), %eax /* eax = src_rect->height */ movl GFXRECT_PITCH(%esi), %ebx /* ebx = src_rect->pitch */ movl GFXRECT_DATA(%esi), %esi /* esi = src_rect->data */ movl %eax, LOCAL1 /* LOCAL1 = SCREEN_H */ subl %ecx, %ebx movl %ebx, LOCAL2 /* LOCAL2 = src_rect->pitch - SCREEN_W */ movl ARG2, %edi /* edi = dest_rect */ addl %ecx, %ecx /* ecx = SCREEN_W * 2 */ movl GFXRECT_PITCH(%edi), %edx /* edx = dest_rect->pitch */ movl GFXRECT_DATA(%edi), %edi /* edi = dest_rect->data */ subl %ecx, %edx movl %edx, LOCAL3 /* LOCAL3 = (dest_rect->pitch) - (SCREEN_W * 2) */ shrl $1, %ecx /* ecx = SCREEN_W */ movl GLOBL(_colorconv_indexed_palette), %ebp /* ebp = _colorconv_indexed_palette */ movl %ecx, %ebx /* 8 bit to 16 bit conversion: we have: eax = free ebx = SCREEN_W ecx = SCREEN_W edx = free esi = src_rect->data edi = dest_rect->data ebp = _colorconv_indexed_palette LOCAL1 = SCREEN_H LOCAL2 = offset from the end of a line to the beginning of the next LOCAL3 = same as LOCAL2, but for the dest bitmap */ _align_ next_line_8_to_16: shrl $2, %ecx /* work with packs of 4 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_8_to_16 /* less than 4 pixels? Can't work with the main loop */ #endif _align_ next_block_8_to_16: movl (%esi), %edx /* edx = [4][3][2][1] */ movzbl %dl, %eax movd (%ebp,%eax,4), %mm0 /* mm0 = xxxxxxxxxx xxxxx[ 1 ] */ shrl $8, %edx movzbl %dl, %eax movd (%ebp,%eax,4), %mm1 /* mm1 = xxxxxxxxxx xxxxx[ 2 ] */ punpcklwd %mm1, %mm0 /* mm0 = xxxxxxxxxx [ 2 ][ 1 ] */ shrl $8, %edx movzbl %dl, %eax movd (%ebp,%eax,4), %mm2 /* mm2 = xxxxxxxxxx xxxxx[ 3 ] */ shrl $8, %edx movl %edx, %eax movd (%ebp,%eax,4), %mm3 /* mm3 = xxxxxxxxxx xxxxx[ 4 ] */ punpcklwd %mm3, %mm2 /* mm2 = xxxxxxxxxx [ 4 ][ 3 ] */ addl $4, %esi punpckldq %mm2, %mm0 /* mm0 = [ 4 ][ 3 ] [ 2 ][ 1 ] */ movq %mm0, (%edi) addl $8, %edi decl %ecx jnz next_block_8_to_16 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_8_to_16: movl %ebx, %ecx /* restore width */ andl $3, %ecx jz end_of_line_8_to_16 /* nothing to do? */ shrl $1, %ecx jnc do_two_pixels_8_to_16 movzbl (%esi), %edx /* convert 1 pixel */ movl (%ebp,%edx,4), %eax incl %esi addl $2, %edi movw %ax, -2(%edi) do_two_pixels_8_to_16: shrl $1, %ecx jnc end_of_line_8_to_16 movzbl (%esi), %edx /* convert 2 pixels */ movzbl 1(%esi), %eax movl (%ebp,%edx,4), %edx movl (%ebp,%eax,4), %eax shll $16, %eax addl $2, %esi orl %eax, %edx addl $4, %edi movl %edx, -4(%edi) _align_ end_of_line_8_to_16: #endif movl LOCAL2, %edx addl %edx, %esi movl LOCAL3, %eax addl %eax, %edi movl LOCAL1, %edx movl %ebx, %ecx /* restore width */ decl %edx movl %edx, LOCAL1 jnz next_line_8_to_16 CLEANUP_LOCALS(4) emms popl %edi popl %esi popl %ebx popl %ebp ret /* void _colorconv_blit_8_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_8_to_32) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_8_to_32_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi RESERVE_LOCALS(4) /* init register values */ movl ARG1, %esi /* esi = src_rect */ movl GFXRECT_WIDTH(%esi), %ecx /* ecx = src_rect->width */ movl GFXRECT_HEIGHT(%esi), %eax /* eax = src_rect->height */ movl GFXRECT_PITCH(%esi), %ebx /* ebx = src_rect->pitch */ movl GFXRECT_DATA(%esi), %esi /* esi = src_rect->data */ movl %eax, LOCAL1 /* LOCAL1 = SCREEN_H */ subl %ecx, %ebx movl %ebx, LOCAL2 /* LOCAL2 = src_rect->pitch - SCREEN_W */ movl ARG2, %edi /* edi = dest_rect */ shll $2, %ecx /* ecx = SCREEN_W * 4 */ movl GFXRECT_PITCH(%edi), %edx /* edx = dest_rect->pitch */ movl GFXRECT_DATA(%edi), %edi /* edi = dest_rect->data */ subl %ecx, %edx movl %edx, LOCAL3 /* LOCAL3 = (dest_rect->pitch) - (SCREEN_W * 4) */ shrl $2, %ecx /* ecx = SCREEN_W */ movl GLOBL(_colorconv_indexed_palette), %ebp /* ebp = _colorconv_indexed_palette */ movl %ecx, %ebx /* 8 bit to 32 bit conversion: we have: eax = free ebx = SCREEN_W ecx = SCREEN_W edx = free esi = src_rect->data edi = dest_rect->data ebp = _colorconv_indexed_palette LOCAL1 = SCREEN_H LOCAL2 = offset from the end of a line to the beginning of the next LOCAL3 = same as LOCAL2, but for the dest bitmap */ _align_ next_line_8_to_32: shrl $2, %ecx /* work with packs of 4 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_8_to_32 /* less than 4 pixels? Can't work with the main loop */ #endif _align_ next_block_8_to_32: movl (%esi), %edx /* edx = [4][3][2][1] */ movzbl %dl, %eax movd (%ebp,%eax,4), %mm0 /* mm0 = xxxxxxxxx [ 1 ] */ shrl $8, %edx movzbl %dl, %eax movd (%ebp,%eax,4), %mm1 /* mm1 = xxxxxxxxx [ 2 ] */ punpckldq %mm1, %mm0 /* mm0 = [ 2 ] [ 1 ] */ addl $4, %esi movq %mm0, (%edi) shrl $8, %edx movzbl %dl, %eax movd (%ebp,%eax,4), %mm0 /* mm0 = xxxxxxxxx [ 3 ] */ shrl $8, %edx movl %edx, %eax movd (%ebp,%eax,4), %mm1 /* mm1 = xxxxxxxxx [ 4 ] */ punpckldq %mm1, %mm0 /* mm0 = [ 4 ] [ 3 ] */ movq %mm0, 8(%edi) addl $16, %edi decl %ecx jnz next_block_8_to_32 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_8_to_32: movl %ebx, %ecx /* restore width */ andl $3, %ecx jz end_of_line_8_to_32 /* nothing to do? */ shrl $1, %ecx jnc do_two_pixels_8_to_32 movzbl (%esi), %edx /* convert 1 pixel */ movl (%ebp,%edx,4), %edx incl %esi addl $4, %edi movl %edx, -4(%edi) do_two_pixels_8_to_32: shrl $1, %ecx jnc end_of_line_8_to_32 movzbl (%esi), %edx /* convert 2 pixels */ movzbl 1(%esi), %eax movl (%ebp,%edx,4), %edx movl (%ebp,%eax,4), %eax addl $2, %esi movl %edx, (%edi) movl %eax, 4(%edi) addl $8, %edi _align_ end_of_line_8_to_32: #endif movl LOCAL2, %edx addl %edx, %esi movl LOCAL3, %eax addl %eax, %edi movl LOCAL1, %edx movl %ebx, %ecx /* restore width */ decl %edx movl %edx, LOCAL1 jnz next_line_8_to_32 CLEANUP_LOCALS(4) emms popl %edi popl %esi popl %ebx popl %ebp ret #endif /* ALLEGRO_COLOR8 */ #ifdef ALLEGRO_COLOR16 /* void _colorconv_blit_15_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_15_to_16) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_15_to_16_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi /* init register values */ movl ARG1, %eax /* eax = src_rect */ movl GFXRECT_WIDTH(%eax), %ecx /* ecx = src_rect->width */ movl GFXRECT_HEIGHT(%eax), %edx /* edx = src_rect->height */ shll $1, %ecx movl GFXRECT_DATA(%eax), %esi /* esi = src_rect->data */ movl GFXRECT_PITCH(%eax), %eax /* eax = src_rect->pitch */ subl %ecx, %eax movl ARG2, %ebx /* ebx = dest_rect */ movl GFXRECT_DATA(%ebx), %edi /* edi = dest_rect->data */ movl GFXRECT_PITCH(%ebx), %ebx /* ebx = dest_rect->pitch */ subl %ecx, %ebx shrl $1, %ecx /* 15 bit to 16 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data */ movd %ecx, %mm7 /* save width for later */ movl $0x7FE07FE0, %ecx movd %ecx, %mm6 movl $0x00200020, %ecx /* addition to green component */ punpckldq %mm6, %mm6 /* mm6 = reg-green mask */ movd %ecx, %mm4 movl $0x001F001F, %ecx punpckldq %mm4, %mm4 /* mm4 = green add mask */ movd %ecx, %mm5 punpckldq %mm5, %mm5 /* mm5 = blue mask */ movd %mm7, %ecx _align_ next_line_15_to_16: shrl $3, %ecx /* work with packs of 8 pixels */ orl %ecx, %ecx jz do_one_pixel_15_to_16 /* less than 8 pixels? Can't work with the main loop */ _align_ next_block_15_to_16: movq (%esi), %mm0 /* read 8 pixels */ movq 8(%esi), %mm1 /* mm1 = [rgb7][rgb6][rgb5][rgb4] */ movq %mm0, %mm2 /* mm0 = [rgb3][rgb2][rgb1][rgb0] */ movq %mm1, %mm3 pand %mm6, %mm0 /* isolate red-green */ pand %mm6, %mm1 pand %mm5, %mm2 /* isolate blue */ pand %mm5, %mm3 psllq $1, %mm0 /* shift red-green by 1 bit to the left */ addl $16, %esi psllq $1, %mm1 addl $16, %edi por %mm4, %mm0 /* set missing bit to 1 */ por %mm4, %mm1 por %mm2, %mm0 /* recombine components */ por %mm3, %mm1 movq %mm0, -16(%edi) /* write result */ movq %mm1, -8(%edi) decl %ecx jnz next_block_15_to_16 do_one_pixel_15_to_16: movd %mm7, %ecx /* anything left to do? */ andl $7, %ecx jz end_of_line_15_to_16 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $1, %ecx /* do one pixel */ jnc do_two_pixels_15_to_16 movzwl (%esi), %ecx /* read one pixel */ addl $2, %esi movd %ecx, %mm0 movd %ecx, %mm2 pand %mm6, %mm0 pand %mm5, %mm2 psllq $1, %mm0 addl $2, %edi por %mm4, %mm0 por %mm2, %mm0 movd %mm0, %ecx movw %cx, -2(%edi) movd %mm7, %ecx shrl $1, %ecx do_two_pixels_15_to_16: shrl $1, %ecx jnc do_four_pixels_15_to_16 movd (%esi), %mm0 /* read two pixels */ addl $4, %esi movq %mm0, %mm2 pand %mm6, %mm0 pand %mm5, %mm2 psllq $1, %mm0 addl $4, %edi por %mm4, %mm0 por %mm2, %mm0 movd %mm0, -4(%edi) _align_ do_four_pixels_15_to_16: shrl $1, %ecx jnc end_of_line_15_to_16 #endif movq (%esi), %mm0 /* read four pixels */ addl $8, %esi movq %mm0, %mm2 pand %mm6, %mm0 pand %mm5, %mm2 psllq $1, %mm0 por %mm4, %mm0 por %mm2, %mm0 addl $8, %edi movq %mm0, -8(%edi) _align_ end_of_line_15_to_16: addl %eax, %esi movd %mm7, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_15_to_16 emms popl %edi popl %esi popl %ebx popl %ebp ret /* void _colorconv_blit_15_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_15_to_32) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_15_to_32_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi INIT_CONVERSION_2 ($0x7c00, $0x03e0, $0x001f); /* 15 bit to 32 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data ebp = SCREEN_W */ _align_ next_line_15_to_32: shrl $1, %ecx /* work with packs of 2 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_15_to_32 /* 1 pixel? Can't use dual-pixel code */ #endif _align_ next_block_15_to_32: movd (%esi), %mm0 /* mm0 = 0000 0000 [rgb1][rgb2] */ punpcklwd %mm0, %mm0 /* mm0 = xxxx [rgb1] xxxx [rgb2] (x don't matter) */ movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ pslld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ pslld $6, %mm1 por %mm1, %mm0 addl $4, %esi PAND (4, 2) /* pand %mm4, %mm2 */ pslld $9, %mm2 por %mm2, %mm0 movq %mm0, (%edi) addl $8, %edi decl %ecx jnz next_block_15_to_32 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_15_to_32: movl %ebp, %ecx /* restore width */ shrl $1, %ecx jnc end_of_line_15_to_32 movd (%esi), %mm0 punpcklwd %mm0, %mm0 movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ pslld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ pslld $6, %mm1 por %mm1, %mm0 addl $2, %esi PAND (4, 2) /* pand %mm4, %mm2 */ pslld $9, %mm2 por %mm2, %mm0 movd %mm0, (%edi) addl $4, %edi _align_ end_of_line_15_to_32: #endif addl %eax, %esi movl %ebp, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_15_to_32 emms popl %edi popl %esi popl %ebx popl %ebp ret /* void _colorconv_blit_16_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_16_to_15) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_16_to_15_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi /* init register values */ movl ARG1, %eax /* eax = src_rect */ movl GFXRECT_WIDTH(%eax), %ecx /* ecx = src_rect->width */ movl GFXRECT_HEIGHT(%eax), %edx /* edx = src_rect->height */ shll $1, %ecx movl GFXRECT_DATA(%eax), %esi /* esi = src_rect->data */ movl GFXRECT_PITCH(%eax), %eax /* eax = src_rect->pitch */ subl %ecx, %eax movl ARG2, %ebx /* ebx = dest_rect */ movl GFXRECT_DATA(%ebx), %edi /* edi = dest_rect->data */ movl GFXRECT_PITCH(%ebx), %ebx /* ebx = dest_rect->pitch */ subl %ecx, %ebx shrl $1, %ecx /* 16 bit to 15 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data */ movd %ecx, %mm7 /* save width for later */ movl $0xFFC0FFC0, %ecx movd %ecx, %mm6 punpckldq %mm6, %mm6 /* mm6 = reg-green mask */ movl $0x001F001F, %ecx movd %ecx, %mm5 punpckldq %mm5, %mm5 /* mm4 = blue mask */ movd %mm7, %ecx _align_ next_line_16_to_15: shrl $3, %ecx /* work with packs of 8 pixels */ orl %ecx, %ecx jz do_one_pixel_16_to_15 /* less than 8 pixels? Can't work with the main loop */ _align_ next_block_16_to_15: movq (%esi), %mm0 /* read 8 pixels */ movq 8(%esi), %mm1 /* mm1 = [rgb7][rgb6][rgb5][rgb4] */ addl $16, %esi addl $16, %edi movq %mm0, %mm2 /* mm0 = [rgb3][rgb2][rgb1][rgb0] */ movq %mm1, %mm3 pand %mm6, %mm0 /* isolate red-green */ pand %mm6, %mm1 pand %mm5, %mm2 /* isolate blue */ psrlq $1, %mm0 /* shift red-green by 1 bit to the right */ pand %mm5, %mm3 psrlq $1, %mm1 por %mm2, %mm0 /* recombine components */ por %mm3, %mm1 movq %mm0, -16(%edi) /* write result */ movq %mm1, -8(%edi) decl %ecx jnz next_block_16_to_15 do_one_pixel_16_to_15: movd %mm7, %ecx /* anything left to do? */ andl $7, %ecx jz end_of_line_16_to_15 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $1, %ecx /* do one pixel */ jnc do_two_pixels_16_to_15 movzwl (%esi), %ecx /* read one pixel */ addl $2, %esi movd %ecx, %mm0 movd %ecx, %mm2 pand %mm6, %mm0 pand %mm5, %mm2 psrlq $1, %mm0 por %mm2, %mm0 movd %mm0, %ecx addl $2, %edi movw %cx, -2(%edi) movd %mm7, %ecx shrl $1, %ecx do_two_pixels_16_to_15: shrl $1, %ecx jnc do_four_pixels_16_to_15 movd (%esi), %mm0 /* read two pixels */ addl $4, %esi movq %mm0, %mm2 pand %mm6, %mm0 pand %mm5, %mm2 psrlq $1, %mm0 por %mm2, %mm0 addl $4, %edi movd %mm0, -4(%edi) _align_ do_four_pixels_16_to_15: shrl $1, %ecx jnc end_of_line_16_to_15 #endif movq (%esi), %mm0 /* read four pixels */ addl $8, %esi movq %mm0, %mm2 pand %mm6, %mm0 pand %mm5, %mm2 psrlq $1, %mm0 por %mm2, %mm0 addl $8, %edi movd %mm0, -8(%edi) _align_ end_of_line_16_to_15: addl %eax, %esi movd %mm7, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_16_to_15 emms popl %edi popl %esi popl %ebx popl %ebp ret /* void _colorconv_blit_16_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_16_to_32) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_16_to_32_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi INIT_CONVERSION_2 ($0xf800, $0x07e0, $0x001f); /* 16 bit to 32 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data ebp = SCREEN_W */ _align_ next_line_16_to_32: shrl $1, %ecx /* work with packs of 2 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_16_to_32 /* 1 pixel? Can't use dual-pixel code */ #endif _align_ next_block_16_to_32: movd (%esi), %mm0 /* mm0 = 0000 0000 [rgb1][rgb2] */ punpcklwd %mm0, %mm0 /* mm0 = xxxx [rgb1] xxxx [rgb2] (x don't matter) */ movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ pslld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ pslld $5, %mm1 por %mm1, %mm0 addl $4, %esi PAND (4, 2) /* pand %mm4, %mm2 */ pslld $8, %mm2 por %mm2, %mm0 movq %mm0, (%edi) addl $8, %edi decl %ecx jnz next_block_16_to_32 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_16_to_32: movl %ebp, %ecx /* restore width */ shrl $1, %ecx jnc end_of_line_16_to_32 movd (%esi), %mm0 punpcklwd %mm0, %mm0 movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ pslld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ pslld $5, %mm1 por %mm1, %mm0 addl $2, %esi PAND (4, 2) /* pand %mm4, %mm2 */ pslld $8, %mm2 por %mm2, %mm0 movd %mm0, (%edi) addl $4, %edi _align_ end_of_line_16_to_32: #endif addl %eax, %esi movl %ebp, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_16_to_32 emms popl %edi popl %esi popl %ebx popl %ebp ret #endif /* ALLEGRO_COLOR16 */ #ifdef ALLEGRO_COLOR24 /* void _colorconv_blit_24_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_24_to_32) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_24_to_32_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi /* init register values */ movl ARG1, %eax /* eax = src_rect */ movl GFXRECT_WIDTH(%eax), %ecx /* ecx = src_rect->width */ movl GFXRECT_HEIGHT(%eax), %edx /* edx = src_rect->height */ leal (%ecx, %ecx, 2), %ebx /* ebx = SCREEN_W * 3 */ movl GFXRECT_DATA(%eax), %esi /* esi = src_rect->data */ movl GFXRECT_PITCH(%eax), %eax /* eax = src_rect->pitch */ subl %ebx, %eax movl ARG2, %ebx /* ebx = dest_rect */ shll $2, %ecx /* ecx = SCREEN_W * 4 */ movl GFXRECT_DATA(%ebx), %edi /* edi = dest_rect->data */ movl GFXRECT_PITCH(%ebx), %ebx /* ebx = dest_rect->pitch */ subl %ecx, %ebx shrl $2, %ecx /* ecx = SCREEN_W */ movd %ecx, %mm7 /* 24 bit to 32 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data */ _align_ next_line_24_to_32: shrl $2, %ecx /* work with packs of 4 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_24_to_32 /* less than 4 pixels? Can't work with the main loop */ #endif _align_ next_block_24_to_32: movq (%esi), %mm0 /* mm0 = [GB2][RGB1][RGB0] */ movd 8(%esi), %mm1 /* mm1 = [..0..][RGB3][R2] */ movq %mm0, %mm2 movq %mm0, %mm3 movq %mm1, %mm4 psllq $16, %mm2 psllq $40, %mm0 psrlq $40, %mm2 psrlq $40, %mm0 /* mm0 = [....0....][RGB0] */ psllq $32, %mm2 /* mm2 = [..][RGB1][..0..] */ psrlq $8, %mm1 psrlq $48, %mm3 /* mm3 = [.....0....][GB2] */ psllq $56, %mm4 psllq $32, %mm1 /* mm1 = [.RGB3][....0...] */ psrlq $40, %mm4 /* mm4 = [....0...][R2][0] */ por %mm3, %mm1 por %mm2, %mm0 /* mm0 = [.RGB1][.RGB0] */ por %mm4, %mm1 /* mm1 = [.RGB3][.RGB2] */ movq %mm0, (%edi) movq %mm1, 8(%edi) addl $12, %esi addl $16, %edi decl %ecx jnz next_block_24_to_32 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_24_to_32: movd %mm7, %ecx /* restore width */ andl $3, %ecx jz end_of_line_24_to_32 /* nothing to do? */ shrl $1, %ecx jnc do_two_pixels_24_to_32 xorl %ecx, %ecx /* partial registar stalls ahead, 6 cycles penalty on the 686 */ movzwl (%esi), %ebp movb 2(%esi), %cl movw %bp, (%edi) movw %cx, 2(%edi) addl $3, %esi addl $4, %edi movd %mm7, %ecx /* restore width */ shrl $1, %ecx do_two_pixels_24_to_32: shrl $1, %ecx jnc end_of_line_24_to_32 movd (%esi), %mm0 /* read 2 pixels */ movzwl 4(%esi), %ecx movd %ecx, %mm1 movq %mm0, %mm2 pslld $8, %mm1 addl $6, %esi pslld $8, %mm0 addl $8, %edi psrld $24, %mm2 psrld $8, %mm0 por %mm2, %mm1 psllq $32, %mm1 por %mm1, %mm0 movq %mm0, -8(%edi) _align_ end_of_line_24_to_32: #endif addl %eax, %esi movd %mm7, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_24_to_32 emms popl %edi popl %esi popl %ebx popl %ebp ret #endif /* ALLEGRO_COLOR24 */ #ifdef ALLEGRO_COLOR32 /* void _colorconv_blit_32_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_32_to_15) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_32_to_15_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi INIT_CONVERSION_1 ($0xf80000, $0x00f800, $0x0000f8); /* 32 bit to 15 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data ebp = SCREEN_W */ _align_ next_line_32_to_15: shrl $1, %ecx /* work with packs of 2 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_32_to_15 /* 1 pixel? Can't use dual-pixel code */ #endif _align_ next_block_32_to_15: movq (%esi), %mm0 movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ psrld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ psrld $6, %mm1 por %mm1, %mm0 addl $8, %esi PAND (4, 2) /* pand %mm4, %mm2 */ psrld $9, %mm2 por %mm2, %mm0 movq %mm0, %mm6 psrlq $16, %mm0 por %mm0, %mm6 movd %mm6, (%edi) addl $4, %edi decl %ecx jnz next_block_32_to_15 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_32_to_15: movl %ebp, %ecx /* restore width */ shrl $1, %ecx jnc end_of_line_32_to_15 movd (%esi), %mm0 movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ psrld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ psrld $6, %mm1 por %mm1, %mm0 addl $4, %esi PAND (4, 2) /* pand %mm4, %mm2 */ psrld $9, %mm2 por %mm2, %mm0 movd %mm0, %ecx movw %cx, (%edi) addl $2, %edi _align_ end_of_line_32_to_15: #endif addl %eax, %esi movl %ebp, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_32_to_15 emms popl %edi popl %esi popl %ebx popl %ebp ret /* void _colorconv_blit_32_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_32_to_16) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_32_to_16_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi INIT_CONVERSION_1 ($0xf80000, $0x00fc00, $0x0000f8); /* 32 bit to 16 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data ebp = SCREEN_W */ _align_ next_line_32_to_16: shrl $1, %ecx /* work with packs of 2 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_32_to_16 /* 1 pixel? Can't use dual-pixel code */ #endif _align_ next_block_32_to_16: movq (%esi), %mm0 movq %mm0, %mm1 nop movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 */ psrld $3, %mm0 PAND (3, 1) /* pand %mm3, %mm1 */ psrld $5, %mm1 por %mm1, %mm0 addl $8, %esi PAND (4, 2) /* pand %mm4, %mm2 */ psrld $8, %mm2 nop nop por %mm2, %mm0 movq %mm0, %mm6 psrlq $16, %mm0 por %mm0, %mm6 movd %mm6, (%edi) addl $4, %edi decl %ecx jnz next_block_32_to_16 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_32_to_16: movl %ebp, %ecx /* restore width */ shrl $1, %ecx jnc end_of_line_32_to_16 movd (%esi), %mm0 movq %mm0, %mm1 movq %mm0, %mm2 PAND (5, 0) /* pand %mm5, %mm0 - get Blue component */ PAND (3, 1) /* pand %mm3, %mm1 - get Red component */ psrld $3, %mm0 /* adjust Red, Green and Blue to correct positions */ PAND (4, 2) /* pand %mm4, %mm2 - get Green component */ psrld $5, %mm1 psrld $8, %mm2 por %mm1, %mm0 /* combine Red and Blue */ addl $4, %esi por %mm2, %mm0 /* and green */ movq %mm0, %mm6 /* make the pixels fit in the first 32 bits */ psrlq $16, %mm0 por %mm0, %mm6 movd %mm6, %ecx movw %cx, (%edi) addl $2, %edi _align_ end_of_line_32_to_16: #endif addl %eax, %esi movl %ebp, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_32_to_16 emms popl %edi popl %esi popl %ebx popl %ebp ret /* void _colorconv_blit_32_to_24 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_32_to_24) movl GLOBL(cpu_capabilities), %eax /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %eax jz _colorconv_blit_32_to_24_no_mmx pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi /* init register values */ movl $0xFFFFFF, %eax /* get RGB mask */ movd %eax, %mm5 /* low RGB mask in mm5 */ movd %eax, %mm6 psllq $32, %mm6 /* high RGB mask in mm6 */ movl ARG1, %eax /* eax = src_rect */ movl GFXRECT_WIDTH(%eax), %ecx /* ecx = src_rect->width */ movl GFXRECT_HEIGHT(%eax), %edx /* edx = src_rect->height */ shll $2, %ecx /* ecx = SCREEN_W * 4 */ movl GFXRECT_DATA(%eax), %esi /* esi = src_rect->data */ movl GFXRECT_PITCH(%eax), %eax /* eax = src_rect->pitch */ subl %ecx, %eax movl ARG2, %ebx /* ebx = dest_rect */ shrl $2, %ecx /* ecx = SCREEN_W */ leal (%ecx, %ecx, 2), %ebp /* ebp = SCREEN_W * 3 */ movl GFXRECT_DATA(%ebx), %edi /* edi = dest_rect->data */ movl GFXRECT_PITCH(%ebx), %ebx /* ebx = dest_rect->pitch */ subl %ebp, %ebx movd %ecx, %mm7 /* 32 bit to 24 bit conversion: we have: eax = offset from the end of a line to the beginning of the next ebx = same as eax, but for the dest bitmap ecx = SCREEN_W edx = SCREEN_H esi = src_rect->data edi = dest_rect->data */ _align_ next_line_32_to_24: shrl $2, %ecx /* work with packs of 4 pixels */ #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH jz do_one_pixel_32_to_24 /* less than 4 pixels? Can't work with the main loop */ #endif _align_ next_block_32_to_24: /* i686: 14 cycles/4 pixels, i586: 11 cycles/4 pixels */ movq (%esi), %mm0 /* mm0 = [ARGBARGB](1)(0) */ addl $12, %edi movq 8(%esi), %mm2 /* mm2 = [ARGBARGB](3)(2) */ addl $16, %esi movq %mm0, %mm1 /* mm1 = [ARGBARGB](1)(0) */ movq %mm2, %mm3 /* mm3 = [ARGBARGB](3)(2) */ pand %mm6, %mm1 /* mm1 = [.RGB....](1) */ pand %mm5, %mm2 /* mm2 = [.....RGB](2) */ psrlq $8, %mm1 /* mm1 = [..RGB...](1) */ pand %mm6, %mm3 /* mm3 = [.RGB....](3) */ movq %mm2, %mm4 /* mm4 = [.....RGB](2) */ pand %mm5, %mm0 /* mm0 = [.....RGB](0) */ psrlq $16, %mm2 /* mm2 = [.......R](2) */ por %mm1, %mm0 /* mm0 = [..RGBRGB](1)(0) */ psrlq $24, %mm3 /* mm3 = [....RGB.](3) */ decl %ecx psllq $48, %mm4 /* mm4 = [GB......](2) */ por %mm3, %mm2 /* mm2 = [....RGBR](3)(2) */ por %mm4, %mm0 /* mm0 = [GBRGBRGB](2)(1)(0) */ movq %mm0, -12(%edi) movd %mm2, -4(%edi) jnz next_block_32_to_24 #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_32_to_24: movd %mm7, %ecx /* restore width */ andl $3, %ecx jz end_of_line_32_to_24 /* nothing to do? */ shrl $1, %ecx jnc do_two_pixels_32_to_24 movl (%esi), %ecx addl $4, %esi movw %cx, (%edi) shrl $16, %ecx addl $3, %edi movb %cl, -1(%edi) movd %mm7, %ecx shrl $1, %ecx /* restore width */ do_two_pixels_32_to_24: shrl $1, %ecx jnc end_of_line_32_to_24 /* 4 cycles/2 pixels */ movq (%esi), %mm0 /* mm0 = [.RGB.RGB](1)(0) */ movq %mm0, %mm1 /* mm1 = [.RGB.RGB](1)(0) */ pand %mm5, %mm0 /* mm0 = [.....RGB](0) */ pand %mm6, %mm1 /* mm1 = [.RGB....](1) */ psrlq $8, %mm1 /* mm1 = [..RGB...](1) */ por %mm1, %mm0 /* mm0 = [..RGBRGB](1)(0) */ movd %mm0, (%edi) psrlq $32, %mm0 movd %mm0, %ecx movw %cx, 2(%edi) addl $8, %esi addl $6, %edi _align_ end_of_line_32_to_24: #endif addl %eax, %esi movd %mm7, %ecx /* restore width */ addl %ebx, %edi decl %edx jnz next_line_32_to_24 emms popl %edi popl %esi popl %ebx popl %ebp ret #endif /* ALLEGRO_COLOR32 */ #endif /* ALLEGRO_MMX */ /********************************************************************************************/ /* pure 386 asm routines */ /* optimized for Intel Pentium */ /********************************************************************************************/ #define RESERVE_MYLOCALS(n) subl $SLOTS_TO_BYTES(n), %esp #define CLEANUP_MYLOCALS(n) addl $SLOTS_TO_BYTES(n), %esp /* create the default stack frame (4 slots) */ #define CREATE_STACK_FRAME \ pushl %ebp ; \ movl %esp, %ebp ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ RESERVE_MYLOCALS(4) #define DESTROY_STACK_FRAME \ CLEANUP_MYLOCALS(4) ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ popl %ebp #define MYLOCAL1 0(%esp) #define MYLOCAL2 4(%esp) #define MYLOCAL3 8(%esp) #define MYLOCAL4 12(%esp) /* create the big stack frame (5 slots) */ #define CREATE_BIG_STACK_FRAME \ pushl %ebp ; \ movl %esp, %ebp ; \ pushl %ebx ; \ pushl %esi ; \ pushl %edi ; \ RESERVE_MYLOCALS(5) #define DESTROY_BIG_STACK_FRAME \ CLEANUP_MYLOCALS(5) ; \ popl %edi ; \ popl %esi ; \ popl %ebx ; \ popl %ebp #define SPILL_SLOT 16(%esp) /* initialize the registers */ #define SIZE_1 #define SIZE_2 addl %ebx, %ebx #define SIZE_3 leal (%ebx,%ebx,2), %ebx #define SIZE_4 shll $2, %ebx #define LOOP_RATIO_1 #define LOOP_RATIO_2 shrl $1, %edi #define LOOP_RATIO_4 shrl $2, %edi #define INIT_REGISTERS_NO_MMX(src_mul_code, dest_mul_code, width_ratio_code) \ movl ARG1, %eax /* eax = src_rect */ ; \ movl GFXRECT_WIDTH(%eax), %ebx /* ebx = src_rect->width */ ; \ movl GFXRECT_HEIGHT(%eax), %edx /* edx = src_rect->height */ ; \ movl GFXRECT_PITCH(%eax), %ecx /* ecx = src_rect->pitch */ ; \ movl %ebx, %edi /* edi = width */ ; \ src_mul_code /* ebx = width*x */ ; \ movl GFXRECT_DATA(%eax), %esi /* esi = src_rect->data */ ; \ subl %ebx, %ecx ; \ movl %edi, %ebx ; \ width_ratio_code ; \ movl ARG2, %eax /* eax = dest_rect */ ; \ movl %edi, MYLOCAL1 /* MYLOCAL1 = width/y */ ; \ movl %ecx, MYLOCAL2 /* MYLOCAL2 = src_rect->pitch - width*x */ ; \ dest_mul_code /* ebx = width*y */ ; \ movl GFXRECT_PITCH(%eax), %ecx /* ecx = dest_rect->pitch */ ; \ subl %ebx, %ecx ; \ movl GFXRECT_DATA(%eax), %edi /* edi = dest_rect->data */ ; \ movl %ecx, MYLOCAL3 /* MYLOCAL3 = dest_rect->pitch - width*y */ ; \ movl %edx, MYLOCAL4 /* MYLOCAL4 = src_rect->height */ /* registers state after initialization: eax: free ebx: free ecx: free (for the inner loop counter) edx: free esi: (char *) source surface pointer edi: (char *) destination surface pointer ebp: free (for the lookup table base pointer) MYLOCAL1: (const int) width/ratio MYLOCAL2: (const int) offset from the end of a line to the beginning of next MYLOCAL3: (const int) same as MYLOCAL2, but for the dest bitmap MYLOCAL4: (int) height */ #define CONV_TRUE_TO_8_NO_MMX(name, bytes_ppixel) \ _align_ ; \ next_line_##name: ; \ movl MYLOCAL1, %ecx ; \ ; \ _align_ ; \ next_block_##name: ; \ xorl %edx, %edx ; \ movb (%esi), %al /* read 1 pixel */ ; \ movb 1(%esi), %bl ; \ movb 2(%esi), %dl ; \ shrb $4, %al ; \ addl $bytes_ppixel, %esi ; \ shll $4, %edx ; \ andb $0xf0, %bl ; \ orb %bl, %al /* combine to get 4.4.4 */ ; \ incl %edi ; \ movb %al, %dl ; \ movb (%ebp, %edx), %dl /* look it up */ ; \ movb %dl, -1(%edi) /* write 1 pixel */ ; \ decl %ecx ; \ jnz next_block_##name ; \ ; \ addl MYLOCAL2, %esi ; \ addl MYLOCAL3, %edi ; \ decl MYLOCAL4 ; \ jnz next_line_##name #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH #define CONV_TRUE_TO_15_NO_MMX(name, bytes_ppixel) \ _align_ ; \ next_line_##name: ; \ movl MYLOCAL1, %ecx ; \ ; \ _align_ ; \ /* 100% Pentium pairable loop */ ; \ /* 11 cycles = 10 cycles/2 pixels + 1 cycle loop */ ; \ next_block_##name: ; \ movb bytes_ppixel(%esi), %al /* al = b8 pixel2 */ ; \ addl $4, %edi /* 2 pixels written */ ; \ shrb $3, %al /* al = b5 pixel2 */ ; \ movb bytes_ppixel+1(%esi), %bh /* ebx = g8 pixel2 << 8 */ ; \ shll $16, %ebx /* ebx = g8 pixel2 << 24 */ ; \ movb bytes_ppixel+2(%esi), %ah /* eax = r8b5 pixel2 */ ; \ shrb $1, %ah /* eax = r7b5 pixel2 */ ; \ movb (%esi), %dl /* dl = b8 pixel1 */ ; \ shrb $3, %dl /* dl = b5 pixel1 */ ; \ movb 1(%esi), %bh /* ebx = g8 pixel2 | g8 pixel1 */ ; \ shll $16, %eax /* eax = r7b5 pixel2 << 16 */ ; \ movb 2(%esi), %dh /* edx = r8b5 pixel1 */ ; \ shrb $1, %dh /* edx = r7b5 pixel1 */ ; \ addl $bytes_ppixel*2, %esi /* 2 pixels read */ ; \ shrl $6, %ebx /* ebx = g5 pixel2 | g5 pixel1 */ ; \ orl %edx, %eax /* eax = r7b5 pixel2 | r7b5 pixel1 */ ; \ andl $0x7c1f7c1f, %eax /* eax = r5b5 pixel2 | r5b5 pixel1 */ ; \ andl $0x03e003e0, %ebx /* clean g5 pixel2 | g5 pixel1 */ ; \ orl %ebx, %eax /* eax = pixel2 | pixel1 */ ; \ decl %ecx ; \ movl %eax, -4(%edi) /* write pixel1..pixel2 */ ; \ jnz next_block_##name ; \ ; \ addl MYLOCAL2, %esi ; \ addl MYLOCAL3, %edi ; \ decl MYLOCAL4 ; \ jnz next_line_##name #define CONV_TRUE_TO_16_NO_MMX(name, bytes_ppixel) \ _align_ ; \ next_line_##name: ; \ movl MYLOCAL1, %ecx ; \ ; \ _align_ ; \ /* 100% Pentium pairable loop */ ; \ /* 10 cycles = 9 cycles/2 pixels + 1 cycle loop */ ; \ next_block_##name: ; \ movb bytes_ppixel(%esi), %al /* al = b8 pixel2 */ ; \ addl $4, %edi /* 2 pixels written */ ; \ shrb $3, %al /* al = b5 pixel2 */ ; \ movb bytes_ppixel+1(%esi), %bh /* ebx = g8 pixel2 << 8 */ ; \ shll $16, %ebx /* ebx = g8 pixel2 << 24 */ ; \ movb (%esi), %dl /* dl = b8 pixel1 */ ; \ shrb $3, %dl /* dl = b5 pixel1 */ ; \ movb bytes_ppixel+2(%esi), %ah /* eax = r8b5 pixel2 */ ; \ shll $16, %eax /* eax = r8b5 pixel2 << 16 */ ; \ movb 1(%esi), %bh /* ebx = g8 pixel2 | g8 pixel1 */ ; \ shrl $5, %ebx /* ebx = g6 pixel2 | g6 pixel1 */ ; \ movb 2(%esi), %dh /* edx = r8b5 pixel1 */ ; \ orl %edx, %eax /* eax = r8b5 pixel2 | r8b5 pixel1 */ ; \ addl $bytes_ppixel*2, %esi /* 2 pixels read */ ; \ andl $0xf81ff81f, %eax /* eax = r5b5 pixel2 | r5b5 pixel1 */ ; \ andl $0x07e007e0, %ebx /* clean g6 pixel2 | g6 pixel1 */ ; \ orl %ebx, %eax /* eax = pixel2 | pixel1 */ ; \ decl %ecx ; \ movl %eax, -4(%edi) /* write pixel1..pixel2 */ ; \ jnz next_block_##name ; \ ; \ addl MYLOCAL2, %esi ; \ addl MYLOCAL3, %edi ; \ decl MYLOCAL4 ; \ jnz next_line_##name #else #define CONV_TRUE_TO_15_NO_MMX(name, bytes_ppixel) \ _align_ ; \ next_line_##name: ; \ movl MYLOCAL1, %ecx ; \ ; \ shrl $1, %ecx ; \ jz do_one_pixel_##name ; \ ; \ _align_ ; \ /* 100% Pentium pairable loop */ ; \ /* 11 cycles = 10 cycles/2 pixels + 1 cycle loop */ ; \ next_block_##name: ; \ movb bytes_ppixel(%esi), %al /* al = b8 pixel2 */ ; \ addl $4, %edi /* 2 pixels written */ ; \ shrb $3, %al /* al = b5 pixel2 */ ; \ movb bytes_ppixel+1(%esi), %bh /* ebx = g8 pixel2 << 8 */ ; \ shll $16, %ebx /* ebx = g8 pixel2 << 24 */ ; \ movb bytes_ppixel+2(%esi), %ah /* eax = r8b5 pixel2 */ ; \ shrb $1, %ah /* eax = r7b5 pixel2 */ ; \ movb (%esi), %dl /* dl = b8 pixel1 */ ; \ shrb $3, %dl /* dl = b5 pixel1 */ ; \ movb 1(%esi), %bh /* ebx = g8 pixel2 | g8 pixel1 */ ; \ shll $16, %eax /* eax = r7b5 pixel2 << 16 */ ; \ movb 2(%esi), %dh /* edx = r8b5 pixel1 */ ; \ shrb $1, %dh /* edx = r7b5 pixel1 */ ; \ addl $bytes_ppixel*2, %esi /* 2 pixels read */ ; \ shrl $6, %ebx /* ebx = g5 pixel2 | g5 pixel1 */ ; \ orl %edx, %eax /* eax = r7b5 pixel2 | r7b5 pixel1 */ ; \ andl $0x7c1f7c1f, %eax /* eax = r5b5 pixel2 | r5b5 pixel1 */ ; \ andl $0x03e003e0, %ebx /* clean g5 pixel2 | g5 pixel1 */ ; \ orl %ebx, %eax /* eax = pixel2 | pixel1 */ ; \ decl %ecx ; \ movl %eax, -4(%edi) /* write pixel1..pixel2 */ ; \ jnz next_block_##name ; \ ; \ do_one_pixel_##name: ; \ movl MYLOCAL1, %ecx ; \ shrl $1, %ecx ; \ jnc end_of_line_##name ; \ ; \ movb (%esi), %cl /* cl = b8 pixel1 */ ; \ addl $2, %edi ; \ shrb $3, %cl /* cl = b5 pixel1 */ ; \ movb 1(%esi), %bh /* ebx = g8 pixel1 */ ; \ shrl $6, %ebx /* ebx = g5 pixel1 */ ; \ movb 2(%esi), %ch /* ecx = r8b5 pixel1 */ ; \ shrb $1, %ch /* ecx = r7b5 pixel1 */ ; \ addl $bytes_ppixel, %esi /* 1 pixel read */ ; \ andl $0x7c1f, %ecx /* ecx = r5b5 pixel1 */ ; \ andl $0x03e0, %ebx /* clean g5 pixel1 */ ; \ orl %ebx, %ecx /* edx = pixel1 */ ; \ movw %cx, -2(%edi) /* write pixel1 */ ; \ ; \ _align_ ; \ end_of_line_##name: ; \ addl MYLOCAL2, %esi ; \ addl MYLOCAL3, %edi ; \ decl MYLOCAL4 ; \ jnz next_line_##name #define CONV_TRUE_TO_16_NO_MMX(name, bytes_ppixel) \ _align_ ; \ next_line_##name: ; \ movl MYLOCAL1, %ecx ; \ ; \ shrl $1, %ecx ; \ jz do_one_pixel_##name ; \ ; \ _align_ ; \ /* 100% Pentium pairable loop */ ; \ /* 10 cycles = 9 cycles/2 pixels + 1 cycle loop */ ; \ next_block_##name: ; \ movb bytes_ppixel(%esi), %al /* al = b8 pixel2 */ ; \ addl $4, %edi /* 2 pixels written */ ; \ shrb $3, %al /* al = b5 pixel2 */ ; \ movb bytes_ppixel+1(%esi), %bh /* ebx = g8 pixel2 << 8 */ ; \ shll $16, %ebx /* ebx = g8 pixel2 << 24 */ ; \ movb (%esi), %dl /* dl = b8 pixel1 */ ; \ shrb $3, %dl /* dl = b5 pixel1 */ ; \ movb bytes_ppixel+2(%esi), %ah /* eax = r8b5 pixel2 */ ; \ shll $16, %eax /* eax = r8b5 pixel2 << 16 */ ; \ movb 1(%esi), %bh /* ebx = g8 pixel2 | g8 pixel1 */ ; \ shrl $5, %ebx /* ebx = g6 pixel2 | g6 pixel1 */ ; \ movb 2(%esi), %dh /* edx = r8b5 pixel1 */ ; \ orl %edx, %eax /* eax = r8b5 pixel2 | r8b5 pixel1 */ ; \ addl $bytes_ppixel*2, %esi /* 2 pixels read */ ; \ andl $0xf81ff81f, %eax /* eax = r5b5 pixel2 | r5b5 pixel1 */ ; \ andl $0x07e007e0, %ebx /* clean g6 pixel2 | g6 pixel1 */ ; \ orl %ebx, %eax /* eax = pixel2 | pixel1 */ ; \ decl %ecx ; \ movl %eax, -4(%edi) /* write pixel1..pixel2 */ ; \ jnz next_block_##name ; \ ; \ do_one_pixel_##name: ; \ movl MYLOCAL1, %ecx ; \ shrl $1, %ecx ; \ jnc end_of_line_##name ; \ ; \ movb (%esi), %cl /* cl = b8 pixel1 */ ; \ addl $2, %edi ; \ shrb $3, %cl /* cl = b5 pixel1 */ ; \ movb 1(%esi), %bh /* ebx = g8 pixel1 */ ; \ shrl $5, %ebx /* ebx = g6 pixel1 */ ; \ movb 2(%esi), %ch /* ecx = r8b5 pixel1 */ ; \ addl $bytes_ppixel, %esi /* 1 pixel read */ ; \ andl $0xf81f, %ecx /* ecx = r5b5 pixel1 */ ; \ andl $0x07e0, %ebx /* clean g6 pixel1 */ ; \ orl %ebx, %ecx /* edx = pixel1 */ ; \ movw %cx, -2(%edi) /* write pixel1 */ ; \ ; \ _align_ ; \ end_of_line_##name: ; \ addl MYLOCAL2, %esi ; \ addl MYLOCAL3, %edi ; \ decl MYLOCAL4 ; \ jnz next_line_##name #endif /* ALLEGRO_COLORCONV_ALIGNED_WIDTH */ #ifdef ALLEGRO_COLOR8 /* void _colorconv_blit_8_to_8 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_8_to_8) CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_1, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_1, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_rgb_map), %ebp _align_ next_line_8_to_8_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx /* work in packs of 4 pixels */ jz do_one_pixel_8_to_8_no_mmx #endif _align_ next_block_8_to_8_no_mmx: movl (%esi), %eax /* read 4 pixels */ xorl %ebx, %ebx xorl %edx, %edx addl $4, %esi addl $4, %edi movb %al, %bl /* pick out 2x bottom 8 bits */ movb %ah, %dl shrl $16, %eax movb (%ebp, %ebx), %bl /* lookup the new palette entries */ movb (%ebp, %edx), %bh xorl %edx, %edx movb %ah, %dl /* repeat for the top 16 bits */ andl $0xff, %eax movb (%ebp, %eax), %al movb (%ebp, %edx), %ah shll $16, %eax orl %ebx, %eax /* put everything together */ movl %eax, -4(%edi) /* write 4 pixels */ decl %ecx jnz next_block_8_to_8_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_8_to_8_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_8_to_8_no_mmx shrl $1, %ecx jnc do_two_pixels_8_to_8_no_mmx xorl %eax, %eax movb (%esi), %al /* read 1 pixel */ incl %edi incl %esi movb (%ebp, %eax), %al /* lookup the new palette entry */ movb %al, -1(%edi) /* write 1 pixel */ do_two_pixels_8_to_8_no_mmx: shrl $1, %ecx jnc end_of_line_8_to_8_no_mmx xorl %eax, %eax xorl %ebx, %ebx movb (%esi), %al /* read 2 pixels */ movb 1(%esi), %bl addl $2, %edi addl $2, %esi movb (%ebp, %eax), %al /* lookup the new palette entry */ movb (%ebp, %ebx), %bl movb %al, -2(%edi) /* write 2 pixels */ movb %bl, -1(%edi) _align_ end_of_line_8_to_8_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_8_to_8_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_8_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ /* void _colorconv_blit_8_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_8_to_16_no_mmx: #else FUNC (_colorconv_blit_8_to_15) FUNC (_colorconv_blit_8_to_16) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_2, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_2, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_indexed_palette), %ebp xorl %eax, %eax /* init first line */ _align_ next_line_8_to_16_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_8_to_16_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 10 cycles = 9 cycles/4 pixels + 1 cycle loop */ next_block_8_to_16_no_mmx: xorl %ebx, %ebx movb (%esi), %al /* al = pixel1 */ xorl %edx, %edx movb 1(%esi), %bl /* bl = pixel2 */ movb 2(%esi), %dl /* dl = pixel3 */ movl (%ebp,%eax,4), %eax /* lookup: ax = pixel1 */ movl 1024(%ebp,%ebx,4), %ebx /* lookup: bx = pixel2 */ addl $4, %esi /* 4 pixels read */ orl %ebx, %eax /* eax = pixel2..pixel1 */ xorl %ebx, %ebx movl %eax, (%edi) /* write pixel1, pixel2 */ movb -1(%esi), %bl /* bl = pixel4 */ movl (%ebp,%edx,4), %edx /* lookup: dx = pixel3 */ xorl %eax, %eax movl 1024(%ebp,%ebx,4), %ebx /* lookup: bx = pixel4 */ addl $8, %edi /* 4 pixels written */ orl %ebx, %edx /* edx = pixel4..pixel3 */ decl %ecx movl %edx, -4(%edi) /* write pixel3, pixel4 */ jnz next_block_8_to_16_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_8_to_16_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_8_to_16_no_mmx shrl $1, %ecx jnc do_two_pixels_8_to_16_no_mmx xorl %eax, %eax incl %esi movb -1(%esi), %al movl (%ebp, %eax, 4), %ebx addl $2, %edi xorl %eax, %eax movw %bx, -2(%edi) do_two_pixels_8_to_16_no_mmx: shrl $1, %ecx jnc end_of_line_8_to_16_no_mmx xorl %ebx, %ebx movb (%esi), %al movb 1(%esi), %bl addl $2, %esi movl (%ebp, %eax, 4), %eax movl 1024(%ebp, %ebx, 4), %ebx addl $4, %edi orl %eax, %ebx xorl %eax, %eax movl %ebx, -4(%edi) _align_ end_of_line_8_to_16_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_8_to_16_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_8_to_24 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_8_to_24) CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_3, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_3, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_indexed_palette), %ebp xorl %eax, %eax /* init first line */ _align_ next_line_8_to_24_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_8_to_24_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 12 cycles = 11 cycles/4 pixels + 1 cycle loop */ next_block_8_to_24_no_mmx: xorl %ebx, %ebx movb 3(%esi), %al /* al = pixel4 */ movb 2(%esi), %bl /* bl = pixel3 */ xorl %edx, %edx movl 3072(%ebp,%eax,4), %eax /* lookup: eax = pixel4 << 8 */ movb 1(%esi), %dl /* dl = pixel 2 */ movl 2048(%ebp,%ebx,4), %ebx /* lookup: ebx = g8b800r8 pixel3 */ addl $12, %edi /* 4 pixels written */ movl 1024(%ebp,%edx,4), %edx /* lookup: edx = b800r8g8 pixel2 */ movb %bl, %al /* eax = pixel4 << 8 | r8 pixel3 */ movl %eax, -4(%edi) /* write r8 pixel3..pixel4 */ xorl %eax, %eax movb %dl, %bl /* ebx = g8b8 pixel3 | 00g8 pixel2 */ movb (%esi), %al /* al = pixel1 */ movb %dh, %bh /* ebx = g8b8 pixel3 | r8g8 pixel2 */ andl $0xff000000, %edx /* edx = b8 pixel2 << 24 */ movl %ebx, -8(%edi) /* write g8r8 pixel2..b8g8 pixel3 */ movl (%ebp,%eax,4), %eax /* lookup: eax = pixel1 */ orl %eax, %edx /* edx = b8 pixel2 << 24 | pixel1 */ xorl %eax, %eax movl %edx, -12(%edi) /* write pixel1..b8 pixel2 */ addl $4, %esi /* 4 pixels read */ decl %ecx jnz next_block_8_to_24_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_8_to_24_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_8_to_24_no_mmx shrl $1, %ecx jnc do_two_pixels_8_to_24_no_mmx xorl %eax, %eax movb (%esi), %al /* al = pixel1 */ incl %esi movl (%ebp,%eax,4), %eax /* lookup: eax = pixel1 */ movw %ax, (%edi) shrl $16, %eax addl $3, %edi movb %al, -1(%edi) xorl %eax, %eax do_two_pixels_8_to_24_no_mmx: shrl $1, %ecx jnc end_of_line_8_to_24_no_mmx xorl %ebx, %ebx movb (%esi), %al /* al = pixel1 */ movb 1(%esi), %bl /* bl = pixel2 */ addl $2, %esi movl (%ebp,%eax,4), %eax /* lookup: eax = pixel1 */ movl (%ebp,%ebx,4), %ebx /* lookup: ebx = pixel2 */ movl %eax, (%edi) /* write pixel1 */ movw %bx, 3(%edi) shrl $16, %ebx addl $6, %edi movb %bl, -1(%edi) xorl %eax, %eax _align_ end_of_line_8_to_24_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_8_to_24_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_8_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_8_to_32_no_mmx: #else FUNC (_colorconv_blit_8_to_32) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_4, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_1, SIZE_4, LOOP_RATIO_1) #endif xorl %eax, %eax /* init first line */ movl GLOBL(_colorconv_indexed_palette), %ebp _align_ next_line_8_to_32_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_8_to_32_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 10 cycles = 9 cycles/4 pixels + 1 cycle loop */ next_block_8_to_32_no_mmx: movb (%esi), %al /* al = pixel1 */ xorl %ebx, %ebx movb 1(%esi), %bl /* bl = pixel2 */ xorl %edx, %edx movl (%ebp,%eax,4), %eax /* lookup: eax = pixel1 */ movb 2(%esi), %dl /* dl = pixel3 */ movl %eax, (%edi) /* write pixel1 */ movl (%ebp,%ebx,4), %ebx /* lookup: ebx = pixel2 */ xorl %eax, %eax movl (%ebp,%edx,4), %edx /* lookup: edx = pixel3 */ movl %ebx, 4(%edi) /* write pixel2 */ movb 3(%esi), %al /* al = pixel4 */ movl %edx, 8(%edi) /* write pixel3 */ addl $16, %edi /* 4 pixels written */ movl (%ebp,%eax,4), %eax /* lookup: eax = pixel4 */ addl $4, %esi /* 4 pixels read */ movl %eax, -4(%edi) /* write pixel4 */ xorl %eax, %eax decl %ecx jnz next_block_8_to_32_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_8_to_32_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_8_to_32_no_mmx shrl $1, %ecx jnc do_two_pixels_8_to_32_no_mmx movb (%esi), %al /* read one pixel */ incl %esi movl (%ebp,%eax,4), %ebx /* lookup: ebx = pixel */ addl $4, %edi xorl %eax, %eax movl %ebx, -4(%edi) /* write pixel */ do_two_pixels_8_to_32_no_mmx: shrl $1, %ecx jnc end_of_line_8_to_32_no_mmx movb (%esi), %al /* read one pixel */ xorl %ebx, %ebx addl $2, %esi movb -1(%esi), %bl /* read another pixel */ movl (%ebp,%eax,4), %ecx /* lookup: ecx = pixel */ movl (%ebp,%ebx,4), %ebx /* lookup: ebx = pixel */ addl $8, %edi xorl %eax, %eax movl %ecx, -8(%edi) /* write pixel */ movl %ebx, -4(%edi) /* write pixel */ _align_ end_of_line_8_to_32_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_8_to_32_no_mmx DESTROY_STACK_FRAME ret #endif /* ALLEGRO_COLOR8 */ #ifdef ALLEGRO_COLOR16 /* void _colorconv_blit_15_to_8 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_15_to_8) CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_1, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_1, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_rgb_map), %ebp _align_ next_line_15_to_8_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $1, %ecx /* work in packs of 2 pixels */ jz do_one_pixel_15_to_8_no_mmx #endif _align_ next_block_15_to_8_no_mmx: movl (%esi), %eax /* read 2 pixels */ addl $4, %esi addl $2, %edi movl %eax, %ebx /* get bottom 16 bits */ movl %eax, %edx andl $0x781e, %ebx andl $0x03c0, %edx shrb $1, %bl /* shift to correct positions */ shrb $3, %bh shrl $2, %edx shrl $16, %eax orl %edx, %ebx /* combine to get a 4.4.4 number */ movl %eax, %edx movb (%ebp, %ebx), %bl /* look it up */ andl $0x781f, %eax andl $0x03c0, %edx shrb $1, %al /* shift to correct positions */ shrb $3, %ah shrl $2, %edx orl %edx, %eax /* combine to get a 4.4.4 number */ movb (%ebp, %eax), %bh /* look it up */ movw %bx, -2(%edi) /* write 2 pixels */ decl %ecx jnz next_block_15_to_8_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_15_to_8_no_mmx: movl MYLOCAL1, %ecx shrl $1, %ecx jnc end_of_line_15_to_8_no_mmx xorl %eax, %eax movw (%esi), %ax /* read 1 pixel */ addl $2, %esi incl %edi movl %eax, %ebx andl $0x781e, %ebx andl $0x03c0, %eax shrb $1, %bl /* shift to correct positions */ shrb $3, %bh shrl $2, %eax orl %eax, %ebx /* combine to get a 4.4.4 number */ movb (%ebp, %ebx), %bl /* look it up */ movb %bl, -1(%edi) /* write 1 pixel */ _align_ end_of_line_15_to_8_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_15_to_8_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_15_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_15_to_16_no_mmx: #else FUNC (_colorconv_blit_15_to_16) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_2, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_2, LOOP_RATIO_1) #endif _align_ next_line_15_to_16_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_15_to_16_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 10 cycles = 9 cycles/4 pixels + 1 cycle loop */ next_block_15_to_16_no_mmx: movl (%esi), %eax /* eax = pixel2 | pixel1 */ addl $8, %edi /* 4 pixels written */ movl %eax, %ebx /* ebx = pixel2 | pixel1 */ andl $0x7fe07fe0, %eax /* eax = r5g5b0 | r5g5b0 */ shll $1, %eax /* eax = r5g6b0 | r5g6b0 */ andl $0x001f001f, %ebx /* ebx = r0g0b5 | r0g0b5 */ orl %ebx, %eax /* eax = r5g6b5 | r5g6b5 */ movl 4(%esi), %edx /* edx = pixel4 | pixel3 */ movl %edx, %ebx /* ebx = pixel4 | pixel3 */ andl $0x7fe07fe0, %edx /* edx = r5g5b0 | r5g5b0 */ shll $1, %edx /* edx = r5g6b0 | r5g6b0 */ andl $0x001f001f, %ebx /* ebx = r0g0b5 | r0g0b5 */ orl %ebx, %edx /* edx = r5g6b5 | r5g6b5 */ orl $0x00200020, %eax /* green gamma correction */ movl %eax, -8(%edi) /* write pixel1..pixel2 */ orl $0x00200020, %edx /* green gamma correction */ movl %edx, -4(%edi) /* write pixel3..pixel4 */ addl $8, %esi /* 4 pixels read */ decl %ecx jnz next_block_15_to_16_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_15_to_16_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_15_to_16_no_mmx shrl $1, %ecx jnc do_two_pixels_15_to_16_no_mmx xorl %eax, %eax movw (%esi), %ax addl $2, %edi movl %eax, %ebx andl $0x7fe0, %eax andl $0x001f, %ebx shll $1, %eax addl $2, %esi orl $0x0020, %eax orl %ebx, %eax movw %ax, -2(%edi) do_two_pixels_15_to_16_no_mmx: shrl $1, %ecx jnc end_of_line_15_to_16_no_mmx movl (%esi), %eax addl $4, %edi movl %eax, %ebx andl $0x7fe07fe0, %eax andl $0x001f001f, %ebx shll $1, %eax addl $4, %esi orl $0x00200020, %eax orl %ebx, %eax movl %eax, -4(%edi) _align_ end_of_line_15_to_16_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_15_to_16_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_15_to_24 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ /* void _colorconv_blit_16_to_24 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_15_to_24) FUNC (_colorconv_blit_16_to_24) CREATE_BIG_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_3, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_3, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_rgb_scale_5x35), %ebp next_line_16_to_24_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_16_to_24_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 22 cycles = 20 cycles/4 pixels + 1 cycle stack + 1 cycle loop */ next_block_16_to_24_no_mmx: movl %ecx, SPILL_SLOT /* spill %ecx to the stack */ xorl %ebx, %ebx xorl %eax, %eax movb 7(%esi), %bl /* bl = high byte pixel4 */ xorl %edx, %edx movb 6(%esi), %al /* al = low byte pixel4 */ movl (%ebp,%ebx,4), %ebx /* lookup: ebx = r8g8b0 pixel4 */ movb 4(%esi), %dl /* dl = low byte pixel3 */ movl 1024(%ebp,%eax,4), %eax /* lookup: eax = r0g8b8 pixel4 */ xorl %ecx, %ecx addl %ebx, %eax /* eax = r8g8b8 pixel4 */ movb 5(%esi), %cl /* cl = high byte pixel3 */ shll $8, %eax /* eax = r8g8b8 pixel4 << 8 */ movl 5120(%ebp,%edx,4), %edx /* lookup: edx = g8b800r0 pixel3 */ movl 4096(%ebp,%ecx,4), %ecx /* lookup: ecx = g8b000r8 pixel3 */ xorl %ebx, %ebx addl %ecx, %edx /* edx = g8b800r8 pixel3 */ movb %cl, %al /* eax = pixel4 << 8 | r8 pixel3 */ movl %eax, 8(%edi) /* write r8 pixel3..pixel4 */ movb 3(%esi), %bl /* bl = high byte pixel2 */ xorl %eax, %eax xorl %ecx, %ecx movb 2(%esi), %al /* al = low byte pixel2 */ movl 2048(%ebp,%ebx,4), %ebx /* lookup: ebx = b000r8g8 pixel2 */ movb 1(%esi), %cl /* cl = high byte pixel1 */ addl $12, %edi /* 4 pixels written */ movl 3072(%ebp,%eax,4), %eax /* lookup: eax = b800r0g8 pixel2 */ addl $8, %esi /* 4 pixels read */ addl %ebx, %eax /* eax = b800r8g8 pixel2 */ movl (%ebp,%ecx,4), %ecx /* lookup: ecx = r8g8b0 pixel1 */ movb %al, %dl /* edx = g8b8 pixel3 | 00g8 pixel2 */ xorl %ebx, %ebx movb %ah, %dh /* edx = g8b8 pixel3 | r8g8 pixel2 */ movb -8(%esi), %bl /* bl = low byte pixel1 */ movl %edx, -8(%edi) /* write g8r8 pixel2..b8g8 pixel3 */ andl $0xff000000, %eax /* eax = b8 pixel2 << 24 */ movl 1024(%ebp,%ebx,4), %ebx /* lookup: ebx = r0g8b8 pixel1 */ /* nop */ addl %ecx, %ebx /* ebx = r8g8b8 pixel1 */ movl SPILL_SLOT, %ecx /* restore %ecx */ orl %ebx, %eax /* eax = b8 pixel2 << 24 | pixel1 */ decl %ecx movl %eax, -12(%edi) /* write pixel1..b8 pixel2 */ jnz next_block_16_to_24_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_16_to_24_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_16_to_24_no_mmx shrl $1, %ecx jnc do_two_pixels_16_to_24_no_mmx xorl %eax, %eax xorl %ebx, %ebx movb 1(%esi), %al /* al = high byte pixel1 */ addl $3, %edi /* 1 pixel written */ addl $2, %esi /* 1 pixel read */ movl (%ebp,%eax,4), %eax /* lookup: eax = r8g8b0 pixel1 */ movb -2(%esi), %bl /* bl = low byte pixel1 */ movl 1024(%ebp,%ebx,4), %ebx /* lookup: ebx = r0g8b8 pixel1 */ addl %eax, %ebx /* ebx = r8g8b8 pixel1 */ movw %bx, -3(%edi) shrl $16, %ebx movb %bl, -1(%edi) do_two_pixels_16_to_24_no_mmx: shrl $1, %ecx jnc end_of_line_16_to_24_no_mmx xorl %eax, %eax xorl %ebx, %ebx movb 1(%esi), %al /* al = high byte pixel1 */ addl $6, %edi /* 1 pixel written */ addl $4, %esi /* 1 pixel read */ movl (%ebp,%eax,4), %eax /* lookup: eax = r8g8b0 pixel1 */ movb -4(%esi), %bl /* bl = low byte pixel1 */ movl 1024(%ebp,%ebx,4), %ebx /* lookup: ebx = r0g8b8 pixel1 */ addl %eax, %ebx /* ebx = r8g8b8 pixel1 */ xorl %eax, %eax movl %ebx, -6(%edi) /* write pixel1 */ movb -1(%esi), %al /* al = high byte pixel2 */ xorl %ebx, %ebx movl (%ebp,%eax,4), %eax /* lookup: eax = r8g8b0 pixel2 */ movb -2(%esi), %bl /* bl = low byte pixel2 */ movl 1024(%ebp,%ebx,4), %ebx /* lookup: ebx = r0g8b8 pixel2 */ addl %eax, %ebx /* ebx = r8g8b8 pixel2 */ movw %bx, -3(%edi) /* write pixel2 */ shrl $16, %ebx movb %bl, -1(%edi) _align_ end_of_line_16_to_24_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_16_to_24_no_mmx DESTROY_BIG_STACK_FRAME ret /* void _colorconv_blit_15_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ /* void _colorconv_blit_16_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_15_to_32_no_mmx: _colorconv_blit_16_to_32_no_mmx: #else FUNC (_colorconv_blit_15_to_32) FUNC (_colorconv_blit_16_to_32) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_4, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_4, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_rgb_scale_5x35), %ebp xorl %eax, %eax /* init first line */ _align_ next_line_16_to_32_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $1, %ecx jz do_one_pixel_16_to_32_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 10 cycles = 9 cycles/2 pixels + 1 cycle loop */ next_block_16_to_32_no_mmx: xorl %ebx, %ebx movb (%esi), %al /* al = low byte pixel1 */ xorl %edx, %edx movb 1(%esi), %bl /* bl = high byte pixel1 */ movl 1024(%ebp,%eax,4), %eax /* lookup: eax = r0g8b8 pixel1 */ movb 2(%esi), %dl /* dl = low byte pixel2 */ movl (%ebp,%ebx,4), %ebx /* lookup: ebx = r8g8b0 pixel1 */ addl $8, %edi /* 2 pixels written */ addl %ebx, %eax /* eax = r8g8b8 pixel1 */ xorl %ebx, %ebx movl 1024(%ebp,%edx,4), %edx /* lookup: edx = r0g8b8 pixel2 */ movb 3(%esi), %bl /* bl = high byte pixel2 */ movl %eax, -8(%edi) /* write pixel1 */ xorl %eax, %eax movl (%ebp,%ebx,4), %ebx /* lookup: ebx = r8g8b0 pixel2 */ addl $4, %esi /* 4 pixels read */ addl %ebx, %edx /* edx = r8g8b8 pixel2 */ decl %ecx movl %edx, -4(%edi) /* write pixel2 */ jnz next_block_16_to_32_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_16_to_32_no_mmx: movl MYLOCAL1, %ecx /* restore width */ shrl $1, %ecx jnc end_of_line_16_to_32_no_mmx xorl %ebx, %ebx movb (%esi), %al /* al = low byte pixel1 */ addl $4, %edi /* 2 pixels written */ movb 1(%esi), %bl /* bl = high byte pixel1 */ movl 1024(%ebp,%eax,4), %eax /* lookup: eax = r0g8b8 pixel1 */ movl (%ebp,%ebx,4), %ebx /* lookup: ebx = r8g8b0 pixel1 */ addl $2, %esi addl %eax, %ebx /* ebx = r8g8b8 pixel1 */ xorl %eax, %eax movl %ebx, -4(%edi) /* write pixel1 */ _align_ end_of_line_16_to_32_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_16_to_32_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_16_to_8 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_16_to_8) CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_1, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_1, LOOP_RATIO_1) #endif movl GLOBL(_colorconv_rgb_map), %ebp _align_ next_line_16_to_8_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $1, %ecx /* work in packs of 2 pixels */ jz do_one_pixel_16_to_8_no_mmx #endif _align_ next_block_16_to_8_no_mmx: movl (%esi), %eax /* read 2 pixels */ addl $4, %esi addl $2, %edi movl %eax, %ebx /* get bottom 16 bits */ movl %eax, %edx andl $0xf01e, %ebx andl $0x0780, %edx shrb $1, %bl /* shift to correct positions */ shrb $4, %bh shrl $3, %edx shrl $16, %eax orl %edx, %ebx /* combine to get a 4.4.4 number */ movl %eax, %edx movb (%ebp, %ebx), %bl /* look it up */ andl $0xf01e, %eax andl $0x0780, %edx shrb $1, %al /* shift to correct positions */ shrb $4, %ah shrl $3, %edx orl %edx, %eax /* combine to get a 4.4.4 number */ movb (%ebp, %eax), %bh /* look it up */ movw %bx, -2(%edi) /* write 2 pixels */ decl %ecx jnz next_block_16_to_8_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_16_to_8_no_mmx: movl MYLOCAL1, %ecx shrl $1, %ecx jnc end_of_line_16_to_8_no_mmx xorl %eax, %eax movw (%esi), %ax /* read 1 pixel */ addl $2, %esi incl %edi movl %eax, %ebx andl $0xf01e, %ebx andl $0x0780, %eax shrb $1, %bl /* shift to correct positions */ shrb $4, %bh shrl $3, %eax orl %eax, %ebx /* combine to get a 4.4.4 number */ movb (%ebp, %ebx), %bl /* look it up */ movb %bl, -1(%edi) /* write 1 pixel */ _align_ end_of_line_16_to_8_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_16_to_8_no_mmx DESTROY_STACK_FRAME ret /* void _colorconv_blit_16_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_16_to_15_no_mmx: #else FUNC (_colorconv_blit_16_to_15) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_2, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_2, SIZE_2, LOOP_RATIO_1) #endif _align_ next_line_16_to_15_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_16_to_15_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 9 cycles = 8 cycles/4 pixels + 1 cycle loop */ next_block_16_to_15_no_mmx: movl (%esi), %eax /* eax = pixel2 | pixel1 */ addl $8, %edi /* 4 pixels written */ movl %eax, %ebx /* ebx = pixel2 | pixel1 */ andl $0xffc0ffc0, %eax /* eax = r5g6b0 | r5g6b0 */ shrl $1, %eax /* eax = r5g5b0 | r5g5b0 */ andl $0x001f001f, %ebx /* ebx = r0g0b5 | r0g0b5 */ orl %ebx, %eax /* eax = r5g5b5 | r5g5b5 */ movl 4(%esi), %edx /* edx = pixel4 | pixel3 */ movl %edx, %ebx /* ebx = pixel4 | pixel3 */ andl $0xffc0ffc0, %edx /* edx = r5g6b0 | r5g6b0 */ shrl $1, %edx /* edx = r5g5b0 | r5g5b0 */ andl $0x001f001f, %ebx /* ebx = r0g0b5 | r0g0b5 */ movl %eax, -8(%edi) /* write pixel1..pixel2 */ orl %ebx, %edx /* edx = r5g5b5 | r5g5b5 */ movl %edx, -4(%edi) /* write pixel3..pixel4 */ addl $8, %esi /* 4 pixels read */ decl %ecx jnz next_block_16_to_15_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_16_to_15_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_16_to_15_no_mmx shrl $1, %ecx jnc do_two_pixels_16_to_15_no_mmx xorl %eax, %eax movw (%esi), %ax addl $2, %edi movl %eax, %ebx andl $0xffc0ffc0, %eax andl $0x001f001f, %ebx shrl $1, %eax addl $2, %esi orl %ebx, %eax movw %ax, -2(%edi) do_two_pixels_16_to_15_no_mmx: shrl $1, %ecx jnc end_of_line_16_to_15_no_mmx movl (%esi), %eax addl $4, %edi movl %eax, %ebx andl $0xffc0ffc0, %eax andl $0x001f001f, %ebx shrl $1, %eax addl $4, %esi orl %ebx, %eax movl %eax, -4(%edi) _align_ end_of_line_16_to_15_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_16_to_15_no_mmx DESTROY_STACK_FRAME ret #endif /* ALLEGRO_COLOR16 */ #ifdef ALLEGRO_COLOR24 /* void _colorconv_blit_24_to_8 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_24_to_8) CREATE_STACK_FRAME INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_1, LOOP_RATIO_1) movl GLOBL(_colorconv_rgb_map), %ebp CONV_TRUE_TO_8_NO_MMX(24_to_8_no_mmx, 3) DESTROY_STACK_FRAME ret /* void _colorconv_blit_24_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_24_to_15) CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_2, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_2, LOOP_RATIO_1) #endif CONV_TRUE_TO_15_NO_MMX(24_to_15_no_mmx, 3) DESTROY_STACK_FRAME ret /* void _colorconv_blit_24_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_24_to_16) CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_2, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_2, LOOP_RATIO_1) #endif CONV_TRUE_TO_16_NO_MMX(24_to_16_no_mmx, 3) DESTROY_STACK_FRAME ret /* void _colorconv_blit_24_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_24_to_32_no_mmx: #else FUNC (_colorconv_blit_24_to_32) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_4, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_3, SIZE_4, LOOP_RATIO_1) #endif _align_ next_line_24_to_32_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_24_to_32_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 9 cycles = 8 cycles/4 pixels + 1 cycle loop */ next_block_24_to_32_no_mmx: movl 4(%esi), %ebx /* ebx = r8g8 pixel2 */ movl (%esi), %eax /* eax = pixel1 */ shll $8, %ebx /* ebx = r8g8b0 pixel2 */ movl 8(%esi), %edx /* edx = pixel4 | r8 pixel 3 */ movl %eax, (%edi) /* write pixel1 */ movb 3(%esi), %bl /* ebx = pixel2 */ movl %edx, %eax /* eax = r8 pixel3 */ movl %ebx, 4(%edi) /* write pixel2 */ shll $16, %eax /* eax = r8g0b0 pixel3 */ addl $16, %edi /* 4 pixels written */ shrl $8, %edx /* edx = pixel4 */ movb 6(%esi), %al /* eax = r8g0b8 pixel3 */ movl %edx, -4(%edi) /* write pixel4 */ movb 7(%esi), %ah /* eax = r8g8b8 pixel3 */ movl %eax, -8(%edi) /* write pixel3 */ addl $12, %esi /* 4 pixels read */ decl %ecx jnz next_block_24_to_32_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_24_to_32_no_mmx: movl MYLOCAL1, %ecx /* restore width */ andl $3, %ecx jz end_of_line_24_to_32_no_mmx shrl $1, %ecx jnc do_two_pixels_24_to_32_no_mmx xorl %eax, %eax xorl %ebx, %ebx movw (%esi), %ax /* read one pixel */ movb 2(%esi), %bl addl $3, %esi shll $16, %ebx orl %ebx, %eax movl %eax, (%edi) /* write */ addl $4, %edi do_two_pixels_24_to_32_no_mmx: shrl $1, %ecx jnc end_of_line_24_to_32_no_mmx xorl %ebx, %ebx movl (%esi), %eax /* read 2 pixels */ movw 4(%esi), %bx movl %eax, %ecx shll $8, %ebx shrl $24, %ecx addl $6, %esi orl %ecx, %ebx movl %eax, (%edi) /* write */ movl %ebx, 4(%edi) addl $8, %edi _align_ end_of_line_24_to_32_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_24_to_32_no_mmx DESTROY_STACK_FRAME ret #endif /* ALLEGRO_COLOR24 */ #ifdef ALLEGRO_COLOR32 /* void _colorconv_blit_32_to_8 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorconv_blit_32_to_8) CREATE_STACK_FRAME INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_1, LOOP_RATIO_1) movl GLOBL(_colorconv_rgb_map), %ebp CONV_TRUE_TO_8_NO_MMX(32_to_8_no_mmx, 4) DESTROY_STACK_FRAME ret /* void _colorconv_blit_32_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_32_to_15_no_mmx: #else FUNC (_colorconv_blit_32_to_15) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_2, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_2, LOOP_RATIO_1) #endif CONV_TRUE_TO_15_NO_MMX(32_to_15_no_mmx, 4) DESTROY_STACK_FRAME ret /* void _colorconv_blit_32_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_32_to_16_no_mmx: #else FUNC (_colorconv_blit_32_to_16) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_2, LOOP_RATIO_2) #else INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_2, LOOP_RATIO_1) #endif CONV_TRUE_TO_16_NO_MMX(32_to_16_no_mmx, 4) DESTROY_STACK_FRAME ret /* void _colorconv_blit_32_to_24 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ #ifdef ALLEGRO_MMX _align_ _colorconv_blit_32_to_24_no_mmx: #else FUNC (_colorconv_blit_32_to_24) #endif CREATE_STACK_FRAME #ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_3, LOOP_RATIO_4) #else INIT_REGISTERS_NO_MMX(SIZE_4, SIZE_3, LOOP_RATIO_1) #endif movl $0xFFFFFF, %ebp _align_ next_line_32_to_24_no_mmx: movl MYLOCAL1, %ecx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH shrl $2, %ecx jz do_one_pixel_32_to_24_no_mmx #endif _align_ /* 100% Pentium pairable loop */ /* 12 cycles = 11 cycles/4 pixels + 1 cycle loop */ next_block_32_to_24_no_mmx: movl 4(%esi), %ebx /* ebx = [ARGB](2) */ addl $12, %edi /* 4 pixels written */ movl (%esi), %eax /* eax = [ARGB](1) */ movl %ebx, %edx /* edx = [ARGB](2) */ shll $24, %edx /* edx = [B...](2) */ andl %ebp, %ebx /* ebx = [.RGB](2) */ shrl $8, %ebx /* ebx = [..RG](2) */ andl %ebp, %eax /* eax = [.RGB](1) */ orl %edx, %eax /* eax = [BRGB](2)(1) */ movl 8(%esi), %edx /* edx = [ARGB](3) */ movl %eax, -12(%edi) /* write [BRGB](2)(1) */ movl %edx, %eax /* eax = [ARGB](3) */ shll $16, %edx /* edx = [GB..](3) */ andl %ebp, %eax /* eax = [.RGB](3) */ shrl $16, %eax /* eax = [...R](3) */ orl %edx, %ebx /* ebx = [GBRG](3)(2) */ movl 12(%esi), %edx /* edx = [ARGB](4) */ movl %ebx, -8(%edi) /* write [GBRG](3)(2) */ shll $8, %edx /* edx = [RGB.](4) */ addl $16, %esi /* 4 pixels read */ orl %edx, %eax /* eax = [RGBR](4)(3) */ decl %ecx movl %eax, -4(%edi) /* write [RGBR](4)(3) */ jnz next_block_32_to_24_no_mmx #ifndef ALLEGRO_COLORCONV_ALIGNED_WIDTH do_one_pixel_32_to_24_no_mmx: movl MYLOCAL1, %ecx andl $3, %ecx jz end_of_line_32_to_24_no_mmx shrl $1, %ecx jnc do_two_pixels_32_to_24_no_mmx movl (%esi), %eax /* read one pixel */ addl $4, %esi movw %ax, (%edi) /* write bottom 24 bits */ shrl $16, %eax addl $3, %edi movb %al, -1(%edi) do_two_pixels_32_to_24_no_mmx: shrl $1, %ecx jnc end_of_line_32_to_24_no_mmx movl (%esi), %eax /* read two pixels */ movl 4(%esi), %ebx addl $8, %esi movl %ebx, %ecx andl %ebp, %eax shll $24, %ebx orl %ebx, %eax shrl $8, %ecx movl %eax, (%edi) /* write bottom 48 bits */ addl $6, %edi movw %cx, -2(%edi) _align_ end_of_line_32_to_24_no_mmx: #endif addl MYLOCAL2, %esi addl MYLOCAL3, %edi decl MYLOCAL4 jnz next_line_32_to_24_no_mmx DESTROY_STACK_FRAME ret #endif /* ALLEGRO_COLOR32 */ #ifndef ALLEGRO_NO_COLORCOPY /********************************************************************************************/ /* color copy routines */ /* 386 and MMX support */ /********************************************************************************************/ /* void _colorcopy (struct GRAPHICS_RECT *src_rect, struct GRAPHICS_RECT *dest_rect, int bpp) */ FUNC (_colorcopy) pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi /* init register values */ movl ARG3, %ebx movl ARG1, %eax /* eax = src_rect */ movl GFXRECT_WIDTH(%eax), %eax mull %ebx movl %eax, %ecx /* ecx = src_rect->width * bpp */ movl ARG1, %eax movl GFXRECT_HEIGHT(%eax), %edx /* edx = src_rect->height */ movl GFXRECT_DATA(%eax), %esi /* esi = src_rect->data */ movl GFXRECT_PITCH(%eax), %eax /* eax = src_rect->pitch */ subl %ecx, %eax /* eax = (src_rect->pitch) - ecx */ movl ARG2, %ebx /* ebx = dest_rect */ movl GFXRECT_DATA(%ebx), %edi /* edi = dest_rect->data */ movl GFXRECT_PITCH(%ebx), %ebx /* ebx = dest_rect->pitch */ subl %ecx, %ebx /* ebx = (dest_rect->pitch) - ecx */ movl %ecx, %ebp /* save for later */ #ifdef ALLEGRO_MMX movl GLOBL(cpu_capabilities), %ecx /* if MMX is enabled (or not disabled :) */ andl $CPU_MMX, %ecx jz next_line_no_mmx movl %ebp, %ecx shrl $5, %ecx /* we work with 32 pixels at a time */ movd %ecx, %mm6 _align_ next_line: movd %mm6, %ecx orl %ecx, %ecx jz do_one_byte _align_ next_block: movq (%esi), %mm0 /* read */ movq 8(%esi), %mm1 addl $32, %esi movq -16(%esi), %mm2 movq -8(%esi), %mm3 movq %mm0, (%edi) /* write */ movq %mm1, 8(%edi) addl $32, %edi movq %mm2, -16(%edi) movq %mm3, -8(%edi) decl %ecx jnz next_block do_one_byte: movl %ebp, %ecx andl $31, %ecx jz end_of_line shrl $1, %ecx jnc do_two_bytes movsb do_two_bytes: shrl $1, %ecx jnc do_four_bytes movsb movsb _align_ do_four_bytes: shrl $1, %ecx jnc do_eight_bytes movsl _align_ do_eight_bytes: shrl $1, %ecx jnc do_sixteen_bytes movq (%esi), %mm0 addl $8, %esi movq %mm0, (%edi) addl $8, %edi _align_ do_sixteen_bytes: shrl $1, %ecx jnc end_of_line movq (%esi), %mm0 movq 8(%esi), %mm1 addl $16, %esi movq %mm0, (%edi) movq %mm1, 8(%edi) addl $16, %edi _align_ end_of_line: addl %eax, %esi addl %ebx, %edi decl %edx jnz next_line emms jmp end_of_function #endif _align_ next_line_no_mmx: movl %ebp, %ecx shrl $2, %ecx orl %ecx, %ecx jz do_one_byte_no_mmx rep; movsl do_one_byte_no_mmx: movl %ebp, %ecx andl $3, %ecx jz end_of_line_no_mmx shrl $1, %ecx jnc do_two_bytes_no_mmx movsb do_two_bytes_no_mmx: shrl $1, %ecx jnc end_of_line_no_mmx movsb movsb _align_ end_of_line_no_mmx: addl %eax, %esi addl %ebx, %edi decl %edx jnz next_line_no_mmx end_of_function: popl %edi popl %esi popl %ebx popl %ebp ret #ifdef ALLEGRO_COLOR16 /* void _colorcopy_blit_15_to_15 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ /* void _colorcopy_blit_16_to_16 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorcopy_blit_15_to_15) FUNC (_colorcopy_blit_16_to_16) pushl %ebp movl %esp, %ebp pushl $2 pushl ARG2 pushl ARG1 call GLOBL(_colorcopy) addl $12, %esp popl %ebp ret #endif /* ALLEGRO_COLOR16 */ #ifdef ALLEGRO_COLOR24 /* void _colorcopy_blit_24_to_24 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorcopy_blit_24_to_24) pushl %ebp movl %esp, %ebp pushl $3 pushl ARG2 pushl ARG1 call GLOBL(_colorcopy) addl $12, %esp popl %ebp ret #endif /* ALLEGRO_COLOR24 */ #ifdef ALLEGRO_COLOR32 /* void _colorcopy_blit_32_to_32 (struct GRAPHICS_RECT *src_rect, * struct GRAPHICS_RECT *dest_rect) */ FUNC (_colorcopy_blit_32_to_32) pushl %ebp movl %esp, %ebp pushl $4 pushl ARG2 pushl ARG1 call GLOBL(_colorcopy) addl $12, %esp popl %ebp ret #endif /* ALLEGRO_COLOR32 */ #endif /* ALLEGRO_NO_COLORCOPY */ allegro-4.4.3.1/src/mixer.c0000664000175000017500000014335413437077643014371 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sample mixing code. * * By Shawn Hargreaves. * * Proper 16 bit sample support added by Salvador Eduardo Tropea. * * Ben Davis provided the set_volume_per_voice() functionality, * programmed the silent mixer so that silent voices don't freeze, * and fixed a few minor bugs elsewhere. * * Synchronization added by Sam Hocevar. * * Chris Robinson included functions to report the mixer's settings, * switched to signed 24-bit mixing, and cleaned up some of the mess the * code had gathered. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" typedef struct MIXER_VOICE { int playing; /* are we active? */ int channels; /* # of chaanels for input data? */ int bits; /* sample bit-depth */ union { unsigned char *u8; /* data for 8 bit samples */ unsigned short *u16; /* data for 16 bit samples */ void *buffer; /* generic data pointer */ } data; long pos; /* fixed point position in sample */ long diff; /* fixed point speed of play */ long len; /* fixed point sample length */ long loop_start; /* fixed point loop start position */ long loop_end; /* fixed point loop end position */ int lvol; /* left channel volume */ int rvol; /* right channel volume */ } MIXER_VOICE; /* MIX_FIX_SHIFT must be <= (sizeof(int)*8)-24 */ #define MIX_FIX_SHIFT 8 #define MIX_FIX_SCALE (1< 2)) quality = 2; if(mix_channels == 1) quality = 0; _sound_hq = quality; } END_OF_FUNCTION(set_mixer_quality); /* get_mixer_quality: * Returns the current mixing quality, as loaded by the 'quality' config * variable, or a previous call to set_mixer_quality. */ int get_mixer_quality(void) { return _sound_hq; } END_OF_FUNCTION(get_mixer_quality); /* get_mixer_frequency: * Returns the mixer frequency, in Hz. */ int get_mixer_frequency(void) { return mix_freq; } END_OF_FUNCTION(get_mixer_frequency); /* get_mixer_bits: * Returns the mixer bitdepth. */ int get_mixer_bits(void) { return mix_bits; } END_OF_FUNCTION(get_mixer_bits); /* get_mixer_channels: * Returns the number of output channels. */ int get_mixer_channels(void) { return mix_channels; } END_OF_FUNCTION(get_mixer_channels); /* get_mixer_voices: * Returns the number of voices allocated to the mixer. */ int get_mixer_voices(void) { return mix_voices; } END_OF_FUNCTION(get_mixer_voices); /* get_mixer_buffer_length: * Returns the number of samples per channel in the mixer buffer. */ int get_mixer_buffer_length(void) { return mix_size; } END_OF_FUNCTION(get_mixer_buffer_length); /* clamp_volume: * Clamps an integer between 0 and the specified (positive!) value. */ static INLINE int clamp_val(int i, int max) { /* Clamp to 0 */ i &= (~i) >> 31; /* Clamp to max */ i -= max; i &= i >> 31; i += max; return i; } /* set_volume_per_voice: * Enables the programmer (not the end-user) to alter the maximum volume of * each voice: * - pass -1 for Allegro to work as it did before this option was provided * (volume dependent on number of voices), * - pass 0 if you want a single centred sample to be as loud as possible * without distorting, * - pass 1 if you want to pan a full-volume sample to one side without * distortion, * - each time the scale parameter increases by 1, the volume halves. */ static void update_mixer_volume(MIXER_VOICE *mv, PHYS_VOICE *pv); void set_volume_per_voice(int scale) { int i; if(scale < 0) { /* Work out the # of voices and the needed scale */ scale = 1; for(i = 1;i < mix_voices;i <<= 1) scale++; /* Backwards compatiblity with 3.12 */ if(scale < 2) scale = 2; } /* Update the mixer voices' volumes */ #ifdef ALLEGRO_MULTITHREADED if(mixer_mutex) system_driver->lock_mutex(mixer_mutex); #endif voice_volume_scale = scale; for(i = 0;i < mix_voices;++i) update_mixer_volume(mixer_voice+i, _phys_voice+i); #ifdef ALLEGRO_MULTITHREADED if(mixer_mutex) system_driver->unlock_mutex(mixer_mutex); #endif } END_OF_FUNCTION(set_volume_per_voice); /* _mixer_init: * Initialises the sample mixing code, returning 0 on success. You should * pass it the number of samples you want it to mix each time the refill * buffer routine is called, the sample rate to mix at, and two flags * indicating whether the mixing should be done in stereo or mono and with * eight or sixteen bits. The bufsize parameter is the number of samples, * not bytes. It should take into account whether you are working in stereo * or not (eg. double it if in stereo), but it should not be affected by * whether each sample is 8 or 16 bits. */ int _mixer_init(int bufsize, int freq, int stereo, int is16bit, int *voices) { int i, j; if((_sound_hq < 0) || (_sound_hq > 2)) _sound_hq = 2; mix_voices = *voices; if(mix_voices > MIXER_MAX_SFX) *voices = mix_voices = MIXER_MAX_SFX; mix_freq = freq; mix_channels = (stereo ? 2 : 1); mix_bits = (is16bit ? 16 : 8); mix_size = bufsize / mix_channels; for (i=0; icreate_mutex(); if (!mixer_mutex) { _AL_FREE(mix_buffer); mix_buffer = NULL; mix_size = 0; mix_freq = 0; mix_channels = 0; mix_bits = 0; return -1; } #endif return 0; } /* _mixer_exit: * Cleans up the sample mixer code when you are done with it. */ void _mixer_exit(void) { #ifdef ALLEGRO_MULTITHREADED system_driver->destroy_mutex(mixer_mutex); mixer_mutex = NULL; #endif if (mix_buffer) _AL_FREE(mix_buffer); mix_buffer = NULL; mix_size = 0; mix_freq = 0; mix_channels = 0; mix_bits = 0; mix_voices = 0; } /* update_mixer_volume: * Called whenever the voice volume or pan changes, to update the mixer * amplification table indexes. */ static void update_mixer_volume(MIXER_VOICE *mv, PHYS_VOICE *pv) { int vol, pan, lvol, rvol; /* now use full 16 bit volume ranges */ vol = pv->vol>>12; pan = pv->pan>>12; lvol = vol * (255-pan); rvol = vol * pan; /* Adjust for 255*255 < 256*256-1 */ lvol += lvol >> 7; rvol += rvol >> 7; /* Apply voice volume scale and clamp */ mv->lvol = clamp_val((lvol<<1) >> voice_volume_scale, 65535); mv->rvol = clamp_val((rvol<<1) >> voice_volume_scale, 65535); if (!_sound_hq) { /* Scale 16-bit -> table size */ mv->lvol = mv->lvol * MIX_VOLUME_LEVELS / 65536; mv->rvol = mv->rvol * MIX_VOLUME_LEVELS / 65536; } } END_OF_STATIC_FUNCTION(update_mixer_volume); /* update_mixer_freq: * Called whenever the voice frequency changes, to update the sample * delta value. */ static INLINE void update_mixer_freq(MIXER_VOICE *mv, PHYS_VOICE *pv) { mv->diff = (pv->freq >> (12 - MIX_FIX_SHIFT)) / mix_freq; if (pv->playmode & PLAYMODE_BACKWARD) mv->diff = -mv->diff; } /* update_mixer: * Helper for updating the volume ramp and pitch/pan sweep status. */ static void update_mixer(MIXER_VOICE *spl, PHYS_VOICE *voice, int len) { if ((voice->dvol) || (voice->dpan)) { /* update volume ramp */ if (voice->dvol) { voice->vol += voice->dvol; if (((voice->dvol > 0) && (voice->vol >= voice->target_vol)) || ((voice->dvol < 0) && (voice->vol <= voice->target_vol))) { voice->vol = voice->target_vol; voice->dvol = 0; } } /* update pan sweep */ if (voice->dpan) { voice->pan += voice->dpan; if (((voice->dpan > 0) && (voice->pan >= voice->target_pan)) || ((voice->dpan < 0) && (voice->pan <= voice->target_pan))) { voice->pan = voice->target_pan; voice->dpan = 0; } } update_mixer_volume(spl, voice); } /* update frequency sweep */ if (voice->dfreq) { voice->freq += voice->dfreq; if (((voice->dfreq > 0) && (voice->freq >= voice->target_freq)) || ((voice->dfreq < 0) && (voice->freq <= voice->target_freq))) { voice->freq = voice->target_freq; voice->dfreq = 0; } update_mixer_freq(spl, voice); } } END_OF_STATIC_FUNCTION(update_mixer); /* update_silent_mixer: * Another helper for updating the volume ramp and pitch/pan sweep status. * This version is designed for the silent mixer, and it is called just once * per buffer. The len parameter is used to work out how much the values * must be adjusted. */ static void update_silent_mixer(MIXER_VOICE *spl, PHYS_VOICE *voice, int len) { len >>= UPDATE_FREQ_SHIFT; /* update pan sweep */ if (voice->dpan) { voice->pan += voice->dpan * len; if (((voice->dpan > 0) && (voice->pan >= voice->target_pan)) || ((voice->dpan < 0) && (voice->pan <= voice->target_pan))) { voice->pan = voice->target_pan; voice->dpan = 0; } } /* update frequency sweep */ if (voice->dfreq) { voice->freq += voice->dfreq * len; if (((voice->dfreq > 0) && (voice->freq >= voice->target_freq)) || ((voice->dfreq < 0) && (voice->freq <= voice->target_freq))) { voice->freq = voice->target_freq; voice->dfreq = 0; } update_mixer_freq(spl, voice); } } END_OF_STATIC_FUNCTION(update_silent_mixer); /* helper for constructing the body of a sample mixing routine */ #define MIXER() \ { \ if ((voice->playmode & PLAYMODE_LOOP) && \ (spl->loop_start < spl->loop_end)) { \ \ if (voice->playmode & PLAYMODE_BACKWARD) { \ /* mix a backward looping sample */ \ while (len--) { \ MIX(); \ spl->pos += spl->diff; \ if (spl->pos < spl->loop_start) { \ if (voice->playmode & PLAYMODE_BIDIR) { \ spl->diff = -spl->diff; \ /* however far the sample has overshot, move it the same */\ /* distance from the loop point, within the loop section */\ spl->pos = (spl->loop_start << 1) - spl->pos; \ voice->playmode ^= PLAYMODE_BACKWARD; \ } \ else \ spl->pos += (spl->loop_end - spl->loop_start); \ } \ if ((len & (UPDATE_FREQ-1)) == 0) \ update_mixer(spl, voice, len); \ } \ } \ else { \ /* mix a forward looping sample */ \ while (len--) { \ MIX(); \ spl->pos += spl->diff; \ if (spl->pos >= spl->loop_end) { \ if (voice->playmode & PLAYMODE_BIDIR) { \ spl->diff = -spl->diff; \ /* however far the sample has overshot, move it the same */\ /* distance from the loop point, within the loop section */\ spl->pos = ((spl->loop_end - 1) << 1) - spl->pos; \ voice->playmode ^= PLAYMODE_BACKWARD; \ } \ else \ spl->pos -= (spl->loop_end - spl->loop_start); \ } \ if ((len & (UPDATE_FREQ-1)) == 0) \ update_mixer(spl, voice, len); \ } \ } \ } \ else { \ /* mix a non-looping sample */ \ while (len--) { \ MIX(); \ spl->pos += spl->diff; \ if ((unsigned long)spl->pos >= (unsigned long)spl->len) { \ /* note: we don't need a different version for reverse play, */ \ /* as this will wrap and automatically do the Right Thing */ \ spl->playing = FALSE; \ return; \ } \ if ((len & (UPDATE_FREQ-1)) == 0) \ update_mixer(spl, voice, len); \ } \ } \ } /* mix_silent_samples: * This is used when the voice is silent, instead of the other * mix_*_samples() functions. It just extrapolates the sample position, * and stops the sample if it reaches the end and isn't set to loop. * Since no mixing is necessary, this function is much faster than * its friends. In addition, no buffer parameter is required, * and the same function can be used for all sample types. * * There is a catch. All the mix_stereo_*_samples() and * mix_hq?_*_samples() functions (those which write to a stereo mixing * buffer) divide len by 2 before using it in the MIXER() macro. * Therefore, all the mix_silent_samples() for stereo buffers must divide * the len parameter by 2. */ static void mix_silent_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, int len) { if ((voice->playmode & PLAYMODE_LOOP) && (spl->loop_start < spl->loop_end)) { if (voice->playmode & PLAYMODE_BACKWARD) { /* mix a backward looping sample */ spl->pos += spl->diff * len; if (spl->pos < spl->loop_start) { if (voice->playmode & PLAYMODE_BIDIR) { do { spl->diff = -spl->diff; spl->pos = (spl->loop_start << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; if (spl->pos < spl->loop_end) break; spl->diff = -spl->diff; spl->pos = ((spl->loop_end - 1) << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; } while (spl->pos < spl->loop_start); } else { do { spl->pos += (spl->loop_end - spl->loop_start); } while (spl->pos < spl->loop_start); } } update_silent_mixer(spl, voice, len); } else { /* mix a forward looping sample */ spl->pos += spl->diff * len; if (spl->pos >= spl->loop_end) { if (voice->playmode & PLAYMODE_BIDIR) { do { spl->diff = -spl->diff; spl->pos = ((spl->loop_end - 1) << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; if (spl->pos >= spl->loop_start) break; spl->diff = -spl->diff; spl->pos = (spl->loop_start << 1) - spl->pos; voice->playmode ^= PLAYMODE_BACKWARD; } while (spl->pos >= spl->loop_end); } else { do { spl->pos -= (spl->loop_end - spl->loop_start); } while (spl->pos >= spl->loop_end); } } update_silent_mixer(spl, voice, len); } } else { /* mix a non-looping sample */ spl->pos += spl->diff * len; if ((unsigned long)spl->pos >= (unsigned long)spl->len) { /* note: we don't need a different version for reverse play, */ /* as this will wrap and automatically do the Right Thing */ spl->playing = FALSE; return; } update_silent_mixer(spl, voice, len); } } END_OF_STATIC_FUNCTION(mix_silent_samples); /* mix_mono_8x1_samples: * Mixes from an eight bit sample into a mono buffer, until either len * samples have been mixed or until the end of the sample is reached. */ static void mix_mono_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + (spl->lvol>>1)); signed int *rvol = (int *)(mix_vol_table + (spl->rvol>>1)); #define MIX() \ *(buf) += lvol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]]; \ *(buf++) += rvol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_mono_8x1_samples); /* mix_mono_8x2_samples: * Mixes from an eight bit stereo sample into a mono buffer, until either * len samples have been mixed or until the end of the sample is reached. */ static void mix_mono_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + (spl->lvol>>1)); signed int *rvol = (int *)(mix_vol_table + (spl->rvol>>1)); #define MIX() \ *(buf) += lvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2 ]]; \ *(buf++) += rvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2+1]]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_mono_8x2_samples); /* mix_mono_16x1_samples: * Mixes from a 16 bit sample into a mono buffer, until either len samples * have been mixed or until the end of the sample is reached. */ static void mix_mono_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + (spl->lvol>>1)); signed int *rvol = (int *)(mix_vol_table + (spl->rvol>>1)); #define MIX() \ *(buf) += lvol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8]; \ *(buf++) += rvol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_mono_16x1_samples); /* mix_mono_16x2_samples: * Mixes from a 16 bit stereo sample into a mono buffer, until either len * samples have been mixed or until the end of the sample is reached. */ static void mix_mono_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + (spl->lvol>>1)); signed int *rvol = (int *)(mix_vol_table + (spl->rvol>>1)); #define MIX() \ *(buf) += lvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2 ])>>8]; \ *(buf++) += rvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2+1])>>8]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_mono_16x2_samples); /* mix_stereo_8x1_samples: * Mixes from an eight bit sample into a stereo buffer, until either len * samples have been mixed or until the end of the sample is reached. */ static void mix_stereo_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + spl->lvol); signed int *rvol = (int *)(mix_vol_table + spl->rvol); #define MIX() \ *(buf++) += lvol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]]; \ *(buf++) += rvol[spl->data.u8[spl->pos>>MIX_FIX_SHIFT]]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_stereo_8x1_samples); /* mix_stereo_8x2_samples: * Mixes from an eight bit stereo sample into a stereo buffer, until either * len samples have been mixed or until the end of the sample is reached. */ static void mix_stereo_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + spl->lvol); signed int *rvol = (int *)(mix_vol_table + spl->rvol); #define MIX() \ *(buf++) += lvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2 ]]; \ *(buf++) += rvol[spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2+1]]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_stereo_8x2_samples); /* mix_stereo_16x1_samples: * Mixes from a 16 bit sample into a stereo buffer, until either len samples * have been mixed or until the end of the sample is reached. */ static void mix_stereo_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + spl->lvol); signed int *rvol = (int *)(mix_vol_table + spl->rvol); #define MIX() \ *(buf++) += lvol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8]; \ *(buf++) += rvol[(spl->data.u16[spl->pos>>MIX_FIX_SHIFT])>>8]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_stereo_16x1_samples); /* mix_stereo_16x2_samples: * Mixes from a 16 bit stereo sample into a stereo buffer, until either len * samples have been mixed or until the end of the sample is reached. */ static void mix_stereo_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { signed int *lvol = (int *)(mix_vol_table + spl->lvol); signed int *rvol = (int *)(mix_vol_table + spl->rvol); #define MIX() \ *(buf++) += lvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2 ])>>8]; \ *(buf++) += rvol[(spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2+1])>>8]; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_stereo_16x2_samples); /* mix_hq1_8x1_samples: * Mixes from a mono 8 bit sample into a high quality stereo buffer, * until either len samples have been mixed or until the end of the * sample is reached. */ static void mix_hq1_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; #define MIX() \ *(buf++) += (spl->data.u8[spl->pos>>MIX_FIX_SHIFT]-0x80) * lvol; \ *(buf++) += (spl->data.u8[spl->pos>>MIX_FIX_SHIFT]-0x80) * rvol; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq1_8x1_samples); /* mix_hq1_8x2_samples: * Mixes from a stereo 8 bit sample into a high quality stereo buffer, * until either len samples have been mixed or until the end of the * sample is reached. */ static void mix_hq1_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; #define MIX() \ *(buf++) += (spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2 ]-0x80) * lvol; \ *(buf++) += (spl->data.u8[(spl->pos>>MIX_FIX_SHIFT)*2+1]-0x80) * rvol; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq1_8x2_samples); /* mix_hq1_16x1_samples: * Mixes from a mono 16 bit sample into a high-quality stereo buffer, * until either len samples have been mixed or until the end of the sample * is reached. */ static void mix_hq1_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; #define MIX() \ *(buf++) += ((spl->data.u16[spl->pos>>MIX_FIX_SHIFT]-0x8000)*lvol)>>8; \ *(buf++) += ((spl->data.u16[spl->pos>>MIX_FIX_SHIFT]-0x8000)*rvol)>>8; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq1_16x1_samples); /* mix_hq1_16x2_samples: * Mixes from a stereo 16 bit sample into a high-quality stereo buffer, * until either len samples have been mixed or until the end of the sample * is reached. */ static void mix_hq1_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; #define MIX() \ *(buf++) += ((spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2 ]-0x8000)*lvol)>>8;\ *(buf++) += ((spl->data.u16[(spl->pos>>MIX_FIX_SHIFT)*2+1]-0x8000)*rvol)>>8; MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq1_16x2_samples); /* Helper to apply a 16-bit volume to a 24-bit sample */ #define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32)) /* mix_hq2_8x1_samples: * Mixes from a mono 8 bit sample into an interpolated stereo buffer, * until either len samples have been mixed or until the end of the * sample is reached. */ static void mix_hq2_8x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; int v, v1, v2; #define MIX() \ v = spl->pos>>MIX_FIX_SHIFT; \ \ v1 = (spl->data.u8[v]<<16) - 0x800000; \ \ if (spl->pos >= spl->len-MIX_FIX_SCALE) { \ if ((voice->playmode & (PLAYMODE_LOOP | \ PLAYMODE_BIDIR)) == PLAYMODE_LOOP && \ spl->loop_start < spl->loop_end && spl->loop_end == spl->len) \ v2 = (spl->data.u8[spl->loop_start>>MIX_FIX_SHIFT]<<16)-0x800000;\ else \ v2 = 0; \ } \ else \ v2 = (spl->data.u8[v+1]<<16) - 0x800000; \ \ v = spl->pos & (MIX_FIX_SCALE-1); \ v = ((v2*v) + (v1*(MIX_FIX_SCALE-v))) >> MIX_FIX_SHIFT; \ \ *(buf++) += MULSC(v, lvol); \ *(buf++) += MULSC(v, rvol); MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq2_8x1_samples); /* mix_hq2_8x2_samples: * Mixes from a stereo 8 bit sample into an interpolated stereo buffer, * until either len samples have been mixed or until the end of the * sample is reached. */ static void mix_hq2_8x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; int v, va, v1a, v2a, vb, v1b, v2b; #define MIX() \ v = (spl->pos>>MIX_FIX_SHIFT) << 1; /* x2 for stereo */ \ \ v1a = (spl->data.u8[v]<<16) - 0x800000; \ v1b = (spl->data.u8[v+1]<<16) - 0x800000; \ \ if (spl->pos >= spl->len-MIX_FIX_SCALE) { \ if ((voice->playmode & (PLAYMODE_LOOP | \ PLAYMODE_BIDIR)) == PLAYMODE_LOOP && \ spl->loop_start < spl->loop_end && spl->loop_end == spl->len) { \ v2a = (spl->data.u8[((spl->loop_start>>MIX_FIX_SHIFT)<<1)]<<16) - 0x800000;\ v2b = (spl->data.u8[((spl->loop_start>>MIX_FIX_SHIFT)<<1)+1]<<16) - 0x800000;\ } \ else \ v2a = v2b = 0; \ } \ else { \ v2a = (spl->data.u8[v+2]<<16) - 0x800000; \ v2b = (spl->data.u8[v+3]<<16) - 0x800000; \ } \ \ v = spl->pos & (MIX_FIX_SCALE-1); \ va = ((v2a*v) + (v1a*(MIX_FIX_SCALE-v))) >> MIX_FIX_SHIFT; \ vb = ((v2b*v) + (v1b*(MIX_FIX_SCALE-v))) >> MIX_FIX_SHIFT; \ \ *(buf++) += MULSC(va, lvol); \ *(buf++) += MULSC(vb, rvol); MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq2_8x2_samples); /* mix_hq2_16x1_samples: * Mixes from a mono 16 bit sample into an interpolated stereo buffer, * until either len samples have been mixed or until the end of the sample * is reached. */ static void mix_hq2_16x1_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; int v, v1, v2; #define MIX() \ v = spl->pos>>MIX_FIX_SHIFT; \ \ v1 = (spl->data.u16[v]<<8) - 0x800000; \ \ if (spl->pos >= spl->len-MIX_FIX_SCALE) { \ if ((voice->playmode & (PLAYMODE_LOOP | \ PLAYMODE_BIDIR)) == PLAYMODE_LOOP && \ spl->loop_start < spl->loop_end && spl->loop_end == spl->len) \ v2 = (spl->data.u16[spl->loop_start>>MIX_FIX_SHIFT]<<8)-0x800000;\ else \ v2 = 0; \ } \ else \ v2 = (spl->data.u16[v+1]<<8) - 0x800000; \ \ v = spl->pos & (MIX_FIX_SCALE-1); \ v = ((v2*v) + (v1*(MIX_FIX_SCALE-v))) >> MIX_FIX_SHIFT; \ \ *(buf++) += MULSC(v, lvol); \ *(buf++) += MULSC(v, rvol); MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq2_16x1_samples); /* mix_hq2_16x2_samples: * Mixes from a stereo 16 bit sample into an interpolated stereo buffer, * until either len samples have been mixed or until the end of the sample * is reached. */ static void mix_hq2_16x2_samples(MIXER_VOICE *spl, PHYS_VOICE *voice, signed int *buf, int len) { int lvol = spl->lvol; int rvol = spl->rvol; int v, va, v1a, v2a, vb, v1b, v2b; #define MIX() \ v = (spl->pos>>MIX_FIX_SHIFT) << 1; /* x2 for stereo */ \ \ v1a = (spl->data.u16[v]<<8) - 0x800000; \ v1b = (spl->data.u16[v+1]<<8) - 0x800000; \ \ if (spl->pos >= spl->len-MIX_FIX_SCALE) { \ if ((voice->playmode & (PLAYMODE_LOOP | \ PLAYMODE_BIDIR)) == PLAYMODE_LOOP && \ spl->loop_start < spl->loop_end && spl->loop_end == spl->len) { \ v2a = (spl->data.u16[((spl->loop_start>>MIX_FIX_SHIFT)<<1)]<<8) - 0x800000;\ v2b = (spl->data.u16[((spl->loop_start>>MIX_FIX_SHIFT)<<1)+1]<<8) - 0x800000;\ } \ else \ v2a = v2b = 0; \ } \ else { \ v2a = (spl->data.u16[v+2]<<8) - 0x800000; \ v2b = (spl->data.u16[v+3]<<8) - 0x800000; \ } \ \ v = spl->pos & (MIX_FIX_SCALE-1); \ va = ((v2a*v) + (v1a*(MIX_FIX_SCALE-v))) >> MIX_FIX_SHIFT; \ vb = ((v2b*v) + (v1b*(MIX_FIX_SCALE-v))) >> MIX_FIX_SHIFT; \ \ *(buf++) += MULSC(va, lvol); \ *(buf++) += MULSC(vb, rvol); MIXER(); #undef MIX } END_OF_STATIC_FUNCTION(mix_hq2_16x2_samples); #define MAX_24 (0x00FFFFFF) /* _mix_some_samples: * Mixes samples into a buffer in memory (the buf parameter should be a * linear offset into the specified segment), using the buffer size, sample * frequency, etc, set when you called _mixer_init(). This should be called * by the audio driver to get the next buffer full of samples. */ void _mix_some_samples(uintptr_t buf, unsigned short seg, int issigned) { signed int *p = mix_buffer; int i; /* clear mixing buffer */ memset(p, 0, mix_size*mix_channels * sizeof(*p)); #ifdef ALLEGRO_MULTITHREADED system_driver->lock_mutex(mixer_mutex); #endif for (i=0; i 0) || (_phys_voice[i].dvol > 0)) { /* Interpolated mixing */ if (_sound_hq >= 2) { /* stereo input -> interpolated output */ if (mixer_voice[i].channels != 1) { if (mixer_voice[i].bits == 8) mix_hq2_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_hq2_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } /* mono input -> interpolated output */ else { if (mixer_voice[i].bits == 8) mix_hq2_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_hq2_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } } /* high quality mixing */ else if (_sound_hq) { /* stereo input -> high quality output */ if (mixer_voice[i].channels != 1) { if (mixer_voice[i].bits == 8) mix_hq1_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_hq1_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } /* mono input -> high quality output */ else { if (mixer_voice[i].bits == 8) mix_hq1_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_hq1_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } } /* low quality (fast?) stereo mixing */ else if (mix_channels != 1) { /* stereo input -> stereo output */ if (mixer_voice[i].channels != 1) { if (mixer_voice[i].bits == 8) mix_stereo_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_stereo_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } /* mono input -> stereo output */ else { if (mixer_voice[i].bits == 8) mix_stereo_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_stereo_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } } /* low quality (fast?) mono mixing */ else { /* stereo input -> mono output */ if (mixer_voice[i].channels != 1) { if (mixer_voice[i].bits == 8) mix_mono_8x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_mono_16x2_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } /* mono input -> mono output */ else { if (mixer_voice[i].bits == 8) mix_mono_8x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); else mix_mono_16x1_samples(mixer_voice+i, _phys_voice+i, p, mix_size); } } } else mix_silent_samples(mixer_voice+i, _phys_voice+i, mix_size); } } #ifdef ALLEGRO_MULTITHREADED system_driver->unlock_mutex(mixer_mutex); #endif _farsetsel(seg); /* transfer to the audio driver's buffer */ if (mix_bits == 16) { if (issigned) { for (i=mix_size*mix_channels; i>0; i--) { _farnspokew(buf, (clamp_val((*p)+0x800000, MAX_24) >> 8) ^ 0x8000); buf += 2; p++; } } else { for (i=mix_size*mix_channels; i>0; i--) { _farnspokew(buf, clamp_val((*p)+0x800000, MAX_24) >> 8); buf += 2; p++; } } } else { if(issigned) { for (i=mix_size*mix_channels; i>0; i--) { _farnspokeb(buf, (clamp_val((*p)+0x800000, MAX_24) >> 16) ^ 0x80); buf++; p++; } } else { for (i=mix_size*mix_channels; i>0; i--) { _farnspokeb(buf, clamp_val((*p)+0x800000, MAX_24) >> 16); buf++; p++; } } } } END_OF_FUNCTION(_mix_some_samples); /* _mixer_init_voice: * Initialises the specificed voice ready for playing a sample. */ void _mixer_init_voice(int voice, AL_CONST SAMPLE *sample) { mixer_voice[voice].playing = FALSE; mixer_voice[voice].channels = (sample->stereo ? 2 : 1); mixer_voice[voice].bits = sample->bits; mixer_voice[voice].pos = 0; mixer_voice[voice].len = sample->len << MIX_FIX_SHIFT; mixer_voice[voice].loop_start = sample->loop_start << MIX_FIX_SHIFT; mixer_voice[voice].loop_end = sample->loop_end << MIX_FIX_SHIFT; mixer_voice[voice].data.buffer = sample->data; update_mixer_volume(mixer_voice+voice, _phys_voice+voice); update_mixer_freq(mixer_voice+voice, _phys_voice+voice); } END_OF_FUNCTION(_mixer_init_voice); /* _mixer_release_voice: * Releases a voice when it is no longer required. */ void _mixer_release_voice(int voice) { #ifdef ALLEGRO_MULTITHREADED system_driver->lock_mutex(mixer_mutex); #endif mixer_voice[voice].playing = FALSE; mixer_voice[voice].data.buffer = NULL; #ifdef ALLEGRO_MULTITHREADED system_driver->unlock_mutex(mixer_mutex); #endif } END_OF_FUNCTION(_mixer_release_voice); /* _mixer_start_voice: * Activates a voice, with the currently selected parameters. */ void _mixer_start_voice(int voice) { if (mixer_voice[voice].pos >= mixer_voice[voice].len) mixer_voice[voice].pos = 0; mixer_voice[voice].playing = TRUE; } END_OF_FUNCTION(_mixer_start_voice); /* _mixer_stop_voice: * Stops a voice from playing. */ void _mixer_stop_voice(int voice) { mixer_voice[voice].playing = FALSE; } END_OF_FUNCTION(_mixer_stop_voice); /* _mixer_loop_voice: * Sets the loopmode for a voice. */ void _mixer_loop_voice(int voice, int loopmode) { update_mixer_freq(mixer_voice+voice, _phys_voice+voice); } END_OF_FUNCTION(_mixer_loop_voice); /* _mixer_get_position: * Returns the current play position of a voice, or -1 if it has finished. */ int _mixer_get_position(int voice) { if ((!mixer_voice[voice].playing) || (mixer_voice[voice].pos >= mixer_voice[voice].len)) return -1; return (mixer_voice[voice].pos >> MIX_FIX_SHIFT); } END_OF_FUNCTION(_mixer_get_position); /* _mixer_set_position: * Sets the current play position of a voice. */ void _mixer_set_position(int voice, int position) { if (position < 0) position = 0; mixer_voice[voice].pos = (position << MIX_FIX_SHIFT); if (mixer_voice[voice].pos >= mixer_voice[voice].len) mixer_voice[voice].playing = FALSE; } END_OF_FUNCTION(_mixer_set_position); /* _mixer_get_volume: * Returns the current volume of a voice. */ int _mixer_get_volume(int voice) { return (_phys_voice[voice].vol >> 12); } END_OF_FUNCTION(_mixer_get_volume); /* _mixer_set_volume: * Sets the volume of a voice. */ void _mixer_set_volume(int voice, int volume) { update_mixer_volume(mixer_voice+voice, _phys_voice+voice); } END_OF_FUNCTION(_mixer_set_volume); /* _mixer_ramp_volume: * Starts a volume ramping operation. */ void _mixer_ramp_volume(int voice, int time, int endvol) { int d = (endvol << 12) - _phys_voice[voice].vol; time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1); _phys_voice[voice].target_vol = endvol << 12; _phys_voice[voice].dvol = d / time; } END_OF_FUNCTION(_mixer_ramp_volume); /* _mixer_stop_volume_ramp: * Ends a volume ramp operation. */ void _mixer_stop_volume_ramp(int voice) { _phys_voice[voice].dvol = 0; } END_OF_FUNCTION(_mixer_stop_volume_ramp); /* _mixer_get_frequency: * Returns the current frequency of a voice. */ int _mixer_get_frequency(int voice) { return (_phys_voice[voice].freq >> 12); } END_OF_FUNCTION(_mixer_get_frequency); /* _mixer_set_frequency: * Sets the frequency of a voice. */ void _mixer_set_frequency(int voice, int frequency) { update_mixer_freq(mixer_voice+voice, _phys_voice+voice); } END_OF_FUNCTION(_mixer_set_frequency); /* _mixer_sweep_frequency: * Starts a frequency sweep. */ void _mixer_sweep_frequency(int voice, int time, int endfreq) { int d = (endfreq << 12) - _phys_voice[voice].freq; time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1); _phys_voice[voice].target_freq = endfreq << 12; _phys_voice[voice].dfreq = d / time; } END_OF_FUNCTION(_mixer_sweep_frequency); /* _mixer_stop_frequency_sweep: * Ends a frequency sweep. */ void _mixer_stop_frequency_sweep(int voice) { _phys_voice[voice].dfreq = 0; } END_OF_FUNCTION(_mixer_stop_frequency_sweep); /* _mixer_get_pan: * Returns the current pan position of a voice. */ int _mixer_get_pan(int voice) { return (_phys_voice[voice].pan >> 12); } END_OF_FUNCTION(_mixer_get_pan); /* _mixer_set_pan: * Sets the pan position of a voice. */ void _mixer_set_pan(int voice, int pan) { update_mixer_volume(mixer_voice+voice, _phys_voice+voice); } END_OF_FUNCTION(_mixer_set_pan); /* _mixer_sweep_pan: * Starts a pan sweep. */ void _mixer_sweep_pan(int voice, int time, int endpan) { int d = (endpan << 12) - _phys_voice[voice].pan; time = MAX(time * (mix_freq / UPDATE_FREQ) / 1000, 1); _phys_voice[voice].target_pan = endpan << 12; _phys_voice[voice].dpan = d / time; } END_OF_FUNCTION(_mixer_sweep_pan); /* _mixer_stop_pan_sweep: * Ends a pan sweep. */ void _mixer_stop_pan_sweep(int voice) { _phys_voice[voice].dpan = 0; } END_OF_FUNCTION(_mixer_stop_pan_sweep); /* _mixer_set_echo: * Sets the echo parameters for a voice. */ void _mixer_set_echo(int voice, int strength, int delay) { /* not implemented */ } END_OF_FUNCTION(_mixer_set_echo); /* _mixer_set_tremolo: * Sets the tremolo parameters for a voice. */ void _mixer_set_tremolo(int voice, int rate, int depth) { /* not implemented */ } END_OF_FUNCTION(_mixer_set_tremolo); /* _mixer_set_vibrato: * Sets the amount of vibrato for a voice. */ void _mixer_set_vibrato(int voice, int rate, int depth) { /* not implemented */ } END_OF_FUNCTION(_mixer_set_vibrato); /* mixer_lock_mem: * Locks memory used by the functions in this file. */ static void mixer_lock_mem(void) { LOCK_VARIABLE(mixer_voice); LOCK_VARIABLE(mix_buffer); LOCK_VARIABLE(mix_vol_table); LOCK_VARIABLE(mix_voices); LOCK_VARIABLE(mix_size); LOCK_VARIABLE(mix_freq); LOCK_VARIABLE(mix_channels); LOCK_VARIABLE(mix_bits); LOCK_FUNCTION(set_mixer_quality); LOCK_FUNCTION(get_mixer_quality); LOCK_FUNCTION(get_mixer_buffer_length); LOCK_FUNCTION(get_mixer_frequency); LOCK_FUNCTION(get_mixer_bits); LOCK_FUNCTION(get_mixer_channels); LOCK_FUNCTION(get_mixer_voices); LOCK_FUNCTION(set_volume_per_voice); LOCK_FUNCTION(mix_silent_samples); LOCK_FUNCTION(mix_mono_8x1_samples); LOCK_FUNCTION(mix_mono_8x2_samples); LOCK_FUNCTION(mix_mono_16x1_samples); LOCK_FUNCTION(mix_mono_16x2_samples); LOCK_FUNCTION(mix_stereo_8x1_samples); LOCK_FUNCTION(mix_stereo_8x2_samples); LOCK_FUNCTION(mix_stereo_16x1_samples); LOCK_FUNCTION(mix_stereo_16x2_samples); LOCK_FUNCTION(mix_hq1_8x1_samples); LOCK_FUNCTION(mix_hq1_8x2_samples); LOCK_FUNCTION(mix_hq1_16x1_samples); LOCK_FUNCTION(mix_hq1_16x2_samples); LOCK_FUNCTION(mix_hq2_8x1_samples); LOCK_FUNCTION(mix_hq2_8x2_samples); LOCK_FUNCTION(mix_hq2_16x1_samples); LOCK_FUNCTION(mix_hq2_16x2_samples); LOCK_FUNCTION(update_mixer_volume); LOCK_FUNCTION(update_mixer); LOCK_FUNCTION(update_silent_mixer); LOCK_FUNCTION(_mix_some_samples); LOCK_FUNCTION(_mixer_init_voice); LOCK_FUNCTION(_mixer_release_voice); LOCK_FUNCTION(_mixer_start_voice); LOCK_FUNCTION(_mixer_stop_voice); LOCK_FUNCTION(_mixer_loop_voice); LOCK_FUNCTION(_mixer_get_position); LOCK_FUNCTION(_mixer_set_position); LOCK_FUNCTION(_mixer_get_volume); LOCK_FUNCTION(_mixer_set_volume); LOCK_FUNCTION(_mixer_ramp_volume); LOCK_FUNCTION(_mixer_stop_volume_ramp); LOCK_FUNCTION(_mixer_get_frequency); LOCK_FUNCTION(_mixer_set_frequency); LOCK_FUNCTION(_mixer_sweep_frequency); LOCK_FUNCTION(_mixer_stop_frequency_sweep); LOCK_FUNCTION(_mixer_get_pan); LOCK_FUNCTION(_mixer_set_pan); LOCK_FUNCTION(_mixer_sweep_pan); LOCK_FUNCTION(_mixer_stop_pan_sweep); LOCK_FUNCTION(_mixer_set_echo); LOCK_FUNCTION(_mixer_set_tremolo); LOCK_FUNCTION(_mixer_set_vibrato); } allegro-4.4.3.1/src/sound.c0000664000175000017500000015350013437077643014367 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Sound setup routines and API framework functions. * * By Shawn Hargreaves. * * Input routines added by Ove Kaaven. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" static DIGI_DRIVER digi_none; /* dummy functions for the nosound drivers */ int _dummy_detect(int input) { return TRUE; } int _dummy_init(int input, int voices) { digi_none.desc = _midi_none.desc = get_config_text("The sound of silence"); return 0; } void _dummy_exit(int input) { } int _dummy_set_mixer_volume(int volume) { return 0; } int _dummy_get_mixer_volume(void) { return -1; } void _dummy_init_voice(int voice, AL_CONST SAMPLE *sample) { } void _dummy_noop1(int p) { } void _dummy_noop2(int p1, int p2) { } void _dummy_noop3(int p1, int p2, int p3) { } int _dummy_get_position(int voice) { return -1; } int _dummy_get(int voice) { return 0; } void _dummy_raw_midi(int data) { } int _dummy_load_patches(AL_CONST char *patches, AL_CONST char *drums) { return 0; } void _dummy_adjust_patches(AL_CONST char *patches, AL_CONST char *drums) { } void _dummy_key_on(int inst, int note, int bend, int vol, int pan) { } /* put this after all the dummy functions, so they will all get locked */ END_OF_FUNCTION(_dummy_detect); static DIGI_DRIVER digi_none = { DIGI_NONE, empty_string, empty_string, "No sound", 0, 0, 0xFFFF, 0, _dummy_detect, _dummy_init, _dummy_exit, _dummy_set_mixer_volume, _dummy_get_mixer_volume, NULL, NULL, NULL, _dummy_init_voice, _dummy_noop1, _dummy_noop1, _dummy_noop1, _dummy_noop2, _dummy_get_position, _dummy_noop2, _dummy_get, _dummy_noop2, _dummy_noop3, _dummy_noop1, _dummy_get, _dummy_noop2, _dummy_noop3, _dummy_noop1, _dummy_get, _dummy_noop2, _dummy_noop3, _dummy_noop1, _dummy_noop3, _dummy_noop3, _dummy_noop3, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }; MIDI_DRIVER _midi_none = { MIDI_NONE, empty_string, empty_string, "No sound", 0, 0, 0xFFFF, 0, -1, -1, _dummy_detect, _dummy_init, _dummy_exit, _dummy_set_mixer_volume, _dummy_get_mixer_volume, _dummy_raw_midi, _dummy_load_patches, _dummy_adjust_patches, _dummy_key_on, _dummy_noop1, _dummy_noop2, _dummy_noop3, _dummy_noop2, _dummy_noop2 }; int digi_card = DIGI_AUTODETECT; /* current driver ID numbers */ int midi_card = MIDI_AUTODETECT; int digi_input_card = DIGI_AUTODETECT; int midi_input_card = MIDI_AUTODETECT; DIGI_DRIVER *digi_driver = &digi_none; /* these things do all the work */ MIDI_DRIVER *midi_driver = &_midi_none; DIGI_DRIVER *digi_input_driver = &digi_none; MIDI_DRIVER *midi_input_driver = &_midi_none; void (*digi_recorder)(void) = NULL; void (*midi_recorder)(unsigned char data) = NULL; int _sound_installed = FALSE; /* are we installed? */ int _sound_input_installed = FALSE; static int digi_reserve = -1; /* how many voices to reserve */ static int midi_reserve = -1; static VOICE virt_voice[VIRTUAL_VOICES]; /* list of active samples */ PHYS_VOICE _phys_voice[DIGI_VOICES]; /* physical -> virtual voice map */ int _digi_volume = -1; /* current volume settings */ int _midi_volume = -1; int _sound_flip_pan = FALSE; /* reverse l/r sample panning? */ int _sound_hq = 2; /* mixer speed vs. quality */ int _sound_freq = -1; /* common hardware parameters */ int _sound_stereo = -1; int _sound_bits = -1; int _sound_port = -1; int _sound_dma = -1; int _sound_irq = -1; #define SWEEP_FREQ 50 static void update_sweeps(void); static void sound_lock_mem(void); /* read_sound_config: * Helper for reading the sound hardware configuration data. */ static void read_sound_config(void) { char tmp1[64], tmp2[64]; char *sound = uconvert_ascii("sound", tmp1); _sound_flip_pan = get_config_int(sound, uconvert_ascii("flip_pan", tmp2), FALSE); _sound_hq = get_config_int(sound, uconvert_ascii("quality", tmp2), _sound_hq); _sound_port = get_config_hex(sound, uconvert_ascii("sound_port", tmp2), -1); _sound_dma = get_config_int(sound, uconvert_ascii("sound_dma", tmp2), -1); _sound_irq = get_config_int(sound, uconvert_ascii("sound_irq", tmp2), -1); _sound_freq = get_config_int(sound, uconvert_ascii("sound_freq", tmp2), -1); _sound_bits = get_config_int(sound, uconvert_ascii("sound_bits", tmp2), -1); _sound_stereo = get_config_int(sound, uconvert_ascii("sound_stereo", tmp2), -1); _digi_volume = get_config_int(sound, uconvert_ascii("digi_volume", tmp2), -1); _midi_volume = get_config_int(sound, uconvert_ascii("midi_volume", tmp2), -1); } /* detect_digi_driver: * Detects whether the specified digital sound driver is available, * returning the maximum number of voices that it can provide, or * zero if the device is not present. This function must be called * _before_ install_sound(). */ int detect_digi_driver(int driver_id) { _DRIVER_INFO *digi_drivers; int i, ret; if (_sound_installed) return 0; read_sound_config(); if (system_driver->digi_drivers) digi_drivers = system_driver->digi_drivers(); else digi_drivers = _digi_driver_list; for (i=0; digi_drivers[i].id; i++) { if (digi_drivers[i].id == driver_id) { digi_driver = digi_drivers[i].driver; digi_driver->name = digi_driver->desc = get_config_text(digi_driver->ascii_name); digi_card = driver_id; midi_card = MIDI_AUTODETECT; if (digi_driver->detect(FALSE)) ret = digi_driver->max_voices; else ret = 0; digi_driver = &digi_none; return ret; } } return digi_none.max_voices; } /* detect_midi_driver: * Detects whether the specified MIDI sound driver is available, * returning the maximum number of voices that it can provide, or * zero if the device is not present. If this routine returns -1, * it is a note-stealing MIDI driver, which shares voices with the * current digital driver. In this situation you can use the * reserve_voices() function to specify how the available voices are * divided between the digital and MIDI playback routines. This function * must be called _before_ install_sound(). */ int detect_midi_driver(int driver_id) { _DRIVER_INFO *midi_drivers; int i, ret; if (_sound_installed) return 0; read_sound_config(); if (system_driver->midi_drivers) midi_drivers = system_driver->midi_drivers(); else midi_drivers = _midi_driver_list; for (i=0; midi_drivers[i].id; i++) { if (midi_drivers[i].id == driver_id) { midi_driver = midi_drivers[i].driver; midi_driver->name = midi_driver->desc = get_config_text(midi_driver->ascii_name); digi_card = DIGI_AUTODETECT; midi_card = driver_id; if (midi_driver->detect(FALSE)) ret = midi_driver->max_voices; else ret = 0; midi_driver = &_midi_none; return ret; } } return _midi_none.max_voices; } /* reserve_voices: * Reserves a number of voices for the digital and MIDI sound drivers * respectively. This must be called _before_ install_sound(). If you * attempt to reserve too many voices, subsequent calls to install_sound() * will fail. Note that depending on the driver you may actually get * more voices than you reserve: these values just specify the minimum * that is appropriate for your application. Pass a negative reserve value * to use the default settings. */ void reserve_voices(int digi_voices, int midi_voices) { digi_reserve = digi_voices; midi_reserve = midi_voices; } /* install_sound: * Initialises the sound module, returning zero on success. The two card * parameters should use the DIGI_* and MIDI_* constants defined in * allegro.h. Pass DIGI_AUTODETECT and MIDI_AUTODETECT if you don't know * what the soundcard is. */ int install_sound(int digi, int midi, AL_CONST char *cfg_path) { char tmp1[64], tmp2[64]; char *sound = uconvert_ascii("sound", tmp1); _DRIVER_INFO *digi_drivers, *midi_drivers; int digi_voices, midi_voices; int c; if (_sound_installed) return 0; for (c=0; cinit() != 0) return -1; usetc(allegro_error, 0); register_datafile_object(DAT_SAMPLE, NULL, (void (*)(void *))destroy_sample); digi_card = digi; midi_card = midi; /* read config information */ if (digi_card == DIGI_AUTODETECT) digi_card = get_config_id(sound, uconvert_ascii("digi_card", tmp2), DIGI_AUTODETECT); if (midi_card == MIDI_AUTODETECT) midi_card = get_config_id(sound, uconvert_ascii("midi_card", tmp2), MIDI_AUTODETECT); if (digi_reserve < 0) digi_reserve = get_config_int(sound, uconvert_ascii("digi_voices", tmp2), -1); if (midi_reserve < 0) midi_reserve = get_config_int(sound, uconvert_ascii("midi_voices", tmp2), -1); read_sound_config(); sound_lock_mem(); /* set up digital sound driver */ if (system_driver->digi_drivers) digi_drivers = system_driver->digi_drivers(); else digi_drivers = _digi_driver_list; for (c=0; digi_drivers[c].driver; c++) { digi_driver = digi_drivers[c].driver; digi_driver->name = digi_driver->desc = get_config_text(digi_driver->ascii_name); } digi_driver = NULL; /* search table for a specific digital driver */ for (c=0; digi_drivers[c].driver; c++) { if (digi_drivers[c].id == digi_card) { digi_driver = digi_drivers[c].driver; if (!digi_driver->detect(FALSE)) { digi_driver = &digi_none; if (_al_linker_midi) _al_linker_midi->exit(); if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Digital sound driver not found")); return -1; } break; } } if (digi_card == DIGI_NONE) digi_driver = &digi_none; /* autodetect digital driver */ if (!digi_driver) { for (c=0; digi_drivers[c].driver; c++) { if (digi_drivers[c].autodetect) { digi_card = digi_drivers[c].id; digi_driver = digi_drivers[c].driver; if (digi_driver->detect(FALSE)) break; digi_driver = NULL; } } if (!digi_driver) { digi_card = DIGI_NONE; digi_driver = &digi_none; } } /* set up midi sound driver */ if (system_driver->midi_drivers) midi_drivers = system_driver->midi_drivers(); else midi_drivers = _midi_driver_list; for (c=0; midi_drivers[c].driver; c++) { midi_driver = midi_drivers[c].driver; midi_driver->name = midi_driver->desc = get_config_text(midi_driver->ascii_name); } midi_driver = NULL; /* search table for a specific MIDI driver */ for (c=0; midi_drivers[c].driver; c++) { if (midi_drivers[c].id == midi_card) { midi_driver = midi_drivers[c].driver; if (!midi_driver->detect(FALSE)) { digi_driver = &digi_none; midi_driver = &_midi_none; if (_al_linker_midi) _al_linker_midi->exit(); if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MIDI music driver not found")); return -1; } break; } } if (midi_card == MIDI_NONE) midi_driver = &_midi_none; /* autodetect MIDI driver */ if (!midi_driver) { for (c=0; midi_drivers[c].driver; c++) { if (midi_drivers[c].autodetect) { midi_card = midi_drivers[c].id; midi_driver = midi_drivers[c].driver; if (midi_driver->detect(FALSE)) break; midi_driver = NULL; } } if (!midi_driver) { midi_card = MIDI_NONE; midi_driver = &_midi_none; } } /* work out how many voices to allocate for each driver */ if (digi_reserve >= 0) digi_voices = digi_reserve; else digi_voices = digi_driver->def_voices; if (midi_driver->max_voices < 0) { /* MIDI driver steals voices from the digital player */ if (midi_reserve >= 0) midi_voices = midi_reserve; else midi_voices = CLAMP(0, digi_driver->max_voices - digi_voices, midi_driver->def_voices); digi_voices += midi_voices; } else { /* MIDI driver has voices of its own */ if (midi_reserve >= 0) midi_voices = midi_reserve; else midi_voices = midi_driver->def_voices; } /* make sure this is a reasonable number of voices to use */ if ((digi_voices > DIGI_VOICES) || (midi_voices > MIDI_VOICES)) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Insufficient %s voices available"), (digi_voices > DIGI_VOICES) ? get_config_text("digital") : get_config_text("MIDI")); digi_driver = &digi_none; midi_driver = &_midi_none; if (_al_linker_midi) _al_linker_midi->exit(); return -1; } /* initialise the digital sound driver */ if (digi_driver->init(FALSE, digi_voices) != 0) { digi_driver = &digi_none; midi_driver = &_midi_none; if (_al_linker_midi) _al_linker_midi->exit(); if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed to init digital sound driver")); return -1; } /* initialise the MIDI driver */ if (midi_driver->init(FALSE, midi_voices) != 0) { digi_driver->exit(FALSE); digi_driver = &digi_none; midi_driver = &_midi_none; if (_al_linker_midi) _al_linker_midi->exit(); if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed to init MIDI music driver")); return -1; } digi_driver->voices = MIN(digi_driver->voices, DIGI_VOICES); midi_driver->voices = MIN(midi_driver->voices, MIDI_VOICES); /* check that we actually got enough voices */ if ((digi_driver->voices < digi_voices) || ((midi_driver->voices < midi_voices) && (!midi_driver->raw_midi))) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Insufficient %s voices available"), (digi_driver->voices < digi_voices) ? get_config_text("digital") : get_config_text("MIDI")); midi_driver->exit(FALSE); digi_driver->exit(FALSE); digi_driver = &digi_none; midi_driver = &_midi_none; if (_al_linker_midi) _al_linker_midi->exit(); return -1; } /* adjust for note-stealing MIDI drivers */ if (midi_driver->max_voices < 0) { midi_voices += (digi_driver->voices - digi_voices) * 3/4; digi_driver->voices -= midi_voices; midi_driver->basevoice = VIRTUAL_VOICES - midi_voices; midi_driver->voices = midi_voices; for (c=0; cbasevoice+c].num = digi_driver->voices+c; _phys_voice[digi_driver->voices+c].num = midi_driver->basevoice+c; } } /* simulate ramp/sweep effects for drivers that don't do it directly */ if ((!digi_driver->ramp_volume) || (!digi_driver->sweep_frequency) || (!digi_driver->sweep_pan)) install_int_ex(update_sweeps, BPS_TO_TIMER(SWEEP_FREQ)); /* set the global sound volume */ if ((_digi_volume >= 0) || (_midi_volume >= 0)) set_volume(_digi_volume, _midi_volume); _add_exit_func(remove_sound, "remove_sound"); _sound_installed = TRUE; return 0; } /* install_sound_input: * Initialises the sound recorder module, returning zero on success. The * two card parameters should use the DIGI_* and MIDI_* constants defined * in allegro.h. Pass DIGI_AUTODETECT and MIDI_AUTODETECT if you don't know * what the soundcard is. */ int install_sound_input(int digi, int midi) { char tmp1[64], tmp2[64]; char *sound = uconvert_ascii("sound", tmp1); _DRIVER_INFO *digi_drivers, *midi_drivers; int c; if (_sound_input_installed) return 0; if (!_sound_installed) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Sound system not installed")); return -1; } digi_recorder = NULL; midi_recorder = NULL; digi_input_card = digi; midi_input_card = midi; /* read config information */ if (digi_input_card == DIGI_AUTODETECT) digi_input_card = get_config_id(sound, uconvert_ascii("digi_input_card", tmp2), DIGI_AUTODETECT); if (midi_input_card == MIDI_AUTODETECT) midi_input_card = get_config_id(sound, uconvert_ascii("midi_input_card", tmp2), MIDI_AUTODETECT); /* search table for a good digital input driver */ usetc(allegro_error, 0); if (system_driver->digi_drivers) digi_drivers = system_driver->digi_drivers(); else digi_drivers = _digi_driver_list; for (c=0; digi_drivers[c].driver; c++) { if ((digi_drivers[c].id == digi_input_card) || (digi_input_card == DIGI_AUTODETECT)) { digi_input_driver = digi_drivers[c].driver; if (digi_input_driver->detect(TRUE)) { digi_input_card = digi_drivers[c].id; break; } else { digi_input_driver = &digi_none; if (digi_input_card != DIGI_AUTODETECT) { if (!ugetc(allegro_error)) uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s does not support audio input"), ((DIGI_DRIVER *)digi_drivers[c].driver)->name); break; } } } } /* did we find one? */ if ((digi_input_driver == &digi_none) && (digi_input_card != DIGI_NONE)) { if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Digital input driver not found")); return -1; } /* search table for a good MIDI input driver */ usetc(allegro_error, 0); if (system_driver->midi_drivers) midi_drivers = system_driver->midi_drivers(); else midi_drivers = _midi_driver_list; for (c=0; midi_drivers[c].driver; c++) { if ((midi_drivers[c].id == midi_input_card) || (midi_input_card == MIDI_AUTODETECT)) { midi_input_driver = midi_drivers[c].driver; if (midi_input_driver->detect(TRUE)) { midi_input_card = midi_drivers[c].id; break; } else { midi_input_driver = &_midi_none; if (midi_input_card != MIDI_AUTODETECT) { if (!ugetc(allegro_error)) uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s does not support MIDI input"), ((MIDI_DRIVER *)midi_drivers[c].driver)->name); break; } } } } /* did we find one? */ if ((midi_input_driver == &_midi_none) && (midi_input_card != MIDI_NONE)) { digi_input_driver = &digi_none; if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MIDI input driver not found")); return -1; } /* initialise the digital input driver */ if (digi_input_driver->init(TRUE, 0) != 0) { digi_input_driver = &digi_none; midi_input_driver = &_midi_none; if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed to init digital input driver")); return -1; } /* initialise the MIDI input driver */ if (midi_input_driver->init(TRUE, 0) != 0) { digi_input_driver->exit(TRUE); digi_input_driver = &digi_none; midi_input_driver = &_midi_none; if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed to init MIDI input driver")); return -1; } _sound_input_installed = TRUE; return 0; } /* remove_sound: * Sound module cleanup routine. */ void remove_sound(void) { int c; if (_sound_installed) { remove_sound_input(); remove_int(update_sweeps); for (c=0; cexit(); midi_driver->exit(FALSE); midi_driver = &_midi_none; digi_driver->exit(FALSE); digi_driver = &digi_none; _remove_exit_func(remove_sound); _sound_installed = FALSE; } } /* remove_sound_input: * Sound input module cleanup routine. */ void remove_sound_input(void) { if (_sound_input_installed) { digi_input_driver->exit(TRUE); digi_input_driver = &digi_none; midi_input_driver->exit(TRUE); midi_input_driver = &_midi_none; digi_recorder = NULL; midi_recorder = NULL; _sound_input_installed = FALSE; } } /* set_volume: * Alters the global sound output volume. Specify volumes for both digital * samples and MIDI playback, as integers from 0 to 255. This routine will * not alter the volume of the hardware mixer if it exists. */ void set_volume(int digi_volume, int midi_volume) { int *voice_vol; int i; if (digi_volume >= 0) { voice_vol = _AL_MALLOC_ATOMIC(sizeof(int)*VIRTUAL_VOICES); /* Retrieve the (relative) volume of each voice. */ for (i=0; i= 0) voice_set_volume(i, voice_vol[i]); } _AL_FREE(voice_vol); } if (midi_volume >= 0) _midi_volume = CLAMP(0, midi_volume, 255); } /* get_volume: * Retrieves the global sound output volume, both for digital samples and MIDI * playback, as integers from 0 to 255. Parameters digi_volume and midi_volume * must be valid pointers to int, or NULL if not interested in specific value. */ void get_volume(int *digi_volume, int *midi_volume) { if (digi_volume) (*digi_volume) = _digi_volume; if (midi_volume) (*midi_volume) = _midi_volume; } /* set_hardware_volume: * Alters the hardware sound output volume. Specify volumes for both digital * samples and MIDI playback, as integers from 0 to 255. This routine will * use the hardware mixer to control the volume if it exists, or do nothing. */ void set_hardware_volume(int digi_volume, int midi_volume) { if (digi_volume >= 0) { digi_volume = CLAMP(0, digi_volume, 255); if (digi_driver->set_mixer_volume) digi_driver->set_mixer_volume(digi_volume); } if (midi_volume >= 0) { midi_volume = CLAMP(0, midi_volume, 255); if (midi_driver->set_mixer_volume) midi_driver->set_mixer_volume(midi_volume); } } /* get_hardware_volume: * Retrieves the hardware sound output volume, both for digital samples and MIDI * playback, as integers from 0 to 255, or -1 if the information is not * available. Parameters digi_volume and midi_volume must be valid pointers to * int, or NULL if not interested in specific value. */ void get_hardware_volume(int *digi_volume, int *midi_volume) { if (digi_volume) { if (digi_driver->get_mixer_volume) { (*digi_volume) = digi_driver->get_mixer_volume(); } else { (*digi_volume) = -1; } } if (midi_volume) { if (midi_driver->get_mixer_volume) { (*midi_volume) = midi_driver->get_mixer_volume(); } else { (*midi_volume) = -1; } } } /* lock_sample: * Locks a SAMPLE struct into physical memory. Pretty important, since * they are mostly accessed inside interrupt handlers. */ void lock_sample(SAMPLE *spl) { ASSERT(spl); LOCK_DATA(spl, sizeof(SAMPLE)); LOCK_DATA(spl->data, spl->len * ((spl->bits==8) ? 1 : sizeof(short)) * ((spl->stereo) ? 2 : 1)); } /* load_voc: * Reads a mono VOC format sample file, returning a SAMPLE structure, * or NULL on error. */ SAMPLE *load_voc(AL_CONST char *filename) { PACKFILE *f; SAMPLE *spl; ASSERT(filename); f = pack_fopen(filename, F_READ); if (!f) return NULL; spl = load_voc_pf(f); pack_fclose(f); return spl; } /* load_voc_pf: * Reads a mono VOC format sample from the packfile given, returning a * SAMPLE structure, or NULL on error. If successful the offset into the * file will be left just after the sample data. If unsuccessful the offset * into the file is unspecified, i.e. you must either reset the offset to * some known place or close the packfile. The packfile is not closed by * this function. */ SAMPLE *load_voc_pf(PACKFILE *f) { char buffer[30]; int freq = 22050; int bits = 8; SAMPLE *spl = NULL; int len; int x, ver; int s; ASSERT(f); memset(buffer, 0, sizeof buffer); pack_fread(buffer, 0x16, f); if (memcmp(buffer, "Creative Voice File", 0x13)) goto getout; ver = pack_igetw(f); if (ver != 0x010A && ver != 0x0114) /* version: should be 0x010A or 0x0114 */ goto getout; ver = pack_igetw(f); if (ver != 0x1129 && ver != 0x111f) /* subversion: should be 0x1129 or 0x111f */ goto getout; ver = pack_getc(f); if (ver != 0x01 && ver != 0x09) /* sound data: should be 0x01 or 0x09 */ goto getout; len = pack_igetw(f); /* length is three bytes long: two */ x = pack_getc(f); /* .. and one byte */ x <<= 16; len += x; if (ver == 0x01) { /* block type 1 */ len -= 2; /* sub. size of the rest of block header */ x = pack_getc(f); /* one byte of frequency */ freq = 1000000 / (256-x); x = pack_getc(f); /* skip one byte */ spl = create_sample(8, FALSE, freq, len); if (spl) { if (pack_fread(spl->data, len, f) < len) { destroy_sample(spl); spl = NULL; } } } else { /* block type 9 */ len -= 12; /* sub. size of the rest of block header */ freq = pack_igetw(f); /* two bytes of frequency */ x = pack_igetw(f); /* skip two bytes */ bits = pack_getc(f); /* # of bits per sample */ if (bits != 8 && bits != 16) goto getout; x = pack_getc(f); if (x != 1) /* # of channels: should be mono */ goto getout; pack_fread(buffer, 0x6, f); /* skip 6 bytes of unknown data */ spl = create_sample(bits, FALSE, freq, len*8/bits); if (spl) { if (bits == 8) { if (pack_fread(spl->data, len, f) < len) { destroy_sample(spl); spl = NULL; } } else { len /= 2; for (x=0; xdata)[x] = (signed short)s^0x8000; } } } } getout: return spl; } /* load_wav: * Reads a RIFF WAV format sample file, returning a SAMPLE structure, * or NULL on error. */ SAMPLE *load_wav(AL_CONST char *filename) { PACKFILE *f; SAMPLE *spl; ASSERT(filename); f = pack_fopen(filename, F_READ); if (!f) return NULL; spl = load_wav_pf(f); pack_fclose(f); return spl; } /* load_wav_pf: * Reads a RIFF WAV format sample from the packfile given, returning a * SAMPLE structure, or NULL on error. * * Note that the loader does not stop reading bytes from the PACKFILE until * it sees the EOF. If you want to embed a WAV file into another file, you * will have to implement your own chunking system that stops reading at the * end of the chunk. * * If unsuccessful the offset into the file is unspecified, i.e. you must * either reset the offset to some known place or close the packfile. The * packfile is not closed by this function. */ SAMPLE *load_wav_pf(PACKFILE *f) { char buffer[25]; int i; int length, len; int freq = 22050; int bits = 8; int channels = 1; int s; SAMPLE *spl = NULL; ASSERT(f); memset(buffer, 0, sizeof buffer); pack_fread(buffer, 12, f); /* check RIFF header */ if (memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) goto getout; while (TRUE) { if (pack_fread(buffer, 4, f) != 4) break; length = pack_igetl(f); /* read chunk length */ if (memcmp(buffer, "fmt ", 4) == 0) { i = pack_igetw(f); /* should be 1 for PCM data */ length -= 2; if (i != 1) goto getout; channels = pack_igetw(f); /* mono or stereo data */ length -= 2; if ((channels != 1) && (channels != 2)) goto getout; freq = pack_igetl(f); /* sample frequency */ length -= 4; pack_igetl(f); /* skip six bytes */ pack_igetw(f); length -= 6; bits = pack_igetw(f); /* 8 or 16 bit data? */ length -= 2; if ((bits != 8) && (bits != 16)) goto getout; } else if (memcmp(buffer, "data", 4) == 0) { if (channels == 2) { /* allocate enough space even if length is odd for some reason */ len = (length + 1) / 2; } else { ASSERT(channels == 1); len = length; } if (bits == 16) len /= 2; spl = create_sample(bits, ((channels == 2) ? TRUE : FALSE), freq, len); if (spl) { if (bits == 8) { if (pack_fread(spl->data, length, f) < length) { destroy_sample(spl); spl = NULL; } } else { for (i=0; idata)[i] = (signed short)s^0x8000; } } length = 0; } } while (length > 0) { /* skip the remainder of the chunk */ if (pack_getc(f) == EOF) break; length--; } } getout: return spl; } /* create_sample: * Constructs a new sample structure of the specified type. */ SAMPLE *create_sample(int bits, int stereo, int freq, int len) { SAMPLE *spl; ASSERT(freq > 0); ASSERT(len > 0); spl = _AL_MALLOC(sizeof(SAMPLE)); if (!spl) return NULL; spl->bits = bits; spl->stereo = stereo; spl->freq = freq; spl->priority = 128; spl->len = len; spl->loop_start = 0; spl->loop_end = len; spl->param = 0; spl->data = _AL_MALLOC_ATOMIC(len * ((bits==8) ? 1 : sizeof(short)) * ((stereo) ? 2 : 1)); if (!spl->data) { _AL_FREE(spl); return NULL; } lock_sample(spl); return spl; } /* destroy_sample: * Frees a SAMPLE struct, checking whether the sample is currently playing, * and stopping it if it is. */ void destroy_sample(SAMPLE *spl) { if (spl) { stop_sample(spl); if (spl->data) { UNLOCK_DATA(spl->data, spl->len * ((spl->bits==8) ? 1 : sizeof(short)) * ((spl->stereo) ? 2 : 1)); _AL_FREE(spl->data); } UNLOCK_DATA(spl, sizeof(SAMPLE)); _AL_FREE(spl); } } /* absolute_freq: * Converts a pitch from the relative 1000 = original format to an absolute * value in hz. */ static INLINE int absolute_freq(int freq, AL_CONST SAMPLE *spl) { ASSERT(spl); if (freq == 1000) return spl->freq; else return (spl->freq * freq) / 1000; } /* play_sample: * Triggers a sample at the specified volume, pan position, and frequency. * The volume and pan range from 0 (min/left) to 255 (max/right), although * the resolution actually used by the playback routines is likely to be * less than this. Frequency is relative rather than absolute: 1000 * represents the frequency that the sample was recorded at, 2000 is * twice this, etc. If loop is true the sample will repeat until you call * stop_sample(), and can be manipulated while it is playing by calling * adjust_sample(). */ int play_sample(AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop) { int voice; ASSERT(spl); ASSERT(vol >= 0 && vol <= 255); ASSERT(pan >= 0 && pan <= 255); ASSERT(freq > 0); voice = allocate_voice(spl); if (voice >= 0) { voice_set_volume(voice, vol); voice_set_pan(voice, pan); voice_set_frequency(voice, absolute_freq(freq, spl)); voice_set_playmode(voice, (loop ? PLAYMODE_LOOP : PLAYMODE_PLAY)); voice_start(voice); release_voice(voice); } return voice; } END_OF_FUNCTION(play_sample); /* adjust_sample: * Alters the parameters of a sample while it is playing, useful for * manipulating looped sounds. You can alter the volume, pan, and * frequency, and can also remove the looping flag, which will stop * the sample when it next reaches the end of its loop. If there are * several copies of the same sample playing, this will adjust the * first one it comes across. If the sample is not playing it has no * effect. */ void adjust_sample(AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop) { int c; ASSERT(spl); for (c=0; cvoices; c++) if (_phys_voice[c].num < 0) return c; /* look for an autokill voice that has stopped */ for (c=0; cvoices; c++) { voice = virt_voice + _phys_voice[c].num; if ((voice->autokill) && (digi_driver->get_position(c) < 0)) { digi_driver->release_voice(c); voice->sample = NULL; voice->num = -1; _phys_voice[c].num = -1; return c; } } /* ok, we're going to have to get rid of something to make room... */ for (c=0; cvoices; c++) { voice = virt_voice + _phys_voice[c].num; /* sort by voice priorities */ if (voice->priority <= priority) { score = 65536 - voice->priority * 256; /* bias with a least-recently-used counter */ score += CLAMP(0, retrace_count - voice->time, 32768); /* bias according to whether the voice is looping or not */ if (!(_phys_voice[c].playmode & PLAYMODE_LOOP)) score += 32768; if (score > best_score) { best = c; best_score = score; } } } if (best >= 0) { /* kill off the old voice */ digi_driver->stop_voice(best); digi_driver->release_voice(best); virt_voice[_phys_voice[best].num].num = -1; _phys_voice[best].num = -1; return best; } return -1; } /* allocate_virtual_voice: * Allocates a virtual voice. This doesn't need to worry about killing off * others to make room, as we allow up to 256 virtual voices to be used * simultaneously. */ static INLINE int allocate_virtual_voice(void) { int num_virt_voices, c; num_virt_voices = VIRTUAL_VOICES; if (midi_driver->max_voices < 0) num_virt_voices -= midi_driver->voices; /* look for a free voice */ for (c=0; cget_position(virt_voice[c].num) < 0) { digi_driver->release_voice(virt_voice[c].num); _phys_voice[virt_voice[c].num].num = -1; virt_voice[c].sample = NULL; virt_voice[c].num = -1; return c; } } } } return -1; } /* allocate_voice: * Allocates a voice ready for playing the specified sample, returning * the voice number (note this is not the same as the physical voice * number used by the sound drivers, and must only be used with the other * voice functions, _not_ passed directly to the driver routines). * Returns -1 if there is no voice available (this should never happen, * since there are 256 virtual voices and anyone who needs more than that * needs some urgent repairs to their brain :-) */ int allocate_voice(AL_CONST SAMPLE *spl) { int phys, virt; ASSERT(spl); phys = allocate_physical_voice(spl->priority); virt = allocate_virtual_voice(); if (virt >= 0) { virt_voice[virt].sample = spl; virt_voice[virt].num = phys; virt_voice[virt].autokill = FALSE; virt_voice[virt].time = retrace_count; virt_voice[virt].priority = spl->priority; if (phys >= 0) { _phys_voice[phys].num = virt; _phys_voice[phys].playmode = 0; _phys_voice[phys].vol = ((_digi_volume >= 0) ? _digi_volume : 255) << 12; _phys_voice[phys].pan = 128 << 12; _phys_voice[phys].freq = spl->freq << 12; _phys_voice[phys].dvol = 0; _phys_voice[phys].dpan = 0; _phys_voice[phys].dfreq = 0; digi_driver->init_voice(phys, spl); } } return virt; } END_OF_FUNCTION(allocate_voice); /* deallocate_voice: * Releases a voice that was previously returned by allocate_voice(). */ void deallocate_voice(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) { digi_driver->stop_voice(virt_voice[voice].num); digi_driver->release_voice(virt_voice[voice].num); _phys_voice[virt_voice[voice].num].num = -1; virt_voice[voice].num = -1; } virt_voice[voice].sample = NULL; } END_OF_FUNCTION(deallocate_voice); /* reallocate_voice: * Switches an already-allocated voice to use a different sample. */ void reallocate_voice(int voice, AL_CONST SAMPLE *spl) { int phys; ASSERT(spl); ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); phys = virt_voice[voice].num; if (phys >= 0) { digi_driver->stop_voice(phys); digi_driver->release_voice(phys); } virt_voice[voice].sample = spl; virt_voice[voice].autokill = FALSE; virt_voice[voice].time = retrace_count; virt_voice[voice].priority = spl->priority; if (phys >= 0) { _phys_voice[phys].playmode = 0; _phys_voice[phys].vol = ((_digi_volume >= 0) ? _digi_volume : 255) << 12; _phys_voice[phys].pan = 128 << 12; _phys_voice[phys].freq = spl->freq << 12; _phys_voice[phys].dvol = 0; _phys_voice[phys].dpan = 0; _phys_voice[phys].dfreq = 0; digi_driver->init_voice(phys, spl); } } END_OF_FUNCTION(reallocate_voice); /* release_voice: * Flags that a voice is no longer going to be updated, so it can * automatically be freed as soon as the sample finishes playing. */ void release_voice(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); virt_voice[voice].autokill = TRUE; } END_OF_FUNCTION(release_voice); /* voice_start: * Starts a voice playing. */ void voice_start(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) digi_driver->start_voice(virt_voice[voice].num); virt_voice[voice].time = retrace_count; } END_OF_FUNCTION(voice_start); /* voice_stop: * Stops a voice from playing. */ void voice_stop(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) digi_driver->stop_voice(virt_voice[voice].num); } END_OF_FUNCTION(voice_stop); /* voice_set_priority: * Adjusts the priority of a voice (0-255). */ void voice_set_priority(int voice, int priority) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(priority >= 0 && priority <= 255); virt_voice[voice].priority = priority; } END_OF_FUNCTION(voice_set_priority); /* voice_check: * Checks whether a voice is playing, returning the sample if it is, * or NULL if it has finished or been preempted by a different sound. */ SAMPLE *voice_check(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].sample) { if (virt_voice[voice].num < 0) return NULL; if (virt_voice[voice].autokill) if (voice_get_position(voice) < 0) return NULL; return (SAMPLE*)virt_voice[voice].sample; } else return NULL; } END_OF_FUNCTION(voice_check); /* voice_get_position: * Returns the current play position of a voice, or -1 if that cannot * be determined (because it has finished or been preempted by a * different sound). */ int voice_get_position(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) return digi_driver->get_position(virt_voice[voice].num); else return -1; } END_OF_FUNCTION(voice_get_position); /* voice_set_position: * Sets the play position of a voice. */ void voice_set_position(int voice, int position) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) digi_driver->set_position(virt_voice[voice].num, position); } END_OF_FUNCTION(voice_set_position); /* voice_set_playmode: * Sets the loopmode of a voice. */ void voice_set_playmode(int voice, int playmode) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].playmode = playmode; digi_driver->loop_voice(virt_voice[voice].num, playmode); if (playmode & PLAYMODE_BACKWARD) digi_driver->set_position(virt_voice[voice].num, virt_voice[voice].sample->len-1); } } END_OF_FUNCTION(voice_set_playmode); /* voice_get_volume: * Returns the current volume of a voice, or -1 if that cannot * be determined (because it has finished or been preempted by a * different sound). */ int voice_get_volume(int voice) { int vol; ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) vol = digi_driver->get_volume(virt_voice[voice].num); else vol = -1; if ((vol >= 0) && (_digi_volume >= 0)) { if (_digi_volume > 0) vol = CLAMP(0, (vol * 255) / _digi_volume, 255); else vol = 0; } return vol; } END_OF_FUNCTION(voice_get_volume); /* voice_set_volume: * Sets the current volume of a voice. */ void voice_set_volume(int voice, int volume) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(volume >= 0 && volume <= 255); if (_digi_volume >= 0) volume = (volume * _digi_volume) / 255; if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].vol = volume << 12; _phys_voice[virt_voice[voice].num].dvol = 0; digi_driver->set_volume(virt_voice[voice].num, volume); } } END_OF_FUNCTION(voice_set_volume); /* voice_ramp_volume: * Begins a volume ramp operation. */ void voice_ramp_volume(int voice, int time, int endvol) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(endvol >= 0 && endvol <= 255); ASSERT(time >= 0); if (_digi_volume >= 0) endvol = (endvol * _digi_volume) / 255; if (virt_voice[voice].num >= 0) { if (digi_driver->ramp_volume) { digi_driver->ramp_volume(virt_voice[voice].num, time, endvol); } else { int d = (endvol << 12) - _phys_voice[virt_voice[voice].num].vol; time = MAX(time * SWEEP_FREQ / 1000, 1); _phys_voice[virt_voice[voice].num].target_vol = endvol << 12; _phys_voice[virt_voice[voice].num].dvol = d / time; } } } END_OF_FUNCTION(voice_ramp_volume); /* voice_stop_volumeramp: * Ends a volume ramp operation. */ void voice_stop_volumeramp(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].dvol = 0; if (digi_driver->stop_volume_ramp) digi_driver->stop_volume_ramp(virt_voice[voice].num); } } END_OF_FUNCTION(voice_stop_volumeramp); /* voice_get_frequency: * Returns the current frequency of a voice, or -1 if that cannot * be determined (because it has finished or been preempted by a * different sound). */ int voice_get_frequency(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) return digi_driver->get_frequency(virt_voice[voice].num); else return -1; } END_OF_FUNCTION(voice_get_frequency); /* voice_set_frequency: * Sets the pitch of a voice. */ void voice_set_frequency(int voice, int frequency) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(frequency > 0); if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].freq = frequency << 12; _phys_voice[virt_voice[voice].num].dfreq = 0; digi_driver->set_frequency(virt_voice[voice].num, frequency); } } END_OF_FUNCTION(voice_set_frequency); /* voice_sweep_frequency: * Begins a frequency sweep (glissando) operation. */ void voice_sweep_frequency(int voice, int time, int endfreq) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(endfreq > 0); ASSERT(time >= 0); if (virt_voice[voice].num >= 0) { if (digi_driver->sweep_frequency) { digi_driver->sweep_frequency(virt_voice[voice].num, time, endfreq); } else { int d = (endfreq << 12) - _phys_voice[virt_voice[voice].num].freq; time = MAX(time * SWEEP_FREQ / 1000, 1); _phys_voice[virt_voice[voice].num].target_freq = endfreq << 12; _phys_voice[virt_voice[voice].num].dfreq = d / time; } } } END_OF_FUNCTION(voice_sweep_frequency); /* voice_stop_frequency_sweep: * Ends a frequency sweep. */ void voice_stop_frequency_sweep(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].dfreq = 0; if (digi_driver->stop_frequency_sweep) digi_driver->stop_frequency_sweep(virt_voice[voice].num); } } END_OF_FUNCTION(voice_stop_frequency_sweep); /* voice_get_pan: * Returns the current pan position of a voice, or -1 if that cannot * be determined (because it has finished or been preempted by a * different sound). */ int voice_get_pan(int voice) { int pan; ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) pan = digi_driver->get_pan(virt_voice[voice].num); else pan = -1; if ((pan >= 0) && (_sound_flip_pan)) pan = 255 - pan; return pan; } END_OF_FUNCTION(voice_get_pan); /* voice_set_pan: * Sets the pan position of a voice. */ void voice_set_pan(int voice, int pan) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(pan >= 0 && pan <= 255); if (_sound_flip_pan) pan = 255 - pan; if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].pan = pan << 12; _phys_voice[virt_voice[voice].num].dpan = 0; digi_driver->set_pan(virt_voice[voice].num, pan); } } END_OF_FUNCTION(voice_set_pan); /* voice_sweep_pan: * Begins a pan sweep (left <-> right movement) operation. */ void voice_sweep_pan(int voice, int time, int endpan) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); ASSERT(endpan >= 0 && endpan <= 255); ASSERT(time >= 0); if (_sound_flip_pan) endpan = 255 - endpan; if (virt_voice[voice].num >= 0) { if (digi_driver->sweep_pan) { digi_driver->sweep_pan(virt_voice[voice].num, time, endpan); } else { int d = (endpan << 12) - _phys_voice[virt_voice[voice].num].pan; time = MAX(time * SWEEP_FREQ / 1000, 1); _phys_voice[virt_voice[voice].num].target_pan = endpan << 12; _phys_voice[virt_voice[voice].num].dpan = d / time; } } } END_OF_FUNCTION(voice_sweep_pan); /* voice_stop_pan_sweep: * Ends a pan sweep. */ void voice_stop_pan_sweep(int voice) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if (virt_voice[voice].num >= 0) { _phys_voice[virt_voice[voice].num].dpan = 0; if (digi_driver->stop_pan_sweep) digi_driver->stop_pan_sweep(virt_voice[voice].num); } } END_OF_FUNCTION(voice_stop_pan_sweep); /* voice_set_echo: * Sets the echo parameters of a voice. */ void voice_set_echo(int voice, int strength, int delay) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if ((virt_voice[voice].num >= 0) && (digi_driver->set_echo)) digi_driver->set_echo(virt_voice[voice].num, strength, delay); } END_OF_FUNCTION(voice_set_echo); /* voice_set_tremolo: * Sets the tremolo parameters of a voice. */ void voice_set_tremolo(int voice, int rate, int depth) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if ((virt_voice[voice].num >= 0) && (digi_driver->set_tremolo)) digi_driver->set_tremolo(virt_voice[voice].num, rate, depth); } END_OF_FUNCTION(voice_set_tremolo); /* voice_set_vibrato: * Sets the vibrato parameters of a voice. */ void voice_set_vibrato(int voice, int rate, int depth) { ASSERT(voice >= 0 && voice < VIRTUAL_VOICES); if ((virt_voice[voice].num >= 0) && (digi_driver->set_vibrato)) digi_driver->set_vibrato(virt_voice[voice].num, rate, depth); } END_OF_FUNCTION(voice_set_vibrato); /* update_sweeps: * Timer callback routine used to implement volume/frequency/pan sweep * effects, for those drivers that can't do them directly. */ static void update_sweeps(void) { int phys_voices, i; phys_voices = digi_driver->voices; if (midi_driver->max_voices < 0) phys_voices += midi_driver->voices; for (i=0; i= 0) { /* update volume ramp */ if ((!digi_driver->ramp_volume) && (_phys_voice[i].dvol)) { _phys_voice[i].vol += _phys_voice[i].dvol; if (((_phys_voice[i].dvol > 0) && (_phys_voice[i].vol >= _phys_voice[i].target_vol)) || ((_phys_voice[i].dvol < 0) && (_phys_voice[i].vol <= _phys_voice[i].target_vol))) { _phys_voice[i].vol = _phys_voice[i].target_vol; _phys_voice[i].dvol = 0; } digi_driver->set_volume(i, _phys_voice[i].vol >> 12); } /* update frequency sweep */ if ((!digi_driver->sweep_frequency) && (_phys_voice[i].dfreq)) { _phys_voice[i].freq += _phys_voice[i].dfreq; if (((_phys_voice[i].dfreq > 0) && (_phys_voice[i].freq >= _phys_voice[i].target_freq)) || ((_phys_voice[i].dfreq < 0) && (_phys_voice[i].freq <= _phys_voice[i].target_freq))) { _phys_voice[i].freq = _phys_voice[i].target_freq; _phys_voice[i].dfreq = 0; } digi_driver->set_frequency(i, _phys_voice[i].freq >> 12); } /* update pan sweep */ if ((!digi_driver->sweep_pan) && (_phys_voice[i].dpan)) { _phys_voice[i].pan += _phys_voice[i].dpan; if (((_phys_voice[i].dpan > 0) && (_phys_voice[i].pan >= _phys_voice[i].target_pan)) || ((_phys_voice[i].dpan < 0) && (_phys_voice[i].pan <= _phys_voice[i].target_pan))) { _phys_voice[i].pan = _phys_voice[i].target_pan; _phys_voice[i].dpan = 0; } digi_driver->set_pan(i, _phys_voice[i].pan >> 12); } } } } END_OF_STATIC_FUNCTION(update_sweeps); /* get_sound_input_cap_bits: * Recording capabilities: number of bits */ int get_sound_input_cap_bits(void) { return digi_input_driver->rec_cap_bits; } /* get_sound_input_cap_stereo: * Recording capabilities: stereo */ int get_sound_input_cap_stereo(void) { return digi_input_driver->rec_cap_stereo; } /* get_sound_input_cap_rate: * Recording capabilities: maximum sampling rate */ int get_sound_input_cap_rate(int bits, int stereo) { if (digi_input_driver->rec_cap_rate) return digi_input_driver->rec_cap_rate(bits, stereo); else return 0; } /* get_sound_input_cap_parm: * Checks whether given parameters can be set. */ int get_sound_input_cap_parm(int rate, int bits, int stereo) { if (digi_input_driver->rec_cap_parm) return digi_input_driver->rec_cap_parm(rate, bits, stereo); else return 0; } /* set_sound_input_source: * Selects the sampling source for audio recording. */ int set_sound_input_source(int source) { if (digi_input_driver->rec_source) return digi_input_driver->rec_source(source); else return -1; } /* start_sound_input: * Starts recording, and returns recording buffer size. */ int start_sound_input(int rate, int bits, int stereo) { if (digi_input_driver->rec_start) return digi_input_driver->rec_start(rate, bits, stereo); else return 0; } /* stop_sound_input: * Ends recording. */ void stop_sound_input(void) { if (digi_input_driver->rec_stop) digi_input_driver->rec_stop(); } /* read_sound_input: * Reads audio data. */ int read_sound_input(void *buffer) { if (digi_input_driver->rec_read) return digi_input_driver->rec_read(buffer); else return 0; } END_OF_FUNCTION(read_sound_input); /* sound_lock_mem: * Locks memory used by the functions in this file. */ static void sound_lock_mem(void) { LOCK_VARIABLE(digi_none); LOCK_VARIABLE(_midi_none); LOCK_VARIABLE(digi_card); LOCK_VARIABLE(midi_card); LOCK_VARIABLE(digi_driver); LOCK_VARIABLE(midi_driver); LOCK_VARIABLE(digi_recorder); LOCK_VARIABLE(midi_recorder); LOCK_VARIABLE(virt_voice); LOCK_VARIABLE(_phys_voice); LOCK_VARIABLE(_digi_volume); LOCK_VARIABLE(_midi_volume); LOCK_VARIABLE(_sound_flip_pan); LOCK_VARIABLE(_sound_hq); LOCK_FUNCTION(_dummy_detect); LOCK_FUNCTION(play_sample); LOCK_FUNCTION(adjust_sample); LOCK_FUNCTION(stop_sample); LOCK_FUNCTION(allocate_voice); LOCK_FUNCTION(deallocate_voice); LOCK_FUNCTION(reallocate_voice); LOCK_FUNCTION(voice_start); LOCK_FUNCTION(voice_stop); LOCK_FUNCTION(voice_set_priority); LOCK_FUNCTION(voice_check); LOCK_FUNCTION(voice_get_position); LOCK_FUNCTION(voice_set_position); LOCK_FUNCTION(voice_set_playmode); LOCK_FUNCTION(voice_get_volume); LOCK_FUNCTION(voice_set_volume); LOCK_FUNCTION(voice_ramp_volume); LOCK_FUNCTION(voice_stop_volumeramp); LOCK_FUNCTION(voice_get_frequency); LOCK_FUNCTION(voice_set_frequency); LOCK_FUNCTION(voice_sweep_frequency); LOCK_FUNCTION(voice_stop_frequency_sweep); LOCK_FUNCTION(voice_get_pan); LOCK_FUNCTION(voice_set_pan); LOCK_FUNCTION(voice_sweep_pan); LOCK_FUNCTION(voice_stop_pan_sweep); LOCK_FUNCTION(voice_set_echo); LOCK_FUNCTION(voice_set_tremolo); LOCK_FUNCTION(voice_set_vibrato); LOCK_FUNCTION(update_sweeps); LOCK_FUNCTION(read_sound_input); } allegro-4.4.3.1/src/fontbmp.c0000664000175000017500000001343613437077643014707 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Read font from a bitmap. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* state information for the bitmap font importer */ static int import_x = 0; static int import_y = 0; /* splits bitmaps into sub-sprites, using regions bounded by col #255 */ static void font_find_character(BITMAP *bmp, int *x, int *y, int *w, int *h) { int c; if (_bitmap_has_alpha(bmp)) { c = getpixel(bmp, 0, 0); } else if (bitmap_color_depth(bmp) == 8) { c = 255; } else { c = makecol_depth(bitmap_color_depth(bmp), 255, 255, 0); } /* look for top left corner of character */ while ((getpixel(bmp, *x, *y) != c) || (getpixel(bmp, *x+1, *y) != c) || (getpixel(bmp, *x, *y+1) != c) || (getpixel(bmp, *x+1, *y+1) == c)) { (*x)++; if (*x >= bmp->w) { *x = 0; (*y)++; if (*y >= bmp->h) { *w = 0; *h = 0; return; } } } /* look for right edge of character */ *w = 0; while ((getpixel(bmp, *x+*w+1, *y) == c) && (getpixel(bmp, *x+*w+1, *y+1) != c) && (*x+*w+1 <= bmp->w)) (*w)++; /* look for bottom edge of character */ *h = 0; while ((getpixel(bmp, *x, *y+*h+1) == c) && (getpixel(bmp, *x+1, *y+*h+1) != c) && (*y+*h+1 <= bmp->h)) (*h)++; } /* import_bitmap_font_mono: * Helper for import_bitmap_font, below. */ static int import_bitmap_font_mono(BITMAP *import_bmp, FONT_GLYPH** gl, int num) { int w = 1, h = 1, i; for(i = 0; i < num; i++) { if(w > 0 && h > 0) font_find_character(import_bmp, &import_x, &import_y, &w, &h); if(w <= 0 || h <= 0) { int j; gl[i] = _AL_MALLOC(sizeof(FONT_GLYPH) + 8); gl[i]->w = 8; gl[i]->h = 8; for(j = 0; j < 8; j++) gl[i]->dat[j] = 0; } else { int sx = ((w + 7) / 8), j, k; gl[i] = _AL_MALLOC(sizeof(FONT_GLYPH) + sx * h); gl[i]->w = w; gl[i]->h = h; for(j = 0; j < sx * h; j++) gl[i]->dat[j] = 0; for(j = 0; j < h; j++) { for(k = 0; k < w; k++) { if(getpixel(import_bmp, import_x + k + 1, import_y + j + 1)) gl[i]->dat[(j * sx) + (k / 8)] |= 0x80 >> (k & 7); } } import_x += w; } } return 0; } /* import_bitmap_font_color: * Helper for import_bitmap_font, below. */ static int import_bitmap_font_color(BITMAP *import_bmp, BITMAP** bits, int num) { int w = 1, h = 1, i; for(i = 0; i < num; i++) { if(w > 0 && h > 0) font_find_character(import_bmp, &import_x, &import_y, &w, &h); if(w <= 0 || h <= 0) { bits[i] = create_bitmap_ex(bitmap_color_depth(import_bmp), 8, 8); if(!bits[i]) return -1; clear_to_color(bits[i], 255); } else { bits[i] = create_bitmap_ex(bitmap_color_depth(import_bmp), w, h); if(!bits[i]) return -1; blit(import_bmp, bits[i], import_x + 1, import_y + 1, 0, 0, w, h); import_x += w; } } return 0; } /* bitmap_font_ismono: * Helper for import_bitmap_font, below. */ static int bitmap_font_ismono(BITMAP *bmp) { int x, y, col = -1, pixel; for(y = 0; y < bmp->h; y++) { for(x = 0; x < bmp->w; x++) { pixel = getpixel(bmp, x, y); if(pixel == 0 || pixel == 255) continue; if(col > 0 && pixel != col) return 0; col = pixel; } } return 1; } /* bitmap_font_count: * Helper for `import_bitmap_font', below. */ static int bitmap_font_count(BITMAP* bmp) { int x = 0, y = 0, w = 0, h = 0; int num = 0; while (1) { font_find_character(bmp, &x, &y, &w, &h); if (w <= 0 || h <= 0) break; num++; x += w; } return num; } /* import routine for the Allegro .pcx font format */ FONT *load_bitmap_font(AL_CONST char *fname, RGB *pal, void *param) { /* NB: `end' is -1 if we want every glyph */ int color_conv_mode; BITMAP *import_bmp; FONT *f; ASSERT(fname); /* Don't change the colourdepth of the bitmap if it is 8 bit */ color_conv_mode = get_color_conversion(); set_color_conversion(COLORCONV_MOST | COLORCONV_KEEP_TRANS); import_bmp = load_bitmap(fname, pal); set_color_conversion(color_conv_mode); if(!import_bmp) return NULL; f = grab_font_from_bitmap(import_bmp); destroy_bitmap(import_bmp); return f; } /* work horse for grabbing a font from an Allegro bitmap */ FONT *grab_font_from_bitmap(BITMAP *bmp) { int begin = ' '; int end = -1; FONT *f; ASSERT(bmp) import_x = 0; import_y = 0; f = _AL_MALLOC(sizeof *f); if (end == -1) end = bitmap_font_count(bmp) + begin; if (bitmap_font_ismono(bmp)) { FONT_MONO_DATA* mf = _AL_MALLOC(sizeof(FONT_MONO_DATA)); mf->glyphs = _AL_MALLOC(sizeof(FONT_GLYPH*) * (end - begin)); if ( import_bitmap_font_mono(bmp, mf->glyphs, end - begin) ) { _AL_FREE(mf->glyphs); _AL_FREE(mf); _AL_FREE(f); f = NULL; } else { f->data = mf; f->vtable = font_vtable_mono; f->height = mf->glyphs[0]->h; mf->begin = begin; mf->end = end; mf->next = NULL; } } else { FONT_COLOR_DATA* cf = _AL_MALLOC(sizeof(FONT_COLOR_DATA)); cf->bitmaps = _AL_MALLOC(sizeof(BITMAP*) * (end - begin)); if( import_bitmap_font_color(bmp, cf->bitmaps, end - begin) ) { _AL_FREE(cf->bitmaps); _AL_FREE(cf); _AL_FREE(f); f = 0; } else { f->data = cf; f->vtable = font_vtable_color; f->height = cf->bitmaps[0]->h; cf->begin = begin; cf->end = end; cf->next = 0; } } return f; } allegro-4.4.3.1/src/psp/0000775000175000017500000000000013437077643013671 5ustar siegesiegeallegro-4.4.3.1/src/psp/pjoy.c0000664000175000017500000000744313437077643015026 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Joystick driver routines for PSP. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #include #ifndef ALLEGRO_PSP #error something is wrong with the makefile #endif #define PREFIX_I "al-pjoy INFO: " #define PREFIX_W "al-pjoy WARNING: " #define PREFIX_E "al-pjoy ERROR: " /* The PSP controller no directional buttons. */ struct _PSP_BUTTON { char *name; enum PspCtrlButtons code; } psp_controller_buttons[] = { {"TRIANGLE", PSP_CTRL_TRIANGLE}, {"CIRCLE", PSP_CTRL_CIRCLE}, {"CROSS", PSP_CTRL_CROSS}, {"SQUARE", PSP_CTRL_SQUARE}, {"LTRIGGER", PSP_CTRL_LTRIGGER}, {"RTRIGGER", PSP_CTRL_RTRIGGER}, {"SELECT", PSP_CTRL_SELECT}, {"START", PSP_CTRL_START} }; #define NBUTTONS (sizeof psp_controller_buttons / sizeof psp_controller_buttons[0]) static int psp_joy_init(void); static void psp_joy_exit(void); static int psp_joy_poll(void); JOYSTICK_DRIVER joystick_psp = { JOYSTICK_PSP, // int id; empty_string, // AL_CONST char *name; empty_string, // AL_CONST char *desc; "PSP Digital Pad", // AL_CONST char *ascii_name; psp_joy_init, // AL_METHOD(int, init, (void)); psp_joy_exit, // AL_METHOD(void, exit, (void)); psp_joy_poll, // AL_METHOD(int, poll, (void)); NULL, // AL_METHOD(int, save_data, (void)); NULL, // AL_METHOD(int, load_data, (void)); NULL, // AL_METHOD(AL_CONST char *, calibrate_name, (int n)); NULL // AL_METHOD(int, calibrate, (int n)); }; /* psp_joy_init: * Initializes the PSP joystick driver. */ static int psp_joy_init(void) { uint8_t b; _psp_init_controller(SAMPLING_CYCLE, SAMPLING_MODE); num_joysticks = 1; for (b=0; b #include #include #include #ifndef ALLEGRO_PSP #error something is wrong with the makefile #endif #define DEFAULT_SCREEN_WIDTH 480 #define DEFAULT_SCREEN_HEIGHT 272 #define DEFAULT_COLOR_DEPTH 16 static int psp_sys_init(void); static void psp_sys_exit(void); static void psp_message(AL_CONST char *msg); static void psp_created_sub_bitmap(BITMAP *bmp, BITMAP *parent); static void psp_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); SYSTEM_DRIVER system_psp = { SYSTEM_PSP, empty_string, empty_string, "PlayStation Portable", psp_sys_init, psp_sys_exit, NULL, /* AL_METHOD(void, get_executable_name, (char *output, int size)); */ NULL, /* AL_METHOD(int, find_resource, (char *dest, AL_CONST char *resource, int size)); */ NULL, /* AL_METHOD(void, set_window_title, (AL_CONST char *name)); */ NULL, /* AL_METHOD(int, set_close_button_callback, (AL_METHOD(void, proc, (void)))); */ psp_message, /* AL_METHOD(void, message, (AL_CONST char *msg)); */ NULL, /* AL_METHOD(void, assert, (AL_CONST char *msg)); */ NULL, /* AL_METHOD(void, save_console_state, (void)); */ NULL, /* AL_METHOD(void, restore_console_state, (void)); */ NULL, /* AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); */ NULL, /* AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); */ NULL, /* AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); */ psp_created_sub_bitmap, /* AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); */ NULL, /* AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); */ NULL, /* AL_METHOD(void, read_hardware_palette, (void)); */ NULL, /* AL_METHOD(void, set_palette_range, (AL_CONST struct RGB *p, int from, int to, int retracesync)); */ NULL, /* AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); */ NULL, /* AL_METHOD(int, set_display_switch_mode, (int mode)); */ NULL, /* AL_METHOD(void, display_switch_lock, (int lock, int foreground)); */ NULL, /* AL_METHOD(int, desktop_color_depth, (void)); */ NULL, /* AL_METHOD(int, get_desktop_resolution, (int *width, int *height)); */ psp_get_gfx_safe_mode, /*AL_METHOD(void, get_gfx_safe_mode, (int *driver, struct GFX_MODE *mode));*/ NULL, /* AL_METHOD(void, yield_timeslice, (void)); */ NULL, /* AL_METHOD(void *, create_mutex, (void)); */ NULL, /* AL_METHOD(void, destroy_mutex, (void *handle)); */ NULL, /* AL_METHOD(void, lock_mutex, (void *handle)); */ NULL, /* AL_METHOD(void, unlock_mutex, (void *handle)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); */ NULL, /* AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); */ NULL /* AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); */ }; /* psp_sys_init: * Initializes the PSP system driver. */ static int psp_sys_init(void) { /* Setup OS type & version */ os_type = OSTYPE_PSP; return 0; } /* psp_sys_exit: * Shuts down the system driver. */ static void psp_sys_exit(void) { sceKernelExitGame(); } /* psp_message: * Prints a text message in the PSP system dependent format. */ static void psp_message(AL_CONST char *msg) { SceCtrlData pad; int buffers_to_read = 1; pspDebugScreenInit(); pspDebugScreenPrintf(msg); /* The message is displayed until a button is pressed. */ _psp_init_controller(SAMPLING_CYCLE, SAMPLING_MODE); do { sceCtrlPeekBufferPositive(&pad, buffers_to_read); } while (!pad.Buttons); } /* psp_create_bitmap: * Creates a RAM bitmap with proper PSP pitch. */ BITMAP * psp_create_bitmap(int color_depth, int width, int height) { GFX_VTABLE *vtable; BITMAP *bitmap; int nr_pointers; int i; int pitch; vtable = _get_vtable(color_depth); if (!vtable) return NULL; /* We need at least two pointers when drawing, otherwise we get crashes with * Electric Fence. We think some of the assembly code assumes a second line * pointer is always available. */ nr_pointers = MAX(2, height); bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers)); if (!bitmap) return NULL; /* The memory bitmap width must be multiple of 8 pixels * in order to blit properly using sceGuCopyImage(). */ pitch = ALIGN_TO(width, 8); //bitmap->dat = memalign(64, pitch * height * BYTES_PER_PIXEL(color_depth)); bitmap->dat = _AL_MALLOC_ATOMIC(pitch * height * BYTES_PER_PIXEL(color_depth)); if (!bitmap->dat) { _AL_FREE(bitmap); return NULL; } bitmap->w = bitmap->cr = width; bitmap->h = bitmap->cb = height; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->vtable = vtable; bitmap->write_bank = bitmap->read_bank = _stub_bank_switch; bitmap->id = 0; bitmap->x_ofs = 0; bitmap->y_ofs = 0; bitmap->seg = _default_ds(); if (height > 0) { bitmap->line[0] = bitmap->dat; for (i=1; iline[i] = bitmap->line[i-1] + pitch * BYTES_PER_PIXEL(color_depth); } /* Setup info structure to store additional information. */ bitmap->extra = malloc(sizeof(struct BMP_EXTRA_INFO)); if (!bitmap->extra) { _AL_FREE(bitmap); return NULL; } BMP_EXTRA(bitmap)->pitch = pitch; return bitmap; } /* psp_created_sub_bitmap: * Set the needed sub bitmap info. */ static void psp_created_sub_bitmap(BITMAP *bmp, BITMAP *parent) { if (BMP_EXTRA(parent)) { bmp->extra = malloc(sizeof(struct BMP_EXTRA_INFO)); if (bmp->extra) BMP_EXTRA(bmp)->pitch = BMP_EXTRA(parent)->pitch; } } /* psp_destroy_bitmap: * Destroys the bitmap extra info structure. */ int psp_destroy_bitmap(BITMAP *bitmap) { _AL_FREE(bitmap->extra); return 0; } /* psp_get_gfx_safe_mode: * Defines the safe graphics mode for this system. */ static void psp_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode) { *driver = GFX_PSP; mode->width = DEFAULT_SCREEN_WIDTH; mode->height = DEFAULT_SCREEN_HEIGHT; mode->bpp = DEFAULT_COLOR_DEPTH; } allegro-4.4.3.1/src/psp/pmain.c0000664000175000017500000000363613437077643015151 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Replacement for the Allegro program main() function to execute * the PSP stuff: call the PSP_* macros and create the standard * exit callback. * * By diedel. * * See readme.txt for copyright information. */ #include extern void *_mangled_main_address; /* Define the module info section */ PSP_MODULE_INFO("Allegro Application", PSP_MODULE_USER, 1, 1); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); PSP_MAIN_THREAD_STACK_SIZE_KB(270); PSP_HEAP_SIZE_KB(-256); /* exit_callback: * */ static int exit_callback(int arg1, int arg2, void *common) { sceKernelExitGame(); return 0; } /* callback_thread: * Registers the exit callback. */ static int callback_thread(SceSize args, void *argp) { int cbid = sceKernelCreateCallback("Exit Callback", (void *) exit_callback, NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return 0; } /* setup_callback: * Sets up the callback thread and returns its thread id. */ static int setup_callback(void) { int thid = 0; thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0); if (thid >= 0) { sceKernelStartThread(thid, 0, 0); } return thid; } /* main: * Replacement for main function. */ int main(int argc, char *argv[]) { int (*real_main) (int, char *[]) = (int (*) (int, char *[])) _mangled_main_address; setup_callback(); return (*real_main)(argc, argv); } allegro-4.4.3.1/src/psp/pmouse.c0000664000175000017500000001175113437077643015352 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PSP mouse driver. * TODO:. * * By sauron_le_noir some part of psp_mouse_timer_poll based on * the sdl code of Nekuz0r * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #include "math.h" #include #ifndef ALLEGRO_PSP #error something is wrong with the makefile #endif static int psp_mouse_init(void); static void psp_mouse_exit(void); static void psp_mouse_position(int, int); static void psp_mouse_set_range(int, int, int, int); static void psp_mouse_get_mickeys(int *, int *); static void psp_mouse_timer_poll(void); MOUSE_DRIVER mouse_psp = { MOUSE_PSP, empty_string, empty_string, "psp mouse", psp_mouse_init, psp_mouse_exit, NULL, // AL_METHOD(void, poll, (void)); psp_mouse_timer_poll, // AL_METHOD(void, timer_poll, (void)); psp_mouse_position, psp_mouse_set_range, NULL, // AL_METHOD(void, set_speed, (int xspeed, int yspeed)); psp_mouse_get_mickeys, NULL, // AL_METHOD(int, analyse_data, (AL_CONST char *buffer, int size)); NULL, // AL_METHOD(void, enable_hardware_cursor, (AL_CONST int mode)); NULL // AL_METHOD(int, select_system_cursor, (AL_CONST int cursor)); }; static int mouse_minx = 0; static int mouse_miny = 0; static int mouse_maxx = 479; /* 0 to 479 = 480 */ static int mouse_maxy = 271; /* 0 to 272 = 272 */ /* 480x272 is the resolution of the psp display */ static SceCtrlData pad; static int aStickX = 0; static int aStickY = 0; static float aStickR; static float aStickA; static int x,y; static float Precision = 360.0f; static int getSqrRadius(int X, int Y) { return sqrt((X * X) + (Y * Y)); } static int psp_mouse_init(void) { sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); return 3; //Num of buttons. } static void psp_mouse_timer_poll(void) { sceCtrlPeekBufferPositive(&pad, 1); if (pad.Buttons != 0) { sceCtrlReadBufferPositive(&pad, 1); _mouse_b = 0; if (pad.Buttons & PSP_CTRL_LTRIGGER) _mouse_b = 1; if (pad.Buttons & PSP_CTRL_RTRIGGER) _mouse_b = 2; if ( (pad.Buttons & PSP_CTRL_LTRIGGER) && (pad.Buttons & PSP_CTRL_RTRIGGER)) _mouse_b = 4; } aStickX = pad.Ly - 128; aStickY = pad.Lx - 128; aStickR = getSqrRadius(aStickX, aStickY); if (aStickR > 100) { if (getSqrRadius(aStickX, aStickY) > 30) { aStickA = ((atan2f(aStickX, -aStickY) + M_PI) / (M_PI * 2)) * Precision; } else { aStickA = -1; } //1° a 89° if (aStickA >= 1 && aStickA <= (89 * (Precision / 360.0f))) { x += (10 * (1 - (aStickA / (Precision / 360.0f) / 90))); y -= (10 * (0 + (aStickA / (Precision / 360.0f) / 90))); } else if (aStickA >= (91 * (Precision / 360.0f)) && aStickA <= (179 * (Precision / 360.0f))) { x -= (10 * (0 + (((aStickA / (Precision / 360.0f)) - 89) / 90))); y -= (10 * (1 - (((aStickA / (Precision / 360.0f)) - 89) / 90))); } else if (aStickA >= (181 * (Precision / 360.0f)) && aStickA <= (269 * (Precision / 360.0f))) { x -= (10 * (1 - (((aStickA / (Precision / 360.0f)) - 179) / 90))); y += (10 * (0 + (((aStickA / (Precision / 360.0f)) - 179) / 90))); } else if (aStickA >= (271 * (Precision / 360.0f)) && aStickA <= (359 * (Precision / 360.0f))) { x += (10 * (0 + (((aStickA / (Precision / 360.0f)) - 269) / 90))); y += (10 * (1 - (((aStickA / (Precision / 360.0f)) - 269) / 90))); } else if (aStickA == 0) { x += 10; } else if (aStickA == (90 * (Precision / 360.0f))) { y -= 10; } else if (aStickA == (180 * (Precision / 360.0f))) { x -= 10; } else if (aStickR == (270 * (Precision / 360.0f))) { y += 10; } } if (x < 0) x = 0; if (x > 479) x = 479; if (y < 0) y = 0; if (y > 271) y = 271; _mouse_x = x; _mouse_y = y; } static void psp_mouse_position(int x, int y) { _mouse_x = x; if (_mouse_x < mouse_minx) _mouse_x = 0; if (_mouse_x > mouse_maxx) _mouse_x = mouse_maxx; _mouse_y = y; if (_mouse_y < mouse_miny) _mouse_y = 0; if (_mouse_y > mouse_maxy) _mouse_y = mouse_maxy; } static void psp_mouse_set_range(int x1, int y1, int x2, int y2) { } static void psp_mouse_get_mickeys(int *mickeyx, int *mickeyy) { *mickeyx = 0; *mickeyy = 0; } static void psp_mouse_exit(void) { } allegro-4.4.3.1/src/psp/ptimer.c0000664000175000017500000000570013437077643015337 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Timer driver for the PSP. * TODO: Thread synchronization. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include #include #define TIMER_TO_USEC(t) ((SceUInt)((float)(t) / TIMERS_PER_SECOND * 1000000)) #define PSPTIMER_TO_TIMER(t) ((int)((t) * (TIMERS_PER_SECOND / (float)psp_tick_resolution))) static int psp_timer_thread(); static int psp_timer_init(void); static void psp_timer_exit(void); static uint32_t psp_tick_resolution; static int psp_timer_on = FALSE; static SceUID timer_thread_UID; TIMER_DRIVER timer_psp = { TIMER_PSP, empty_string, empty_string, "PSP timer", psp_timer_init, psp_timer_exit, NULL, NULL, /* install_int, remove_int */ NULL, NULL, /* install_param_int, remove_param_int */ NULL, NULL, /* can_simulate_retrace, simulate_retrace */ NULL /* rest */ }; /* psp_timer_thread: * This PSP thread measures the elapsed time. */ static int psp_timer_thread() { uint64_t old_tick, new_tick; int interval; long delay; sceRtcGetCurrentTick(&old_tick); while (psp_timer_on) { /* Calculate actual time elapsed. */ sceRtcGetCurrentTick(&new_tick); interval = PSPTIMER_TO_TIMER(new_tick - old_tick); old_tick = new_tick; /* Handle a tick and rest. */ delay = _handle_timer_tick(interval); sceKernelDelayThreadCB(TIMER_TO_USEC(delay)); } sceKernelExitThread(0); return 0; } /* psp_timer_init: * Installs the PSP timer thread. */ static int psp_timer_init(void) { /* Get the PSP ticks per second */ psp_tick_resolution = sceRtcGetTickResolution(); psp_timer_on = TRUE; timer_thread_UID = sceKernelCreateThread("psp_timer_thread",(void *)&psp_timer_thread, 0x18, 0x10000, 0, NULL); if (timer_thread_UID < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot create timer thread")); psp_timer_exit(); return -1; } if (sceKernelStartThread(timer_thread_UID, 0, NULL) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot start timer thread")); psp_timer_exit(); return -1; } return 0; } /* psp_timer_exit: * Shuts down the PSP timer thread. */ static void psp_timer_exit(void) { psp_timer_on = FALSE; sceKernelDeleteThread(timer_thread_UID); return; } allegro-4.4.3.1/src/psp/psound.c0000664000175000017500000001244613437077643015354 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PSP digital sound driver using the Allegro mixer. * TODO: Audio input support. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #include #include #ifndef ALLEGRO_PSP #error something is wrong with the makefile #endif #define IS_SIGNED TRUE /* The PSP DSP reads signed sampled data */ #define SAMPLES_PER_BUFFER 1024 static int psp_audio_channel_thread(); static int digi_psp_detect(int); static int digi_psp_init(int, int); static void digi_psp_exit(int); static int digi_psp_buffer_size(); //static int digi_psp_set_mixer_volume(int); static int psp_audio_on = FALSE; static SceUID audio_thread_UID; static int hw_channel; /* The active PSP hardware output channel */ static short sound_buffer[2][SAMPLES_PER_BUFFER][2]; int curr_buffer=0; DIGI_DRIVER digi_psp = { DIGI_PSP, empty_string, empty_string, "PSP digital sound driver", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, digi_psp_detect, digi_psp_init, digi_psp_exit, NULL, //digi_psp_set_mixer_volume, NULL, NULL, NULL, digi_psp_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* psp_audio_channel_thread: * This PSP thread manages the audio playing. */ static int psp_audio_channel_thread() { while (psp_audio_on) { void *bufptr = &sound_buffer[curr_buffer]; /* Asks to the Allegro mixer to fill the buffer */ _mix_some_samples((uintptr_t)bufptr, 0, IS_SIGNED); /* Send mixed buffer to sound card */ sceAudioOutputPannedBlocking(hw_channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, bufptr); curr_buffer = !curr_buffer; } sceKernelExitThread(0); return 0; } /* digi_psp_detect: * Returns TRUE if the audio hardware is present. */ static int digi_psp_detect(int input) { if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } return TRUE; } /* digi_psp_init: * Initializes the PSP digital sound driver. */ static int digi_psp_init(int input, int voices) { char digi_psp_desc[512] = EMPTY_STRING; char tmp1[256]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } hw_channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, SAMPLES_PER_BUFFER, PSP_AUDIO_FORMAT_STEREO); if (hw_channel < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed reserving hardware sound channel")); return -1; } psp_audio_on = TRUE; audio_thread_UID = sceKernelCreateThread("psp_audio_thread", (void *)&psp_audio_channel_thread, 0x19, 0x10000, 0, NULL); if (audio_thread_UID < 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot create audio thread")); digi_psp_exit(FALSE); return -1; } if (sceKernelStartThread(audio_thread_UID, 0, NULL) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot start audio thread")); digi_psp_exit(FALSE); return -1; } /* Allegro sound state variables */ _sound_bits = 16; _sound_stereo = TRUE; _sound_freq = 44100; digi_psp.voices = voices; if (_mixer_init(SAMPLES_PER_BUFFER * 2, _sound_freq, _sound_stereo, (_sound_bits == 16), &digi_psp.voices)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error initializing mixer")); digi_psp_exit(FALSE); return -1; } uszprintf(digi_psp_desc, sizeof(digi_psp_desc), get_config_text("%d bits, %d bps, %s"), _sound_bits, _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp1)); digi_psp.desc = digi_psp_desc; return 0; } /* digi_psp_exit: * Shuts down the sound driver. */ static void digi_psp_exit(int input) { if (input) return; psp_audio_on = FALSE; sceKernelDeleteThread(audio_thread_UID); sceAudioChRelease(hw_channel); _mixer_exit(); } static int digi_psp_buffer_size() { return SAMPLES_PER_BUFFER; } /* static int digi_set_mixer_volume(int volume) { return sceAudioChangeChannelVolume(int channel, int leftvol, int rightvol); } */ allegro-4.4.3.1/src/psp/pvram.c0000664000175000017500000001130713437077643015164 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Video memory manager routines for the PSP. * * By diedel, heavily based upon Minix OS code. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #define PREFIX_I "al-pvram INFO: " #define PREFIX_W "al-pvram WARNING: " #define PREFIX_E "al-pvram ERROR: " /* Pointer to the first element of the holes list. */ static VRAM_HOLE *hole_head; static void vmm_del_slot(VRAM_HOLE *prev_ptr, VRAM_HOLE *hp); static void vmm_merge(VRAM_HOLE *hp); /* vmm_init: * Initializes the vram holes list. * Initially this list contains an element with the available video memory. */ void vmm_init(uintptr_t base, unsigned int available_vram) { VRAM_HOLE *new_h; new_h = _AL_MALLOC(sizeof(VRAM_HOLE)); if (new_h) { new_h->h_base = base; new_h->h_len = available_vram; new_h->h_next = NULL; hole_head = new_h; } TRACE(PREFIX_I "Available VRAM: %u bytes Base: %x\n", new_h->h_len, new_h->h_base); } /* vmm_alloc_mem: * Assigns a free video memory block from the first hole with enough space. */ uintptr_t vmm_alloc_mem(unsigned int size) { VRAM_HOLE *hp, *prev_ptr = NULL; uintptr_t old_base; hp = hole_head; while (hp != NULL) { if (hp->h_len >= size) { /* We have found a hole big enough. */ old_base = hp->h_base; hp->h_base += size; hp->h_len -= size; if (hp->h_len == 0) /* The hole has no more space. Update the holes list. */ vmm_del_slot(prev_ptr, hp); TRACE(PREFIX_I "%u bytes assigned starting at %x\n", size, old_base); return old_base; } prev_ptr = hp; hp = hp->h_next; } return VMM_NO_MEM; } /* vmm_free_mem: * Returns a video memory block to the holes list. * If it's adjacent to some of the existing holes we merge it. */ void vmm_free_mem(uintptr_t base, unsigned int size) { VRAM_HOLE *hp, *new_ptr, *prev_ptr; new_ptr = _AL_MALLOC(sizeof(VRAM_HOLE)); if (new_ptr) { new_ptr->h_base = base; new_ptr->h_len = size; TRACE(PREFIX_I "New hole: %u bytes at %x\n", new_ptr->h_len, new_ptr->h_base); hp = hole_head; if (hp == NULL || base <= hp->h_base) { /* The free block becomes the head of the holes list. */ new_ptr->h_next = hp; hole_head = new_ptr; vmm_merge(new_ptr); } else { while ( hp != NULL && base > hp->h_base) { prev_ptr = hp; hp = hp->h_next; } /* Insert it after prev_ptr. */ new_ptr->h_next = prev_ptr->h_next; prev_ptr->h_next = new_ptr; /* We try to merge the sequence 'prev_ptr', 'new_ptr', 'hp' */ vmm_merge(prev_ptr); } } } /* vmm_del_slot: * Destroy an element of the holes list. */ static void vmm_del_slot(VRAM_HOLE *prev_ptr, VRAM_HOLE *hp) { TRACE(PREFIX_I "Slot deleted: %u bytes at %x\n", hp->h_len, hp->h_base); if (hp == hole_head) hole_head = hp->h_next; else prev_ptr->h_next = hp->h_next; _AL_FREE(hp); } /* vmm_merge: * Try to merge a freed video memory block with the adjacent holes. * 'hp' is the first of a three holes chain potentially mergeable. */ static void vmm_merge(VRAM_HOLE *hp) { VRAM_HOLE *next_ptr; if ((next_ptr = hp->h_next) != NULL) { if (hp->h_base + hp->h_len == next_ptr->h_base) { /* The first absorbs the second. */ TRACE(PREFIX_I "Hole 1 %u bytes at %x merged with hole 2 %u bytes at %x\n", hp->h_len, hp->h_base, next_ptr->h_len, next_ptr->h_base); hp->h_len += next_ptr->h_len; vmm_del_slot(hp, next_ptr); } else hp = next_ptr; /* Now try to merge with the third. */ if ((next_ptr = hp->h_next) != NULL) { if (hp->h_base + hp->h_len == next_ptr->h_base) { /* Absorb the third. */ TRACE(PREFIX_I "Hole 1/2 %u bytes at %x merged with hole 3 %u bytes at %x\n", hp->h_len, hp->h_base, next_ptr->h_len, next_ptr->h_base); hp->h_len += next_ptr->h_len; vmm_del_slot(hp, next_ptr); } } } } allegro-4.4.3.1/src/psp/pdrivers.c0000664000175000017500000000366313437077643015703 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * List of PSP drivers. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #ifndef ALLEGRO_PSP #error Something is wrong with the makefile #endif _DRIVER_INFO _system_driver_list[] = { { SYSTEM_PSP, &system_psp, TRUE }, { SYSTEM_NONE, &system_none, FALSE }, { 0, NULL, 0 } }; _DRIVER_INFO _keyboard_driver_list[] = { { KEYSIM_PSP, &keybd_simulator_psp, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _timer_driver_list[] = { { TIMER_PSP, &timer_psp, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _mouse_driver_list[] = { { MOUSE_PSP, &mouse_psp, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _gfx_driver_list[] = { { GFX_PSP, &gfx_psp, TRUE }, { 0, NULL, 0 } }; _DRIVER_INFO _digi_driver_list[] = { { DIGI_PSP, &digi_psp, TRUE }, { 0, NULL, 0 } }; BEGIN_MIDI_DRIVER_LIST MIDI_DRIVER_DIGMID END_MIDI_DRIVER_LIST BEGIN_JOYSTICK_DRIVER_LIST { JOYSTICK_PSP, &joystick_psp, TRUE }, END_JOYSTICK_DRIVER_LIST allegro-4.4.3.1/src/psp/pkey.c0000664000175000017500000000726613437077643015020 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PSP mini-keyboard driver using the PSP controller. * TODO: Maybe implement it using the OSK. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #include #ifndef ALLEGRO_PSP #error Something is wrong with the makefile #endif #define PREFIX_I "al-pkey INFO: " #define PREFIX_W "al-pkey WARNING: " #define PREFIX_E "al-pkey ERROR: " static int psp_keyboard_init(void); static void psp_keyboard_exit(void); static void psp_poll_keyboard(void); /* * Lookup table for converting PSP_CTRL_* codes into Allegro KEY_* codes * TODO: Choose an alternative mapping? */ static const int psp_to_scancode[][2] = { { PSP_CTRL_SELECT, KEY_ESC }, { PSP_CTRL_START, KEY_ENTER }, { PSP_CTRL_UP, KEY_UP }, { PSP_CTRL_RIGHT, KEY_RIGHT }, { PSP_CTRL_DOWN, KEY_DOWN }, { PSP_CTRL_LEFT, KEY_LEFT }, { PSP_CTRL_TRIANGLE, KEY_LCONTROL }, { PSP_CTRL_CIRCLE, KEY_ALT }, { PSP_CTRL_CROSS, KEY_SPACE }, { PSP_CTRL_SQUARE, KEY_TAB }, { PSP_CTRL_LTRIGGER, KEY_LSHIFT }, { PSP_CTRL_RTRIGGER, KEY_RSHIFT } }; #define NKEYS (sizeof psp_to_scancode / sizeof psp_to_scancode[0]) /* The last polled input. */ static SceCtrlData old_pad = {0, 0, 0, 0, {0,0,0,0,0,0}}; KEYBOARD_DRIVER keybd_simulator_psp = { KEYSIM_PSP, empty_string, empty_string, "PSP keyboard simulator", FALSE, // int autorepeat; psp_keyboard_init, psp_keyboard_exit, psp_poll_keyboard, NULL, // AL_METHOD(void, set_leds, (int leds)); NULL, // AL_METHOD(void, set_rate, (int delay, int rate)); NULL, // AL_METHOD(void, wait_for_input, (void)); NULL, // AL_METHOD(void, stop_waiting_for_input, (void)); NULL, // AL_METHOD(int, scancode_to_ascii, (int scancode)); NULL // scancode_to_name }; /* psp_keyboard_init: * Installs the keyboard handler. */ static int psp_keyboard_init(void) { _psp_init_controller(SAMPLING_CYCLE, SAMPLING_MODE); TRACE(PREFIX_I "PSP keyboard installed\n"); /* TODO: Maybe write a keyboard "interrupt" handler using a dedicated thread * that polls the PSP controller periodically. */ return 0; } /* psp_keyboard_exit: * Removes the keyboard handler. */ static void psp_keyboard_exit(void) { } /* psp_poll_keyboard: * Polls the PSP "mini-keyboard". */ static void psp_poll_keyboard(void) { SceCtrlData pad; int buffers_to_read = 1; uint8_t i; int changed; sceCtrlPeekBufferPositive(&pad, buffers_to_read); for (i = 0; i < NKEYS; i++) { changed = (pad.Buttons ^ old_pad.Buttons) & psp_to_scancode[i][0]; if (changed) { if (pad.Buttons & psp_to_scancode[i][0]) { TRACE(PREFIX_I "PSP Keyboard: [%d] pressed\n", psp_to_scancode[i][1]); _handle_key_press(scancode_to_ascii(psp_to_scancode[i][1]), psp_to_scancode[i][1]); } else { TRACE(PREFIX_I "PSP Keyboard: [%d] released\n", psp_to_scancode[i][1]); _handle_key_release(psp_to_scancode[i][1]); } } } old_pad = pad; } allegro-4.4.3.1/src/psp/pfile.c0000664000175000017500000000313413437077643015135 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Helper routines to make file.c work on PSP platform. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #ifndef ALLEGRO_PSP #error Something is wrong with the makefile #endif int _al_file_isok(AL_CONST char *filename) { return TRUE; } uint64_t _al_file_size_ex(AL_CONST char *filename) { struct stat s; char tmp[1024]; if (stat(uconvert(filename, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } return s.st_size; } time_t _al_file_time(AL_CONST char *filename) { struct stat s; char tmp[1024]; if (stat(uconvert(filename, U_CURRENT, tmp, U_UTF8, sizeof(tmp)), &s) != 0) { *allegro_errno = errno; return 0; } return s.st_mtime; } void _al_getdcwd(int drive, char *buf, int size) { } int al_findfirst(AL_CONST char *pattern, struct al_ffblk *info, int attrib) { return 0; } int al_findnext(struct al_ffblk *info) { return 0; } void al_findclose(struct al_ffblk *info) { } void _al_detect_filename_encoding(void) { } allegro-4.4.3.1/src/psp/pgfx.c0000664000175000017500000005353013437077643015007 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PSP gfx driver. * * By diedel. * * The psp_draw_to_screen() routine is based on the Basilisk II * PSP refresh routines by J.F. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #include #include #include #include #ifndef ALLEGRO_PSP #error something is wrong with the makefile #endif #define MAX_SCR_WIDTH (480) #define MAX_SCR_HEIGHT (272) #define MIN_BUF_WIDTH (512) #define PALETTE_PIXEL_SIZE (4) #define VIDEO_REFRESH_RATE (60) #define DISPLAY_SIZE (MIN_BUF_WIDTH * MAX_SCR_HEIGHT * PALETTE_PIXEL_SIZE) /* The width in pixels of the display framebuffer. */ static unsigned int framebuf_width; /* The PSP pixel format. */ static int gu_psm_format; /* Pointer to the texture area actually displayed onto the screen. * Only for the 8 bpp mode. */ static unsigned char *texture_start; /* Number of vertical black pulses at the start of * a triple buffering operation. */ static unsigned int vcount_start = 0; static unsigned int __attribute__((aligned(16))) list[16384]; /* The current palette in 8 bpp mode. */ static unsigned int __attribute__((aligned(16))) clut[256]; struct TEX_VERTEX { unsigned short u, v; short x, y, z; }; /* Software version of some blitting methods */ static void (*_orig_blit) (BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static BITMAP *psp_display_init(int w, int h, int v_w, int v_h, int color_depth); static void gfx_psp_enable_acceleration(GFX_VTABLE *vtable); static void gfx_psp_enable_triple_buffering(GFX_DRIVER *drv); static void setup_gu(void); static int psp_scroll(int x, int y); static void psp_vsync(void); static void psp_hw_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); static void psp_set_palette(AL_CONST RGB *p, int from, int to, int retracesync); static int psp_request_scroll(int x, int y); static int psp_poll_scroll(void); static BITMAP *psp_create_video_bitmap(int width, int height); static void psp_destroy_video_bitmap(BITMAP *bitmap); static int psp_show_video_bitmap(BITMAP *bitmap); static int psp_request_video_bitmap(BITMAP *bitmap); GFX_DRIVER gfx_psp = { GFX_PSP, empty_string, empty_string, "PSP gfx driver", psp_display_init, /* AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); */ NULL, /* AL_METHOD(void, exit, (struct BITMAP *b)); */ psp_scroll, /* AL_METHOD(int, scroll, (int x, int y)); */ psp_vsync, /* AL_METHOD(void, vsync, (void)); */ psp_set_palette, /* AL_METHOD(void, set_palette, (AL_CONST struct RGB *p, int from, int to, int retracesync)); */ NULL, /* AL_METHOD(int, request_scroll, (int x, int y)); */ NULL, /* AL_METHOD(int, poll_scroll, (void)); */ NULL, /* AL_METHOD(void, enable_triple_buffer, (void)); */ psp_create_video_bitmap, /* AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); */ psp_destroy_video_bitmap, /* AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); */ psp_show_video_bitmap, /* AL_METHOD(int, show_video_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, request_video_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(BITMAP *, create_system_bitmap, (int width, int height)); */ NULL, /* AL_METHOD(void, destroy_system_bitmap, (BITMAP *bitmap)); */ NULL, /* AL_METHOD(int, set_mouse_sprite, (BITMAP *sprite, int xfocus, int yfocus)); */ NULL, /* AL_METHOD(int, show_mouse, (BITMAP *bmp, int x, int y)); */ NULL, /* AL_METHOD(void, hide_mouse, (void)); */ NULL, /* AL_METHOD(void, move_mouse, (int x, int y)); */ NULL, /* AL_METHOD(void, drawing_mode, (void)); */ NULL, /* AL_METHOD(void, save_video_state, (void)); */ NULL, /* AL_METHOD(void, restore_video_state, (void)); */ NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */ NULL, /* AL_METHOD(int, fetch_mode_list, (void)); */ 0, 0, /* physical (not virtual!) screen size */ TRUE, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ FALSE /* true if driver runs windowed */ }; /* psp_display_init: * Initializes the gfx mode. */ static BITMAP *psp_display_init(int w, int h, int v_w, int v_h, int color_depth) { GFX_VTABLE *vtable = _get_vtable(color_depth); BITMAP *psp_screen; uintptr_t vram_start, screen_start; int available_vram, framebuf_height, framebuf_size; int top_margin, left_margin, bytes_per_line; switch (color_depth) { case 8: gu_psm_format = GU_PSM_T8; break; case 15: gu_psm_format = GU_PSM_5551; break; case 16: gu_psm_format = GU_PSM_5650; break; case 32: gu_psm_format = GU_PSM_8888; break; default: ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if (w > MAX_SCR_WIDTH || h > MAX_SCR_HEIGHT) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); return NULL; } /* Virtual screen management. */ if (v_w < w) v_w = w; if (v_h < h) v_h = h; if ( (gu_psm_format != GU_PSM_T8) && ((v_w > w && w < MAX_SCR_WIDTH) || (v_h > h && h < MAX_SCR_HEIGHT)) ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen not valid")); return NULL; } /* How many VRAM we need? */ available_vram = sceGeEdramGetSize(); vram_start = (uintptr_t)sceGeEdramGetAddr(); if (gu_psm_format == GU_PSM_T8) { /* To support the 8 bpp mode we have to set the framebuffer as * a palettized texture outside the display area. */ available_vram -= DISPLAY_SIZE; vram_start += DISPLAY_SIZE; screen_start = vram_start; texture_start = (unsigned char *)screen_start; framebuf_width = ALIGN_TO(v_w, 16); framebuf_height = v_h; } else { framebuf_width = ALIGN_TO(v_w ,64); framebuf_width = MAX(MIN_BUF_WIDTH, framebuf_width); framebuf_height = MAX(MAX_SCR_HEIGHT, v_h); /* Center the screen. */ top_margin = (MAX_SCR_HEIGHT - h) / 2; left_margin = (MAX_SCR_WIDTH - w) / 2; screen_start = vram_start + (top_margin * framebuf_width + left_margin) * BYTES_PER_PIXEL(color_depth); screen_start |= 0x40000000; } bytes_per_line = framebuf_width * BYTES_PER_PIXEL(color_depth); framebuf_size = framebuf_height * bytes_per_line; if ( framebuf_size > available_vram) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen size too large")); return NULL; } /* Create the Allegro screen bitmap. */ psp_screen = _make_bitmap(v_w, v_h, screen_start, &gfx_psp, color_depth, bytes_per_line); if (psp_screen) psp_screen->extra = _AL_MALLOC(sizeof(struct BMP_EXTRA_INFO)); if (!psp_screen || !psp_screen->extra) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } /* Used in the scrolling routines. */ BMP_EXTRA(psp_screen)->hw_addr = vram_start; available_vram -= framebuf_size; vram_start += framebuf_size; BMP_EXTRA(psp_screen)->pitch = framebuf_width; /* Initialize the PSP video. */ setup_gu(); _set_current_refresh_rate(VIDEO_REFRESH_RATE); /* Initialize the video memory manager. */ vmm_init(vram_start, available_vram); /* physical (not virtual!) screen size */ gfx_psp.w = psp_screen->cr = w; gfx_psp.h = psp_screen->cb = h; if (gu_psm_format == GU_PSM_T8) { /* Special routines to manage the 8 bpp color depth. */ vtable->do_stretch_blit = psp_do_stretch_blit8; memcpy(&_screen_vtable, &psp_vtable8, sizeof(GFX_VTABLE)); } else { /* Only supported in truecolor modes. */ gfx_psp_enable_acceleration(vtable); gfx_psp_enable_triple_buffering(&gfx_psp); } displayed_video_bitmap = psp_screen; return psp_screen; } /* gfx_psp_enable_acceleration: * Installs and activates some routines to accelerate Allegro. */ static void gfx_psp_enable_acceleration(GFX_VTABLE *vtable) { /* Keep the original blitting methods */ _orig_blit = vtable->blit_to_self; /* Accelerated blits. */ vtable->blit_from_memory = psp_hw_blit; vtable->blit_to_memory = psp_hw_blit; vtable->blit_from_system = psp_hw_blit; vtable->blit_to_system = psp_hw_blit; vtable->blit_to_self = psp_hw_blit; _screen_vtable.blit_from_memory = psp_hw_blit; _screen_vtable.blit_to_memory = psp_hw_blit; _screen_vtable.blit_from_system = psp_hw_blit; _screen_vtable.blit_to_system = psp_hw_blit; _screen_vtable.blit_to_self = psp_hw_blit; /* Supporting routines. */ system_driver->create_bitmap = psp_create_bitmap; system_driver->destroy_bitmap = psp_destroy_bitmap; gfx_capabilities |= (GFX_HW_VRAM_BLIT | GFX_HW_MEM_BLIT); } /* gfx_psp_enable_triple_buffering: * Installs the triple buffering capability. */ static void gfx_psp_enable_triple_buffering(GFX_DRIVER *drv) { drv->request_scroll = psp_request_scroll; drv->poll_scroll = psp_poll_scroll; drv->request_video_bitmap = psp_request_video_bitmap; gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; } /* setup_gu: * Initializes the PSP graphics hardware. */ static void setup_gu(void) { sceGuInit(); sceGuStart(GU_DIRECT, list); if (gu_psm_format == GU_PSM_T8) { sceGuDrawBuffer(GU_PSM_8888, 0, MIN_BUF_WIDTH); sceGuDispBuffer(MAX_SCR_WIDTH, MAX_SCR_HEIGHT, 0, MIN_BUF_WIDTH); } else { sceGuDrawBuffer(gu_psm_format, 0, framebuf_width); sceGuDispBuffer(MAX_SCR_WIDTH, MAX_SCR_HEIGHT, 0, framebuf_width); } sceGuScissor(0, 0, MAX_SCR_WIDTH, MAX_SCR_HEIGHT); sceGuEnable(GU_SCISSOR_TEST); sceGuEnable(GU_TEXTURE_2D); sceGuClear(GU_COLOR_BUFFER_BIT); sceGuFinish(); sceGuSync(0,0); sceDisplayWaitVblankStart(); sceGuDisplay(GU_TRUE); } /* psp_scroll: * PSP scrolling routine. * This handle horizontal scrolling in 8 pixel increments under 15 or 16 * bpp modes and 4 pixel increments under 32 bpp mode. * The 8 bpp mode has no restrictions. */ static int psp_scroll(int x, int y) { uintptr_t new_addr; if (_wait_for_vsync) sceDisplayWaitVblankStart(); if (gu_psm_format == GU_PSM_T8) { /* We position the texture data pointer at the requested coordinates * and the screen display is updated. */ displayed_video_bitmap = screen; texture_start = screen->line[y] + x; psp_draw_to_screen(); } else { /* Truecolor pixel formats. */ new_addr = BMP_EXTRA(screen)->hw_addr + (y * framebuf_width + x) * BYTES_PER_PIXEL(bitmap_color_depth(screen)); sceDisplaySetFrameBuf((void *)new_addr, framebuf_width, gu_psm_format, PSP_DISPLAY_SETBUF_IMMEDIATE); } return 0; } /* psp_vsync: * Waits for a retrace. */ void psp_vsync(void) { sceDisplayWaitVblankStart(); } /* psp_hw_blit: * PSP accelerated blitting routine. */ static void psp_hw_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { void *source_ptr, *dest_ptr; /* sceGuCopyImage() can transfer blocks of size <=1024x1024. * Also the pitch of the source and destination buffers is limited * to 2048 pixels. */ if (width > 1024 || height > 1024 || BMP_EXTRA(source)->pitch > 2048 || BMP_EXTRA(dest)->pitch > 2048) return _orig_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height); /* We position the pixel data pointers at the requested coordinates * and we align it to 16 bytes. The x,y coordinates are modified accordly. */ source_ptr = source->line[source_y] + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source)); source_x = ((unsigned int)source_ptr & 0xF) / BYTES_PER_PIXEL(bitmap_color_depth(source)); source_y = 0; source_ptr = (void *)((unsigned int)source_ptr & ~0xF); dest_ptr = dest->line[dest_y] + dest_x * BYTES_PER_PIXEL(bitmap_color_depth(dest)); dest_x = ((unsigned int)dest_ptr & 0xF) / BYTES_PER_PIXEL(bitmap_color_depth(dest)); dest_y = 0; dest_ptr = (void *)((unsigned int)dest_ptr & ~0xF); /* The interesting part. */ sceKernelDcacheWritebackAll(); sceGuStart(GU_DIRECT,list); sceGuCopyImage(gu_psm_format, source_x, source_y, width, height, BMP_EXTRA(source)->pitch, source_ptr, dest_x, dest_y, BMP_EXTRA(dest)->pitch, dest_ptr); sceGuFinish(); sceGuSync(0,0); } /* psp_draw_to_screen: * ONLY in 8 bpp video mode. * Draws the texture representing the screen to the PSP display * maximizing the use of the texture-cache. */ void psp_draw_to_screen() { unsigned short texture_x; unsigned char *texture_ptr; short dest_x, dest_y; int slice_w = 64; int num_slices = ceil(SCREEN_W/(float)(slice_w)); int i; struct TEX_VERTEX *vertices; /* We align the texture data pointer to 16 bytes. * The texture u coordinate is modified accordly. */ texture_x = (unsigned int)texture_start & 0xF; texture_ptr = (unsigned char *)((unsigned int)texture_start & ~0xF); /* Blit the texture at the center of the screen. */ dest_x = (MAX_SCR_WIDTH - SCREEN_W) / 2; dest_y = (MAX_SCR_HEIGHT - SCREEN_H) / 2; sceKernelDcacheWritebackAll(); sceGuStart(GU_DIRECT,list); sceGuTexMode(GU_PSM_T8,0,0,0); sceGuTexImage(0, 512, 512, framebuf_width, texture_ptr); sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); sceGuTexFilter(GU_LINEAR, GU_LINEAR); for (i=0; i < num_slices; i++) { vertices = (struct TEX_VERTEX*)sceGuGetMemory(2 * sizeof(struct TEX_VERTEX)); vertices[0].u = texture_x + i * slice_w; vertices[0].v = 0; vertices[1].u = vertices[0].u + slice_w; if (vertices[1].u > texture_x + SCREEN_W) vertices[1].u = texture_x + SCREEN_W; vertices[1].v = vertices[0].v + SCREEN_H; vertices[0].x = dest_x + i * slice_w; vertices[0].y = dest_y; vertices[0].z = 0; vertices[1].x = vertices[0].x + slice_w; if (vertices[1].x > dest_x + SCREEN_W) vertices[1].x = dest_x + SCREEN_W; vertices[1].y = vertices[0].y + SCREEN_H; vertices[1].z = 0; sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D, 2,0,vertices); } sceGuFinish(); sceGuSync(0,0); } /* psp_set_palette: * Sets the hardware palette for the 8 bpp video mode. */ static void psp_set_palette(AL_CONST RGB *p, int from, int to, int retracesync) { int c; /* Update the palette. */ for (c=from; c<=to; c++) { clut[c] = makecol32(_rgb_scale_6[p[c].r], _rgb_scale_6[p[c].g], _rgb_scale_6[p[c].b]); } sceKernelDcacheWritebackAll(); if (retracesync) sceDisplayWaitVblankStart(); sceGuStart(GU_DIRECT,list); sceGuClutMode(GU_PSM_8888,0,0xff,0); /* 32-bit palette */ sceGuClutLoad((256/8),clut); /* upload 32 blocks of 8 entries (256) */ sceGuFinish(); sceGuSync(0,0); psp_draw_to_screen(); } /* psp_request_scroll: * Attempts to initiate a triple buffered hardware scroll, which will * take place during the next retrace. Returns 0 on success. */ static int psp_request_scroll(int x, int y) { uintptr_t new_addr; new_addr = BMP_EXTRA(screen)->hw_addr + (y * framebuf_width + x) * BYTES_PER_PIXEL(bitmap_color_depth(screen)); vcount_start = sceDisplayGetVcount(); sceDisplaySetFrameBuf((void *)new_addr, framebuf_width, gu_psm_format, PSP_DISPLAY_SETBUF_NEXTFRAME); return 0; } /* psp_poll_scroll: * This function is used for triple buffering. It checks the status of * a hardware scroll previously initiated by the request_scroll() or by * the request_video_bitmap() routines. */ static int psp_poll_scroll(void) { int ret; /* A new vertical blank pulse has arrived? */ if (sceDisplayGetVcount() - vcount_start > 0) { vcount_start = 0; ret = 0; } else ret = -1; return ret; } /* psp_create_video_bitmap: * Attempts to make a bitmap object for accessing offscreen video memory. */ static BITMAP *psp_create_video_bitmap(int width, int height) { uintptr_t vram_addr, bitmap_offset = 0; GFX_VTABLE *vtable; BITMAP *bitmap; int pitch, used_height = height; int i, size, top_margin, left_margin; if (_color_depth == 8) { if (width >= SCREEN_W && height >= SCREEN_H) /* This video bitmap or the derived sub bitmaps can be used for * page flipping. The pitch is calculated so that sceGuTexImage() * works correctly in that case. */ pitch = ALIGN_TO(width, 16); else /* A regular 8 bpp video bitmap. */ pitch = width; } else { if (width == SCREEN_W && height == SCREEN_H) { /* Special code for video bitmaps created under truecolor modes that * can be used with the show_video_bitmap() and request_video_bitmap() * functions for page flipping and triple buffering. */ pitch = MIN_BUF_WIDTH; used_height = MAX_SCR_HEIGHT; /* Center the bitmap. */ top_margin = (MAX_SCR_HEIGHT - height) / 2; left_margin = (MAX_SCR_WIDTH - width) / 2; bitmap_offset = (top_margin * MIN_BUF_WIDTH + left_margin) * BYTES_PER_PIXEL(_color_depth); } else /* A regular truecolor video bitmap. * Its width must be multiple of 8 pixels in order to * blit properly using sceGuCopyImage(). */ pitch = ALIGN_TO(width, 8); } /* Allocate video memory for the pixel data. */ size = pitch * used_height * BYTES_PER_PIXEL(_color_depth); vram_addr = vmm_alloc_mem(size); if (!vram_addr) return NULL; /* Clean it. */ for (i=0; iw = bitmap->cr = width; bitmap->h = bitmap->cb = height; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->vtable = vtable; bitmap->write_bank = bitmap->read_bank = _stub_bank_switch; bitmap->id = BMP_ID_VIDEO; bitmap->x_ofs = 0; bitmap->y_ofs = 0; bitmap->seg = _video_ds(); if (height > 0) { bitmap->line[0] = (unsigned char *)(vram_addr + bitmap_offset); for (i=1; iline[i] = bitmap->line[i-1] + pitch * BYTES_PER_PIXEL(_color_depth); } /* Setup info structure to store additional information. */ bitmap->extra = _AL_MALLOC(sizeof(struct BMP_EXTRA_INFO)); if (!bitmap->extra) { vmm_free_mem(vram_addr, size); _AL_FREE(bitmap); return NULL; } BMP_EXTRA(bitmap)->pitch = pitch; BMP_EXTRA(bitmap)->size = size; BMP_EXTRA(bitmap)->hw_addr = vram_addr; return bitmap; } /* psp_destroy_video_bitmap: * Restores the video ram used for the video bitmap and the system ram * used for the bitmap management structures. */ static void psp_destroy_video_bitmap(BITMAP *bitmap) { if (!is_sub_bitmap(bitmap)) vmm_free_mem(BMP_EXTRA(bitmap)->hw_addr, BMP_EXTRA(bitmap)->size); _AL_FREE(bitmap->extra); _AL_FREE(bitmap); } /* psp_show_video_bitmap: * Page flipping function: swaps to display the specified video memory * bitmap object (this must be the same size as the physical screen). */ int psp_show_video_bitmap(BITMAP *bitmap) { if (_wait_for_vsync) sceDisplayWaitVblankStart(); if (gu_psm_format == GU_PSM_T8) { /* We position the texture data pointer at the new bitmap * and the screen display is updated. */ displayed_video_bitmap = bitmap; texture_start = bitmap->line[0]; psp_draw_to_screen(); } else { /* Truecolor pixel formats. */ /* No sub bitmaps are allowed. */ if (is_sub_bitmap(bitmap)) return -1; sceDisplaySetFrameBuf((void *)BMP_EXTRA(bitmap)->hw_addr, BMP_EXTRA(bitmap)->pitch, gu_psm_format, PSP_DISPLAY_SETBUF_IMMEDIATE); } return 0; } /* psp_request_video_bitmap: * Triple buffering function: triggers a swap to display the specified * video memory bitmap object, which will take place on the next retrace. */ static int psp_request_video_bitmap(BITMAP *bitmap) { /* No sub bitmaps are allowed. */ if (is_sub_bitmap(bitmap)) return -1; vcount_start = sceDisplayGetVcount(); sceDisplaySetFrameBuf((void *)BMP_EXTRA(bitmap)->hw_addr, BMP_EXTRA(bitmap)->pitch, gu_psm_format, PSP_DISPLAY_SETBUF_NEXTFRAME); return 0; } allegro-4.4.3.1/src/psp/pvtable8.c0000664000175000017500000001775213437077643015576 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * PSP screen gfx vtable for 8 bpp support. * * By diedel. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintpsp.h" #define CONSTRUCT_8BPP_VERSION(type, func, args, params) \ type psp_##func##8 args \ { \ bmp->vtable = &__linear_vtable8; \ \ /* Call the original function. */ \ __linear_vtable8.func params ; \ \ if (is_same_bitmap(bmp, displayed_video_bitmap)) \ /* Show the screen texture. */ \ psp_draw_to_screen(); \ \ bmp->vtable = &psp_vtable8; \ } CONSTRUCT_8BPP_VERSION(void, putpixel, (BITMAP *bmp, int x, int y, int color), (bmp, x, y, color)); CONSTRUCT_8BPP_VERSION(void, vline, (BITMAP *bmp, int x, int y_1, int y2, int color), (bmp, x, y_1, y2, color)); CONSTRUCT_8BPP_VERSION(void, hline, (BITMAP *bmp, int x1, int y, int x2, int color), (bmp, x1, y, x2, color)); CONSTRUCT_8BPP_VERSION(void, hfill, (BITMAP *bmp, int x1, int y, int x2, int color), (bmp, x1, y, x2, color)); CONSTRUCT_8BPP_VERSION(void, line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), (bmp, x1, y_1, x2, y2, color)); CONSTRUCT_8BPP_VERSION(void, fastline, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), (bmp, x1, y_1, x2, y2, color)); CONSTRUCT_8BPP_VERSION(void, rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), (bmp, x1, y_1, x2, y2, color)); CONSTRUCT_8BPP_VERSION(void, triangle, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color), (bmp, x1, y_1, x2, y2, x3, y3, color)); CONSTRUCT_8BPP_VERSION(void, draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_256_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color), (bmp, sprite, x, y, color)); CONSTRUCT_8BPP_VERSION(void, draw_rle_sprite, (BITMAP *bmp, AL_CONST RLE_SPRITE *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_trans_rle_sprite, (BITMAP *bmp, AL_CONST RLE_SPRITE *sprite, int x, int y), (bmp, sprite, x, y)); CONSTRUCT_8BPP_VERSION(void, draw_lit_rle_sprite, (BITMAP *bmp, AL_CONST RLE_SPRITE *sprite, int x, int y, int color), (bmp, sprite, x, y, color)); CONSTRUCT_8BPP_VERSION(void, draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg), (bmp, sprite, x, y, color, bg)); CONSTRUCT_8BPP_VERSION(void, draw_glyph, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg), (bmp, glyph, x, y, color, bg)); CONSTRUCT_8BPP_VERSION(void, blit_from_memory, (BITMAP *source, BITMAP *bmp, int source_x, int source_y, int dest_x, int dest_y, int width, int height), (source, bmp, source_x, source_y, dest_x, dest_y, width, height)); CONSTRUCT_8BPP_VERSION(void, blit_from_system, (BITMAP *source, BITMAP *bmp, int source_x, int source_y, int dest_x, int dest_y, int width, int height), (source, bmp, source_x, source_y, dest_x, dest_y, width, height)); CONSTRUCT_8BPP_VERSION(void, blit_to_self, (BITMAP *source, BITMAP *bmp, int source_x, int source_y, int dest_x, int dest_y, int width, int height), (source, bmp, source_x, source_y, dest_x, dest_y, width, height)); CONSTRUCT_8BPP_VERSION(void, clear_to_color, (BITMAP *bmp, int color), (bmp, color)); CONSTRUCT_8BPP_VERSION(void, pivot_scaled_sprite_flip, (BITMAP *bmp, BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip), (bmp, sprite, x, y, cx, cy, angle, scale, v_flip)); CONSTRUCT_8BPP_VERSION(void, polygon, (BITMAP *bmp, int vertices, AL_CONST int *points, int color), (bmp, vertices, points, color)); CONSTRUCT_8BPP_VERSION(void, rect, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), (bmp, x1, y_1, x2, y2, color)); CONSTRUCT_8BPP_VERSION(void, circle, (BITMAP *bmp, int x, int y, int radius, int color), (bmp, x, y, radius, color)); CONSTRUCT_8BPP_VERSION(void, circlefill, (BITMAP *bmp, int x, int y, int radius, int color), (bmp, x, y, radius, color)); CONSTRUCT_8BPP_VERSION(void, ellipse, (BITMAP *bmp, int x, int y, int rx, int ry, int color), (bmp, x, y, rx, ry, color)); CONSTRUCT_8BPP_VERSION(void, ellipsefill, (BITMAP *bmp, int x, int y, int rx, int ry, int color), (bmp, x, y, rx, ry, color)); CONSTRUCT_8BPP_VERSION(void, arc, (BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color), (bmp, x, y, ang1, ang2, r, color)); CONSTRUCT_8BPP_VERSION(void, spline, (BITMAP *bmp, AL_CONST int points[8], int color), (bmp, points, color)); CONSTRUCT_8BPP_VERSION(void, floodfill, (BITMAP *bmp, int x, int y, int color), (bmp, x, y, color)); /* psp_do_stretch_blit8: * Hook to capture the call to stretch_blit(). */ void psp_do_stretch_blit8(BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked) { source->vtable->do_stretch_blit = NULL; stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height); if (is_same_bitmap(dest, displayed_video_bitmap)) psp_draw_to_screen(); source->vtable->do_stretch_blit = psp_do_stretch_blit8; } GFX_VTABLE psp_vtable8 = { 8, MASK_COLOR_8, _stub_unbank_switch, NULL, NULL, NULL, NULL, NULL, _linear_getpixel8, psp_putpixel8, psp_vline8, psp_hline8, psp_hfill8, psp_line8, psp_fastline8, psp_rectfill8, psp_triangle8, psp_draw_sprite8, psp_draw_256_sprite8, psp_draw_sprite_v_flip8, psp_draw_sprite_h_flip8, psp_draw_sprite_vh_flip8, psp_draw_trans_sprite8, NULL, psp_draw_lit_sprite8, psp_draw_rle_sprite8, psp_draw_trans_rle_sprite8, NULL, psp_draw_lit_rle_sprite8, psp_draw_character8, psp_draw_glyph8, psp_blit_from_memory8, _linear_blit8, psp_blit_from_system8, _linear_blit8, psp_blit_to_self8, NULL, //_blit_to_self_forward8, NULL, //_blit_to_self_backward8, NULL, //_blit_between_formats8, NULL, //_masked_blit8, psp_clear_to_color8, psp_pivot_scaled_sprite_flip8, NULL, NULL, //_draw_gouraud_sprite8, NULL, //_draw_sprite_end8, NULL, //_blit_end8, psp_polygon8, psp_rect8, psp_circle8, psp_circlefill8, psp_ellipse8, psp_ellipsefill8, psp_arc8, psp_spline8, psp_floodfill8, NULL, //_polygon3d8, NULL, //_polygon3d_f8, NULL, //_triangle3d8, NULL, //_triangle3d_f8, NULL, //_quad3d8, NULL, //_quad3d_f8, NULL //_draw_sprite_ex8 }; allegro-4.4.3.1/src/font.c0000664000175000017500000016467513437077643014224 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * The default 8x8 font, and mono and color font vtables. * * Contains characters: * * ASCII (0x0020 to 0x007F) * Latin-1 (0x00A1 to 0x00FF) * Extended-A (0x0100 to 0x017F) * Euro (0x20AC) * * Elias Pschernig added the Euro character. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "allegro/internal/aintern.h" /* standard ASCII characters (0x20 to 0x7F) */ static FONT_GLYPH f_0x20 = { 8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x21 = { 8, 8, { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00 } }; static FONT_GLYPH f_0x22 = { 8, 8, { 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x23 = { 8, 8, { 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00 } }; static FONT_GLYPH f_0x24 = { 8, 8, { 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00 } }; static FONT_GLYPH f_0x25 = { 8, 8, { 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00 } }; static FONT_GLYPH f_0x26 = { 8, 8, { 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00 } }; static FONT_GLYPH f_0x27 = { 8, 8, { 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x28 = { 8, 8, { 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00 } }; static FONT_GLYPH f_0x29 = { 8, 8, { 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00 } }; static FONT_GLYPH f_0x2A = { 8, 8, { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00 } }; static FONT_GLYPH f_0x2B = { 8, 8, { 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00 } }; static FONT_GLYPH f_0x2C = { 8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30 } }; static FONT_GLYPH f_0x2D = { 8, 8, { 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x2E = { 8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00 } }; static FONT_GLYPH f_0x2F = { 8, 8, { 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00 } }; static FONT_GLYPH f_0x30 = { 8, 8, { 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x31 = { 8, 8, { 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00 } }; static FONT_GLYPH f_0x32 = { 8, 8, { 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00 } }; static FONT_GLYPH f_0x33 = { 8, 8, { 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x34 = { 8, 8, { 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00 } }; static FONT_GLYPH f_0x35 = { 8, 8, { 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x36 = { 8, 8, { 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x37 = { 8, 8, { 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00 } }; static FONT_GLYPH f_0x38 = { 8, 8, { 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x39 = { 8, 8, { 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00 } }; static FONT_GLYPH f_0x3A = { 8, 8, { 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00 } }; static FONT_GLYPH f_0x3B = { 8, 8, { 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30 } }; static FONT_GLYPH f_0x3C = { 8, 8, { 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00 } }; static FONT_GLYPH f_0x3D = { 8, 8, { 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x3E = { 8, 8, { 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00 } }; static FONT_GLYPH f_0x3F = { 8, 8, { 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00 } }; static FONT_GLYPH f_0x40 = { 8, 8, { 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00 } }; static FONT_GLYPH f_0x41 = { 8, 8, { 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x42 = { 8, 8, { 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00 } }; static FONT_GLYPH f_0x43 = { 8, 8, { 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00 } }; static FONT_GLYPH f_0x44 = { 8, 8, { 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00 } }; static FONT_GLYPH f_0x45 = { 8, 8, { 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00 } }; static FONT_GLYPH f_0x46 = { 8, 8, { 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0x47 = { 8, 8, { 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00 } }; static FONT_GLYPH f_0x48 = { 8, 8, { 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x49 = { 8, 8, { 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x4A = { 8, 8, { 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x4B = { 8, 8, { 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00 } }; static FONT_GLYPH f_0x4C = { 8, 8, { 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00 } }; static FONT_GLYPH f_0x4D = { 8, 8, { 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00 } }; static FONT_GLYPH f_0x4E = { 8, 8, { 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00 } }; static FONT_GLYPH f_0x4F = { 8, 8, { 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00 } }; static FONT_GLYPH f_0x50 = { 8, 8, { 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0x51 = { 8, 8, { 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00 } }; static FONT_GLYPH f_0x52 = { 8, 8, { 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00 } }; static FONT_GLYPH f_0x53 = { 8, 8, { 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x54 = { 8, 8, { 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x55 = { 8, 8, { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00 } }; static FONT_GLYPH f_0x56 = { 8, 8, { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00 } }; static FONT_GLYPH f_0x57 = { 8, 8, { 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00 } }; static FONT_GLYPH f_0x58 = { 8, 8, { 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00 } }; static FONT_GLYPH f_0x59 = { 8, 8, { 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x5A = { 8, 8, { 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00 } }; static FONT_GLYPH f_0x5B = { 8, 8, { 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00 } }; static FONT_GLYPH f_0x5C = { 8, 8, { 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00 } }; static FONT_GLYPH f_0x5D = { 8, 8, { 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00 } }; static FONT_GLYPH f_0x5E = { 8, 8, { 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x5F = { 8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF } }; static FONT_GLYPH f_0x60 = { 8, 8, { 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x61 = { 8, 8, { 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00 } }; static FONT_GLYPH f_0x62 = { 8, 8, { 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00 } }; static FONT_GLYPH f_0x63 = { 8, 8, { 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x64 = { 8, 8, { 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00 } }; static FONT_GLYPH f_0x65 = { 8, 8, { 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0x66 = { 8, 8, { 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0x67 = { 8, 8, { 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0x68 = { 8, 8, { 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00 } }; static FONT_GLYPH f_0x69 = { 8, 8, { 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x6A = { 8, 8, { 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78 } }; static FONT_GLYPH f_0x6B = { 8, 8, { 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00 } }; static FONT_GLYPH f_0x6C = { 8, 8, { 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x6D = { 8, 8, { 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00 } }; static FONT_GLYPH f_0x6E = { 8, 8, { 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x6F = { 8, 8, { 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x70 = { 8, 8, { 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0 } }; static FONT_GLYPH f_0x71 = { 8, 8, { 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E } }; static FONT_GLYPH f_0x72 = { 8, 8, { 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0x73 = { 8, 8, { 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00 } }; static FONT_GLYPH f_0x74 = { 8, 8, { 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00 } }; static FONT_GLYPH f_0x75 = { 8, 8, { 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00 } }; static FONT_GLYPH f_0x76 = { 8, 8, { 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00 } }; static FONT_GLYPH f_0x77 = { 8, 8, { 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00 } }; static FONT_GLYPH f_0x78 = { 8, 8, { 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00 } }; static FONT_GLYPH f_0x79 = { 8, 8, { 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0x7A = { 8, 8, { 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00 } }; static FONT_GLYPH f_0x7B = { 8, 8, { 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00 } }; static FONT_GLYPH f_0x7C = { 8, 8, { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 } }; static FONT_GLYPH f_0x7D = { 8, 8, { 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00 } }; static FONT_GLYPH f_0x7E = { 8, 8, { 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0x7F = { 8, 8, { 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00 } }; /* list of ASCII characters */ static FONT_GLYPH* ascii_data[] = { &f_0x20, &f_0x21, &f_0x22, &f_0x23, &f_0x24, &f_0x25, &f_0x26, &f_0x27, &f_0x28, &f_0x29, &f_0x2A, &f_0x2B, &f_0x2C, &f_0x2D, &f_0x2E, &f_0x2F, &f_0x30, &f_0x31, &f_0x32, &f_0x33, &f_0x34, &f_0x35, &f_0x36, &f_0x37, &f_0x38, &f_0x39, &f_0x3A, &f_0x3B, &f_0x3C, &f_0x3D, &f_0x3E, &f_0x3F, &f_0x40, &f_0x41, &f_0x42, &f_0x43, &f_0x44, &f_0x45, &f_0x46, &f_0x47, &f_0x48, &f_0x49, &f_0x4A, &f_0x4B, &f_0x4C, &f_0x4D, &f_0x4E, &f_0x4F, &f_0x50, &f_0x51, &f_0x52, &f_0x53, &f_0x54, &f_0x55, &f_0x56, &f_0x57, &f_0x58, &f_0x59, &f_0x5A, &f_0x5B, &f_0x5C, &f_0x5D, &f_0x5E, &f_0x5F, &f_0x60, &f_0x61, &f_0x62, &f_0x63, &f_0x64, &f_0x65, &f_0x66, &f_0x67, &f_0x68, &f_0x69, &f_0x6A, &f_0x6B, &f_0x6C, &f_0x6D, &f_0x6E, &f_0x6F, &f_0x70, &f_0x71, &f_0x72, &f_0x73, &f_0x74, &f_0x75, &f_0x76, &f_0x77, &f_0x78, &f_0x79, &f_0x7A, &f_0x7B, &f_0x7C, &f_0x7D, &f_0x7E, &f_0x7F }; /* ANSI Latin-1 characters (0xA1 to 0xFF) */ static FONT_GLYPH f_0xA1 = { 8, 8, { 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00 } }; static FONT_GLYPH f_0xA2 = { 8, 8, { 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18 } }; static FONT_GLYPH f_0xA3 = { 8, 8, { 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00 } }; static FONT_GLYPH f_0xA4 = { 8, 8, { 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0x00 } }; static FONT_GLYPH f_0xA5 = { 8, 8, { 0xCC, 0xCC, 0x78, 0xFC, 0x30, 0xFC, 0x30, 0x30 } }; static FONT_GLYPH f_0xA6 = { 8, 8, { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 } }; static FONT_GLYPH f_0xA7 = { 8, 8, { 0x3E, 0x61, 0x3C, 0x66, 0x66, 0x3C, 0x86, 0x7C } }; static FONT_GLYPH f_0xA8 = { 8, 8, { 0x00, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xA9 = { 8, 8, { 0x7E, 0x81, 0x9D, 0xA1, 0xA1, 0x9D, 0x81, 0x7E } }; static FONT_GLYPH f_0xAA = { 8, 8, { 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00 } }; static FONT_GLYPH f_0xAB = { 8, 8, { 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00 } }; static FONT_GLYPH f_0xAC = { 8, 8, { 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00 } }; static FONT_GLYPH f_0xAD = { 8, 8, { 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xAE = { 8, 8, { 0x7E, 0x81, 0xB9, 0xA5, 0xB9, 0xA5, 0x81, 0x7E } }; static FONT_GLYPH f_0xAF = { 8, 8, { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xB0 = { 8, 8, { 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xB1 = { 8, 8, { 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0xFC, 0x00 } }; static FONT_GLYPH f_0xB2 = { 8, 8, { 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xB3 = { 8, 8, { 0x78, 0x0C, 0x38, 0x0C, 0x78, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xB4 = { 8, 8, { 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xB5 = { 8, 8, { 0x00, 0x00, 0x33, 0x33, 0x66, 0x7E, 0xC0, 0x80 } }; static FONT_GLYPH f_0xB6 = { 8, 8, { 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00 } }; static FONT_GLYPH f_0xB7 = { 8, 8, { 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xB8 = { 8, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x38 } }; static FONT_GLYPH f_0xB9 = { 8, 8, { 0x18, 0x38, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00 } }; static FONT_GLYPH f_0xBA = { 8, 8, { 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00 } }; static FONT_GLYPH f_0xBB = { 8, 8, { 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00 } }; static FONT_GLYPH f_0xBC = { 8, 8, { 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6F, 0xCF, 0x03 } }; static FONT_GLYPH f_0xBD = { 8, 8, { 0xC3, 0xC6, 0xCC, 0xDE, 0x33, 0x66, 0xCC, 0x0F } }; static FONT_GLYPH f_0xBE = { 8, 8, { 0xE1, 0x32, 0xE4, 0x3A, 0xF6, 0x2A, 0x5F, 0x86 } }; static FONT_GLYPH f_0xBF = { 8, 8, { 0x30, 0x00, 0x30, 0x60, 0xC0, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xC0 = { 8, 8, { 0x18, 0x0C, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0xC1 = { 8, 8, { 0x30, 0x60, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0xC2 = { 8, 8, { 0x7C, 0x82, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0xC3 = { 8, 8, { 0x76, 0xDC, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0xC4 = { 8, 8, { 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0xC5 = { 8, 8, { 0x10, 0x28, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0xC6 = { 8, 8, { 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00 } }; static FONT_GLYPH f_0xC7 = { 8, 8, { 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x18, 0x0C, 0x78 } }; static FONT_GLYPH f_0xC8 = { 8, 8, { 0x30, 0x18, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0xC9 = { 8, 8, { 0x0C, 0x18, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0xCA = { 8, 8, { 0x7C, 0x82, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0xCB = { 8, 8, { 0xC6, 0x00, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0xCC = { 8, 8, { 0x30, 0x18, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x00 } }; static FONT_GLYPH f_0xCD = { 8, 8, { 0x0C, 0x18, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x00 } }; static FONT_GLYPH f_0xCE = { 8, 8, { 0x3C, 0x42, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x00 } }; static FONT_GLYPH f_0xCF = { 8, 8, { 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x00 } }; static FONT_GLYPH f_0xD0 = { 8, 8, { 0xF8, 0x6C, 0x66, 0xF6, 0x66, 0x6C, 0xF8, 0x00 } }; static FONT_GLYPH f_0xD1 = { 8, 8, { 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00 } }; static FONT_GLYPH f_0xD2 = { 8, 8, { 0x30, 0x18, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xD3 = { 8, 8, { 0x18, 0x30, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xD4 = { 8, 8, { 0x7C, 0x82, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xD5 = { 8, 8, { 0x76, 0xDC, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xD6 = { 8, 8, { 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xD7 = { 8, 8, { 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, 0x00 } }; static FONT_GLYPH f_0xD8 = { 8, 8, { 0x3A, 0x6C, 0xCE, 0xD6, 0xE6, 0x6C, 0xB8, 0x00 } }; static FONT_GLYPH f_0xD9 = { 8, 8, { 0x60, 0x30, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xDA = { 8, 8, { 0x18, 0x30, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xDB = { 8, 8, { 0x7C, 0x82, 0x00, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xDC = { 8, 8, { 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0xDD = { 8, 8, { 0x0C, 0x18, 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x00 } }; static FONT_GLYPH f_0xDE = { 8, 8, { 0xE0, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0xF0 } }; static FONT_GLYPH f_0xDF = { 8, 8, { 0x78, 0xCC, 0xCC, 0xD8, 0xCC, 0xC6, 0xCC, 0x00 } }; static FONT_GLYPH f_0xE0 = { 8, 8, { 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xE1 = { 8, 8, { 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xE2 = { 8, 8, { 0x7E, 0xC3, 0x3C, 0x06, 0x3E, 0x66, 0x3F, 0x00 } }; static FONT_GLYPH f_0xE3 = { 8, 8, { 0x76, 0xDC, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xE4 = { 8, 8, { 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xE5 = { 8, 8, { 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xE6 = { 8, 8, { 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00 } }; static FONT_GLYPH f_0xE7 = { 8, 8, { 0x00, 0x00, 0x78, 0xC0, 0xC0, 0x78, 0x0C, 0x38 } }; static FONT_GLYPH f_0xE8 = { 8, 8, { 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0xE9 = { 8, 8, { 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0xEA = { 8, 8, { 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00 } }; static FONT_GLYPH f_0xEB = { 8, 8, { 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0xEC = { 8, 8, { 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0xED = { 8, 8, { 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0xEE = { 8, 8, { 0x7C, 0xC6, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00 } }; static FONT_GLYPH f_0xEF = { 8, 8, { 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0xF0 = { 8, 8, { 0x08, 0x3C, 0x08, 0x7C, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xF1 = { 8, 8, { 0x00, 0xF8, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0xF2 = { 8, 8, { 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xF3 = { 8, 8, { 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xF4 = { 8, 8, { 0x78, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xF5 = { 8, 8, { 0x76, 0xDC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xF6 = { 8, 8, { 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0xF7 = { 8, 8, { 0x30, 0x30, 0x00, 0xFC, 0x00, 0x30, 0x30, 0x00 } }; static FONT_GLYPH f_0xF8 = { 8, 8, { 0x00, 0x02, 0x7C, 0xCE, 0xD6, 0xE6, 0x7C, 0x80 } }; static FONT_GLYPH f_0xF9 = { 8, 8, { 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xFA = { 8, 8, { 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xFB = { 8, 8, { 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xFC = { 8, 8, { 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0xFD = { 8, 8, { 0x18, 0x30, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0xFE = { 8, 8, { 0xF0, 0x60, 0x7C, 0x66, 0x7C, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0xFF = { 8, 8, { 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; /* list of Latin-1 characters */ static FONT_GLYPH* latin1_data[] = { &f_0xA1, &f_0xA2, &f_0xA3, &f_0xA4, &f_0xA5, &f_0xA6, &f_0xA7, &f_0xA8, &f_0xA9, &f_0xAA, &f_0xAB, &f_0xAC, &f_0xAD, &f_0xAE, &f_0xAF, &f_0xB0, &f_0xB1, &f_0xB2, &f_0xB3, &f_0xB4, &f_0xB5, &f_0xB6, &f_0xB7, &f_0xB8, &f_0xB9, &f_0xBA, &f_0xBB, &f_0xBC, &f_0xBD, &f_0xBE, &f_0xBF, &f_0xC0, &f_0xC1, &f_0xC2, &f_0xC3, &f_0xC4, &f_0xC5, &f_0xC6, &f_0xC7, &f_0xC8, &f_0xC9, &f_0xCA, &f_0xCB, &f_0xCC, &f_0xCD, &f_0xCE, &f_0xCF, &f_0xD0, &f_0xD1, &f_0xD2, &f_0xD3, &f_0xD4, &f_0xD5, &f_0xD6, &f_0xD7, &f_0xD8, &f_0xD9, &f_0xDA, &f_0xDB, &f_0xDC, &f_0xDD, &f_0xDE, &f_0xDF, &f_0xE0, &f_0xE1, &f_0xE2, &f_0xE3, &f_0xE4, &f_0xE5, &f_0xE6, &f_0xE7, &f_0xE8, &f_0xE9, &f_0xEA, &f_0xEB, &f_0xEC, &f_0xED, &f_0xEE, &f_0xEF, &f_0xF0, &f_0xF1, &f_0xF2, &f_0xF3, &f_0xF4, &f_0xF5, &f_0xF6, &f_0xF7, &f_0xF8, &f_0xF9, &f_0xFA, &f_0xFB, &f_0xFC, &f_0xFD, &f_0xFE, &f_0xFF }; /* Extended-A characters (0x100 to 0x17F) */ static FONT_GLYPH f_0x100 = { 8, 8, { 0xFE, 0x00, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0x101 = { 8, 8, { 0xFC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x102 = { 8, 8, { 0x82, 0x7C, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x00 } }; static FONT_GLYPH f_0x103 = { 8, 8, { 0xC3, 0x7E, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x104 = { 8, 8, { 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x1C, 0x30, 0x1E } }; static FONT_GLYPH f_0x105 = { 8, 8, { 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x30, 0x1C } }; static FONT_GLYPH f_0x106 = { 8, 8, { 0x0C, 0x18, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x107 = { 8, 8, { 0x1C, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x108 = { 8, 8, { 0x7C, 0x82, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x109 = { 8, 8, { 0x7E, 0xC3, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x10A = { 8, 8, { 0x10, 0x00, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x10B = { 8, 8, { 0x10, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x10C = { 8, 8, { 0x6C, 0x38, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x10D = { 8, 8, { 0x6C, 0x38, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x10E = { 8, 8, { 0x6C, 0x38, 0xF8, 0x66, 0x66, 0x66, 0xF8, 0x00 } }; static FONT_GLYPH f_0x10F = { 8, 8, { 0xBC, 0x4C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00 } }; static FONT_GLYPH f_0x110 = { 8, 8, { 0xF8, 0x6C, 0x66, 0xF6, 0x66, 0x6C, 0xF8, 0x00 } }; static FONT_GLYPH f_0x111 = { 8, 8, { 0x08, 0x3C, 0x08, 0x7C, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x112 = { 8, 8, { 0xFE, 0x00, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0x113 = { 8, 8, { 0xFC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0x114 = { 8, 8, { 0x6C, 0x38, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0x115 = { 8, 8, { 0x6C, 0x38, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0x116 = { 8, 8, { 0x10, 0x00, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0x117 = { 8, 8, { 0x10, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0x118 = { 8, 8, { 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x18, 0x30, 0x1C } }; static FONT_GLYPH f_0x119 = { 8, 8, { 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x38, 0x0C } }; static FONT_GLYPH f_0x11A = { 8, 8, { 0x6C, 0x38, 0xFE, 0xC0, 0xFC, 0xC0, 0xFE, 0x00 } }; static FONT_GLYPH f_0x11B = { 8, 8, { 0x6C, 0x38, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00 } }; static FONT_GLYPH f_0x11C = { 8, 8, { 0x7C, 0x82, 0x7C, 0xC6, 0xC0, 0xCE, 0x7E, 0x00 } }; static FONT_GLYPH f_0x11D = { 8, 8, { 0x7E, 0xC3, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0x11E = { 8, 8, { 0x82, 0x7C, 0x7C, 0xC6, 0xC0, 0xCE, 0x7E, 0x00 } }; static FONT_GLYPH f_0x11F = { 8, 8, { 0xC3, 0x7E, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0x120 = { 8, 8, { 0x10, 0x00, 0x7C, 0xC6, 0xC0, 0xCE, 0x7E, 0x00 } }; static FONT_GLYPH f_0x121 = { 8, 8, { 0x10, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0x122 = { 8, 8, { 0x7C, 0xC6, 0xC0, 0xCE, 0x7E, 0x18, 0x0C, 0x78 } }; static FONT_GLYPH f_0x123 = { 8, 8, { 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, 0x0C, 0x38 } }; static FONT_GLYPH f_0x124 = { 8, 8, { 0x78, 0x84, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x125 = { 8, 8, { 0xEE, 0x7B, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00 } }; static FONT_GLYPH f_0x126 = { 8, 8, { 0xCC, 0xFE, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x127 = { 8, 8, { 0xE0, 0xFE, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00 } }; static FONT_GLYPH f_0x128 = { 8, 8, { 0x76, 0xDC, 0x78, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x129 = { 8, 8, { 0x76, 0xDC, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x12A = { 8, 8, { 0x78, 0x00, 0x78, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x12B = { 8, 8, { 0x78, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x12C = { 8, 8, { 0x84, 0x78, 0x78, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x12D = { 8, 8, { 0xC6, 0x7C, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x12E = { 8, 8, { 0x78, 0x30, 0x30, 0x30, 0x78, 0x18, 0x30, 0x1E } }; static FONT_GLYPH f_0x12F = { 8, 8, { 0x30, 0x00, 0x70, 0x30, 0x30, 0x78, 0x30, 0x1C } }; static FONT_GLYPH f_0x130 = { 8, 8, { 0x10, 0x00, 0x78, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x131 = { 8, 8, { 0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x132 = { 8, 8, { 0xEE, 0x42, 0x42, 0x42, 0x52, 0x52, 0xEC, 0x00 } }; static FONT_GLYPH f_0x133 = { 8, 8, { 0x42, 0x00, 0xC6, 0x42, 0x42, 0x42, 0xE2, 0x0C } }; static FONT_GLYPH f_0x134 = { 8, 8, { 0x7C, 0x82, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x135 = { 8, 8, { 0x7C, 0xC6, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78 } }; static FONT_GLYPH f_0x136 = { 8, 8, { 0xE6, 0x6C, 0x78, 0x6C, 0xE6, 0x30, 0x18, 0xF0 } }; static FONT_GLYPH f_0x137 = { 8, 8, { 0xE0, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x30, 0xE0 } }; static FONT_GLYPH f_0x138 = { 8, 8, { 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x6C, 0xE6, 0x00 } }; static FONT_GLYPH f_0x139 = { 8, 8, { 0xF3, 0x66, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00 } }; static FONT_GLYPH f_0x13A = { 8, 8, { 0x73, 0x36, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x13B = { 8, 8, { 0xF0, 0x60, 0x62, 0x66, 0xFE, 0x18, 0x0C, 0x78 } }; static FONT_GLYPH f_0x13C = { 8, 8, { 0x70, 0x30, 0x30, 0x30, 0x30, 0x78, 0x0C, 0x38 } }; static FONT_GLYPH f_0x13D = { 8, 8, { 0xF5, 0x66, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00 } }; static FONT_GLYPH f_0x13E = { 8, 8, { 0x75, 0x36, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x13F = { 8, 8, { 0xF0, 0x60, 0x64, 0x60, 0x62, 0x66, 0xFE, 0x00 } }; static FONT_GLYPH f_0x140 = { 8, 8, { 0x70, 0x30, 0x30, 0x32, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x141 = { 8, 8, { 0xF0, 0x60, 0x70, 0x60, 0xE2, 0x66, 0xFE, 0x00 } }; static FONT_GLYPH f_0x142 = { 8, 8, { 0x70, 0x30, 0x38, 0x30, 0x70, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x143 = { 8, 8, { 0x0C, 0x18, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x144 = { 8, 8, { 0x1C, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x145 = { 8, 8, { 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x30, 0x18, 0xF0 } }; static FONT_GLYPH f_0x146 = { 8, 8, { 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x30, 0xE0 } }; static FONT_GLYPH f_0x147 = { 8, 8, { 0x6C, 0x38, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x148 = { 8, 8, { 0x6C, 0x38, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00 } }; static FONT_GLYPH f_0x149 = { 8, 8, { 0xC0, 0x80, 0x5C, 0x66, 0x66, 0x66, 0x66, 0x00 } }; static FONT_GLYPH f_0x14A = { 8, 8, { 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x0C, 0x38 } }; static FONT_GLYPH f_0x14B = { 8, 8, { 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x0C, 0x38 } }; static FONT_GLYPH f_0x14C = { 8, 8, { 0xFE, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x14D = { 8, 8, { 0x00, 0xFC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x14E = { 8, 8, { 0x6C, 0x38, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x14F = { 8, 8, { 0x6C, 0x38, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x150 = { 8, 8, { 0x36, 0x6C, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x151 = { 8, 8, { 0x36, 0x6C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00 } }; static FONT_GLYPH f_0x152 = { 8, 8, { 0x7E, 0xDA, 0x88, 0x8C, 0x88, 0xDA, 0x7E, 0x00 } }; static FONT_GLYPH f_0x153 = { 8, 8, { 0x00, 0x00, 0x6C, 0x92, 0x9E, 0x90, 0x6C, 0x00 } }; static FONT_GLYPH f_0x154 = { 8, 8, { 0x0C, 0x18, 0xFC, 0x66, 0x7C, 0x6C, 0xE6, 0x00 } }; static FONT_GLYPH f_0x155 = { 8, 8, { 0x0C, 0x18, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0x156 = { 8, 8, { 0xFC, 0x66, 0x7C, 0x6C, 0xE6, 0x30, 0x18, 0xF0 } }; static FONT_GLYPH f_0x157 = { 8, 8, { 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x30, 0xE0 } }; static FONT_GLYPH f_0x158 = { 8, 8, { 0x6C, 0x38, 0xFC, 0x66, 0x7C, 0x6C, 0xE6, 0x00 } }; static FONT_GLYPH f_0x159 = { 8, 8, { 0x6C, 0x38, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00 } }; static FONT_GLYPH f_0x15A = { 8, 8, { 0x0C, 0x18, 0x7C, 0xE0, 0x78, 0x0E, 0x7C, 0x00 } }; static FONT_GLYPH f_0x15B = { 8, 8, { 0x0C, 0x18, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00 } }; static FONT_GLYPH f_0x15C = { 8, 8, { 0x7C, 0x82, 0x7C, 0xE0, 0x78, 0x0E, 0x7C, 0x00 } }; static FONT_GLYPH f_0x15D = { 8, 8, { 0x7C, 0xC6, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00 } }; static FONT_GLYPH f_0x15E = { 8, 8, { 0x7C, 0xE0, 0x78, 0x0E, 0x7C, 0x18, 0x0C, 0x78 } }; static FONT_GLYPH f_0x15F = { 8, 8, { 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x0C, 0x38 } }; static FONT_GLYPH f_0x160 = { 8, 8, { 0x6C, 0x38, 0x7C, 0xE0, 0x78, 0x0E, 0x7C, 0x00 } }; static FONT_GLYPH f_0x161 = { 8, 8, { 0x6C, 0x38, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00 } }; static FONT_GLYPH f_0x162 = { 8, 8, { 0xFC, 0x30, 0x30, 0x30, 0x78, 0x18, 0x0C, 0x38 } }; static FONT_GLYPH f_0x163 = { 8, 8, { 0x10, 0x30, 0xFC, 0x30, 0x34, 0x18, 0x0C, 0x38 } }; static FONT_GLYPH f_0x164 = { 8, 8, { 0x6C, 0x38, 0xFC, 0x30, 0x30, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x165 = { 8, 8, { 0x12, 0x3A, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00 } }; static FONT_GLYPH f_0x166 = { 8, 8, { 0xFC, 0xB4, 0x30, 0x30, 0xFC, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x167 = { 8, 8, { 0x10, 0x30, 0xFC, 0x30, 0xFC, 0x34, 0x18, 0x00 } }; static FONT_GLYPH f_0x168 = { 8, 8, { 0x76, 0xDC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x169 = { 8, 8, { 0x76, 0xDC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x16A = { 8, 8, { 0xFE, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x16B = { 8, 8, { 0x00, 0xFE, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x16C = { 8, 8, { 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x16D = { 8, 8, { 0x6C, 0x38, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x16E = { 8, 8, { 0x38, 0x6C, 0xFE, 0xD6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x16F = { 8, 8, { 0x38, 0x6C, 0x38, 0xDC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x170 = { 8, 8, { 0x36, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00 } }; static FONT_GLYPH f_0x171 = { 8, 8, { 0x36, 0x6C, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00 } }; static FONT_GLYPH f_0x172 = { 8, 8, { 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x30, 0x60, 0x3C } }; static FONT_GLYPH f_0x173 = { 8, 8, { 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x18, 0x0E } }; static FONT_GLYPH f_0x174 = { 8, 8, { 0x7C, 0x82, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00 } }; static FONT_GLYPH f_0x175 = { 8, 8, { 0x7C, 0xC6, 0x00, 0xC6, 0xD6, 0xFE, 0x6C, 0x00 } }; static FONT_GLYPH f_0x176 = { 8, 8, { 0x7C, 0x82, 0xCC, 0xCC, 0x78, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x177 = { 8, 8, { 0x7C, 0xC6, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8 } }; static FONT_GLYPH f_0x178 = { 8, 8, { 0xCC, 0x00, 0xCC, 0xCC, 0x78, 0x30, 0x78, 0x00 } }; static FONT_GLYPH f_0x179 = { 8, 8, { 0x0C, 0x18, 0xFE, 0x8C, 0x18, 0x32, 0xFE, 0x00 } }; static FONT_GLYPH f_0x17A = { 8, 8, { 0x0C, 0x18, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00 } }; static FONT_GLYPH f_0x17B = { 8, 8, { 0x10, 0x00, 0xFE, 0x8C, 0x18, 0x32, 0xFE, 0x00 } }; static FONT_GLYPH f_0x17C = { 8, 8, { 0x10, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00 } }; static FONT_GLYPH f_0x17D = { 8, 8, { 0x6C, 0x38, 0xFE, 0x8C, 0x18, 0x32, 0xFE, 0x00 } }; static FONT_GLYPH f_0x17E = { 8, 8, { 0x6C, 0x38, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00 } }; static FONT_GLYPH f_0x17F = { 8, 8, { 0x38, 0x6C, 0x64, 0xE0, 0x60, 0x60, 0xE0, 0x00 } }; /* list of Extended-A characters */ static FONT_GLYPH* extended_a_data[] = { &f_0x100, &f_0x101, &f_0x102, &f_0x103, &f_0x104, &f_0x105, &f_0x106, &f_0x107, &f_0x108, &f_0x109, &f_0x10A, &f_0x10B, &f_0x10C, &f_0x10D, &f_0x10E, &f_0x10F, &f_0x110, &f_0x111, &f_0x112, &f_0x113, &f_0x114, &f_0x115, &f_0x116, &f_0x117, &f_0x118, &f_0x119, &f_0x11A, &f_0x11B, &f_0x11C, &f_0x11D, &f_0x11E, &f_0x11F, &f_0x120, &f_0x121, &f_0x122, &f_0x123, &f_0x124, &f_0x125, &f_0x126, &f_0x127, &f_0x128, &f_0x129, &f_0x12A, &f_0x12B, &f_0x12C, &f_0x12D, &f_0x12E, &f_0x12F, &f_0x130, &f_0x131, &f_0x132, &f_0x133, &f_0x134, &f_0x135, &f_0x136, &f_0x137, &f_0x138, &f_0x139, &f_0x13A, &f_0x13B, &f_0x13C, &f_0x13D, &f_0x13E, &f_0x13F, &f_0x140, &f_0x141, &f_0x142, &f_0x143, &f_0x144, &f_0x145, &f_0x146, &f_0x147, &f_0x148, &f_0x149, &f_0x14A, &f_0x14B, &f_0x14C, &f_0x14D, &f_0x14E, &f_0x14F, &f_0x150, &f_0x151, &f_0x152, &f_0x153, &f_0x154, &f_0x155, &f_0x156, &f_0x157, &f_0x158, &f_0x159, &f_0x15A, &f_0x15B, &f_0x15C, &f_0x15D, &f_0x15E, &f_0x15F, &f_0x160, &f_0x161, &f_0x162, &f_0x163, &f_0x164, &f_0x165, &f_0x166, &f_0x167, &f_0x168, &f_0x169, &f_0x16A, &f_0x16B, &f_0x16C, &f_0x16D, &f_0x16E, &f_0x16F, &f_0x170, &f_0x171, &f_0x172, &f_0x173, &f_0x174, &f_0x175, &f_0x176, &f_0x177, &f_0x178, &f_0x179, &f_0x17A, &f_0x17B, &f_0x17C, &f_0x17D, &f_0x17E, &f_0x17F }; /* euro character (0x20AC) */ static FONT_GLYPH f_0x20AC = { 8, 8, { 0x3C, 0x62, 0xF8, 0x60, 0xF8, 0x62, 0x3C, 0x00 } }; /* euro character */ static FONT_GLYPH* euro_data[] = { &f_0x20AC }; /* allegro_404_char: * This is what we render missing glyphs as. */ int allegro_404_char = '^'; /* font_height: * (mono and color vtable entry) * Returns the height, in pixels of the font. */ static int font_height(AL_CONST FONT *f) { ASSERT(f); return f->height; } /* length: * (mono and color vtable entry) * Returns the length, in pixels, of a string as rendered in a font. */ static int length(AL_CONST FONT* f, AL_CONST char* text) { int ch = 0, w = 0; AL_CONST char* p = text; ASSERT(text); ASSERT(f); while( (ch = ugetxc(&p)) ) { w += f->vtable->char_length(f, ch); } return w; } /* _mono_find_glyph: * Helper for mono vtable, below. */ FONT_GLYPH* _mono_find_glyph(AL_CONST FONT* f, int ch) { FONT_MONO_DATA* mf = (FONT_MONO_DATA*)(f->data); while(mf) { if(ch >= mf->begin && ch < mf->end) return mf->glyphs[ch - mf->begin]; mf = mf->next; } /* if we don't find the character, then search for the missing glyph, but don't get stuck in a loop. */ if(ch != allegro_404_char) return _mono_find_glyph(f, allegro_404_char); return 0; } /* mono_char_length: * (mono vtable entry) * Returns the length, in pixels, of a character as rendered in a * monochrome font. */ static int mono_char_length(AL_CONST FONT* f, int ch) { FONT_GLYPH* g = _mono_find_glyph(f, ch); return g ? g->w : 0; } /* mono_render_char: * (mono vtable entry) * Renders a character, in a monochrome font, onto a bitmap at a given * location and in given colors. Returns the character width, in pixels. */ static int mono_render_char(AL_CONST FONT* f, int ch, int fg, int bg, BITMAP* bmp, int x, int y) { int w = 0; FONT_GLYPH* g = 0; acquire_bitmap(bmp); g = _mono_find_glyph(f, ch); if(g) { bmp->vtable->draw_glyph(bmp, g, x, y + (f->height-g->h)/2, fg, bg); w = g->w; } release_bitmap(bmp); return w; } /* mono_render: * (mono vtable entry) * Renders a string, in a monochrome font, onto a bitmap at a given * location and in given colors. */ static void mono_render(AL_CONST FONT* f, AL_CONST char* text, int fg, int bg, BITMAP* bmp, int x, int y) { int ch = 0; AL_CONST char* p = text; acquire_bitmap(bmp); while( (ch = ugetxc(&p)) ) { x += f->vtable->render_char(f, ch, fg, bg, bmp, x, y); } release_bitmap(bmp); } /* mono_destroy: * (mono vtable entry) * Destroys a monochrome font. */ static void mono_destroy(FONT* f) { FONT_MONO_DATA* mf = 0; if(!f) return; mf = (FONT_MONO_DATA*)(f->data); while(mf) { FONT_MONO_DATA* next = mf->next; int i = 0; for(i = mf->begin; i < mf->end; i++) _AL_FREE(mf->glyphs[i - mf->begin]); _AL_FREE(mf->glyphs); _AL_FREE(mf); mf = next; } _AL_FREE(f); } /* mono_get_font_ranges: * (mono vtable entry) * Returns the number of character ranges in a font, or -1 if that information * is not available. */ static int mono_get_font_ranges(FONT *f) { FONT_MONO_DATA* mf = 0; int ranges = 0; if (!f) return -1; mf = (FONT_MONO_DATA*)(f->data); while(mf) { FONT_MONO_DATA* next = mf->next; ranges++; if (!next) return ranges; mf = next; } return -1; } /* mono_get_font_range_begin: * (mono vtable entry) * Get first character for font range. Pass -1 to get the start of the font. */ static int mono_get_font_range_begin(FONT* f, int range) { FONT_MONO_DATA* mf = 0; int n; if (!f || !f->data) return -1; if (range < 0) range = 0; n = 0; mf = (FONT_MONO_DATA*)(f->data); while(mf && n<=range) { FONT_MONO_DATA* next = mf->next; if (!next || range == n) return mf->begin; mf = next; n++; } return -1; } /* mono_get_font_range_end: * (mono vtable entry) * Get last character for font range. Pass -1 to search the entire font. */ static int mono_get_font_range_end(FONT* f, int range) { FONT_MONO_DATA* mf = 0; int n; if (!f) return -1; n = 0; mf = (FONT_MONO_DATA*)(f->data); while(mf && (n<=range || range==-1)) { FONT_MONO_DATA* next = mf->next; if (!next || range == n) return mf->end - 1; mf = next; n++; } return -1; } /* mono_copy_glyph_range: * Monochrome font helper function. Copies (part of) a glyph range */ static FONT_MONO_DATA *mono_copy_glyph_range(FONT_MONO_DATA *mf, int begin, int end) { FONT_MONO_DATA * newmf; FONT_GLYPH **gl; FONT_GLYPH *g; int num, c; if (beginbegin || end>mf->end) return NULL; newmf = _AL_MALLOC(sizeof *newmf); if (!newmf) return NULL; newmf->begin = begin; newmf->end = end; newmf->next = NULL; num = end - begin; gl = newmf->glyphs = _AL_MALLOC(num * sizeof *gl); for (c=0; cglyphs[begin - mf->begin + c]; sz = ((g->w + 7) / 8) * g->h; gl[c] = _AL_MALLOC(sz + sizeof *(gl[c])); gl[c]->w = g->w; gl[c]->h = g->h; memcpy(gl[c]->dat, g->dat, sz * sizeof *(g->dat)); } return newmf; } /* mono_extract_font_range: * (mono vtable entry) * Extract a range of characters from a mono font */ static FONT *mono_extract_font_range(FONT *f, int begin, int end) { FONT *fontout = NULL; FONT_MONO_DATA *mf, *mfin; int first, last; if (!f) return NULL; /* Special case: copy entire font */ if (begin==-1 && end==-1) { } /* Copy from the beginning */ else if (begin == -1 && end > mono_get_font_range_begin(f, -1)) { } /* Copy to the end */ else if (end == -1 && begin <= mono_get_font_range_end(f, -1)) { } /* begin cannot be bigger than end */ else if (begin <= end && begin != -1 && end != -1) { } else { return NULL; } /* Get output font */ fontout = _AL_MALLOC(sizeof *fontout); fontout->height = f->height; fontout->vtable = f->vtable; fontout->data = NULL; /* Get real character ranges */ first = MAX(begin, mono_get_font_range_begin(f, -1)); last = (end>-1) ? MIN(end, mono_get_font_range_end(f, -1)) : mono_get_font_range_end(f, -1); last++; mf = NULL; mfin = f->data; while (mfin) { /* Find the range that is covered by the requested range. */ /* Check if the requested and processed ranges at least overlap */ if (((first >= mfin->begin && first < mfin->end) || (last <= mfin->end && last > mfin->begin)) /* Check if the requested range wraps processed ranges */ || (first < mfin->begin && last > mfin->end)) { int local_begin, local_end; local_begin = MAX(mfin->begin, first); local_end = MIN(mfin->end, last); if (mf) { mf->next = mono_copy_glyph_range(mfin, local_begin, local_end); mf = mf->next; } else { mf = mono_copy_glyph_range(mfin, local_begin, local_end); fontout->data = mf; } } mfin = mfin->next; } return fontout; } /* mono_merge_fonts: * (mono vtable entry) * Merges font2 with font1 and returns a new font */ static FONT *mono_merge_fonts(FONT *font1, FONT *font2) { FONT *fontout = NULL; FONT_MONO_DATA *mf, *mf1, *mf2; if (!font1 || !font2) return NULL; if (!is_mono_font(font1) || !is_mono_font(font2)) return NULL; /* Get output font */ fontout = _AL_MALLOC(sizeof *fontout); fontout->height = MAX(font1->height, font2->height); fontout->vtable = font1->vtable; mf = fontout->data = NULL; mf1 = font1->data; mf2 = font2->data; while (mf1 || mf2) { if (mf1 && (!mf2 || (mf1->begin < mf2->begin))) { if (mf) { mf->next = mono_copy_glyph_range(mf1, mf1->begin, mf1->end); mf = mf->next; } else { mf = mono_copy_glyph_range(mf1, mf1->begin, mf1->end); fontout->data = mf; } mf1 = mf1->next; } else { if (mf) { mf->next = mono_copy_glyph_range(mf2, mf2->begin, mf2->end); mf = mf->next; } else { mf = mono_copy_glyph_range(mf2, mf2->begin, mf2->end); fontout->data = mf; } mf2 = mf2->next; } } return fontout; } /* mono_transpose_font: * (mono vtable entry) * Transpose all glyphs in a font */ static int mono_transpose_font(FONT* f, int drange) { FONT_MONO_DATA* mf = 0; if (!f) return -1; mf = (FONT_MONO_DATA*)(f->data); while(mf) { FONT_MONO_DATA* next = mf->next; mf->begin += drange; mf->end += drange; mf = next; } return 0; } /* _color_find_glyph: * Helper for color vtable entries, below. */ BITMAP* _color_find_glyph(AL_CONST FONT* f, int ch) { FONT_COLOR_DATA* cf = (FONT_COLOR_DATA*)(f->data); while(cf) { if(ch >= cf->begin && ch < cf->end) return cf->bitmaps[ch - cf->begin]; cf = cf->next; } /* if we don't find the character, then search for the missing glyph, but don't get stuck in a loop. */ if(ch != allegro_404_char) return _color_find_glyph(f, allegro_404_char); return 0; } /* color_char_length: * (color vtable entry) * Returns the length of a character, in pixels, as it would be rendered * in this font. */ static int color_char_length(AL_CONST FONT* f, int ch) { BITMAP* g = _color_find_glyph(f, ch); return g ? g->w : 0; } /* color_render_char: * (color vtable entry) * Renders a color character onto a bitmap, at the specified location, using * the specified colors. If fg == -1, render as color, else render as * mono; if bg == -1, render as transparent, else render as opaque. * Returns the character width, in pixels. */ static int color_render_char(AL_CONST FONT* f, int ch, int fg, int bg, BITMAP* bmp, int x, int y) { int w = 0; int h = f->vtable->font_height(f); BITMAP *g = 0; acquire_bitmap(bmp); if(fg < 0 && bg >= 0) { rectfill(bmp, x, y, x + f->vtable->char_length(f, ch) - 1, y + h - 1, bg); } g = _color_find_glyph(f, ch); if(g) { if (bitmap_color_depth(g) == 8) { if(fg < 0) { bmp->vtable->draw_256_sprite(bmp, g, x, y + (h-g->h)/2); } else { bmp->vtable->draw_character(bmp, g, x, y + (h-g->h)/2, fg, bg); } } else { if (bitmap_color_depth(g) == bitmap_color_depth(bmp)) { masked_blit(g, bmp, 0, 0, x, y + (h-g->h)/2, g->w, g->h); } else { int color_conv_mode; BITMAP *tbmp; /* We need to do colour conversion - which is slow... */ color_conv_mode = get_color_conversion(); set_color_conversion(COLORCONV_MOST | COLORCONV_KEEP_TRANS); tbmp = create_bitmap_ex(bitmap_color_depth(bmp), g->w, g->h); blit(g, tbmp, 0, 0, 0, 0, g->w, g->h); set_color_conversion(color_conv_mode); masked_blit(tbmp, bmp, 0, 0, x, y + (h-g->h)/2, g->w, g->h); destroy_bitmap(tbmp); } } w = g->w; } release_bitmap(bmp); return w; } /* trans_render_char: * (trans vtable entry) * * Renders a transparent character onto a bitmap, at the specified location, * using the specified colors. fg is ignored. if bg == -1, render as * transparent, else render as opaque. Returns the character width, in pixels. */ static int trans_render_char(AL_CONST FONT* f, int ch, int fg, int bg, BITMAP* bmp, int x, int y) { int w = 0; int h = f->vtable->font_height(f); BITMAP *g = 0; acquire_bitmap(bmp); if(bg >= 0) { rectfill(bmp, x, y, x + f->vtable->char_length(f, ch) - 1, y + h - 1, bg); } g = _color_find_glyph(f, ch); if(g) { draw_trans_sprite(bmp, g, x, y + (h-g->h)/2); w = g->w; } release_bitmap(bmp); return w; } /* color_render: * (color vtable entry) * Renders a color font onto a bitmap, at the specified location, using * the specified colors. If fg == -1, render as color, else render as * mono; if bg == -1, render as transparent, else render as opaque. */ static void color_render(AL_CONST FONT* f, AL_CONST char* text, int fg, int bg, BITMAP* bmp, int x, int y) { AL_CONST char* p = text; int ch = 0; acquire_bitmap(bmp); if(fg < 0 && bg >= 0) { rectfill(bmp, x, y, x + text_length(f, text) - 1, y + text_height(f) - 1, bg); bg = -1; /* to avoid filling rectangles for each character */ } while( (ch = ugetxc(&p)) ) { x += f->vtable->render_char(f, ch, fg, bg, bmp, x, y); } release_bitmap(bmp); } /* color_destroy: * (color vtable entry) * Destroys a color font. */ static void color_destroy(FONT* f) { FONT_COLOR_DATA* cf; if(!f) return; cf = (FONT_COLOR_DATA*)(f->data); while(cf) { FONT_COLOR_DATA* next = cf->next; int i = 0; for(i = cf->begin; i < cf->end; i++) destroy_bitmap(cf->bitmaps[i - cf->begin]); _AL_FREE(cf->bitmaps); _AL_FREE(cf); cf = next; } _AL_FREE(f); } /* color_get_font_ranges: * (color vtable entry) * Returns the number of character ranges in a font, or -1 if that information * is not available. */ static int color_get_font_ranges(FONT *f) { FONT_COLOR_DATA* cf = 0; int ranges = 0; if (!f) return -1; cf = (FONT_COLOR_DATA*)(f->data); while(cf) { FONT_COLOR_DATA* next = cf->next; ranges++; if (!next) return ranges; cf = next; } return -1; } /* color_get_font_range_begin: * (color vtable entry) * Get first character for font. */ static int color_get_font_range_begin(FONT* f, int range) { FONT_COLOR_DATA* cf = 0; int n; if (!f || !f->data) return -1; if (range < 0) range = 0; n = 0; cf = (FONT_COLOR_DATA*)(f->data); while(cf && n<=range) { FONT_COLOR_DATA* next = cf->next; if (!next || range == n) return cf->begin; cf = next; n++; } return -1; } /* color_get_font_range_end: * (color vtable entry) * Get last character for font range. */ static int color_get_font_range_end(FONT* f, int range) { FONT_COLOR_DATA* cf = 0; int n; if (!f) return -1; n = 0; cf = (FONT_COLOR_DATA*)(f->data); while(cf && (n<=range || range==-1)) { FONT_COLOR_DATA* next = cf->next; if (!next || range == n) return cf->end - 1; cf = next; n++; } return -1; } /* upgrade_to_color, upgrade_to_color_data: * Helper functions. Upgrades a monochrome font to a color font. */ static FONT_COLOR_DATA* upgrade_to_color_data(FONT_MONO_DATA* mf) { FONT_COLOR_DATA* cf = _AL_MALLOC(sizeof *cf); BITMAP** bits = _AL_MALLOC((mf->end - mf->begin)*sizeof *bits); int i; cf->begin = mf->begin; cf->end = mf->end; cf->bitmaps = bits; cf->next = 0; for(i = mf->begin; i < mf->end; i++) { FONT_GLYPH* g = mf->glyphs[i - mf->begin]; BITMAP* b = create_bitmap_ex(8, g->w, g->h); clear_to_color(b, 0); b->vtable->draw_glyph(b, g, 0, 0, 1, 0); bits[i - mf->begin] = b; } return cf; } static FONT *upgrade_to_color(FONT* f) { FONT_MONO_DATA* mf = f->data; FONT_COLOR_DATA *cf, *cf_write = 0; FONT *outf; if (is_color_font(f)) return NULL; outf = _AL_MALLOC(sizeof *outf); outf->vtable = font_vtable_color; outf->height = f->height; while(mf) { FONT_MONO_DATA* mf_next = mf->next; cf = upgrade_to_color_data(mf); if(!cf_write) outf->data = cf; else cf_write->next = cf; cf_write = cf; mf = mf_next; } return outf; } /* color_copy_glyph_range: * Colour font helper function. Copies (part of) a glyph range */ static FONT_COLOR_DATA *color_copy_glyph_range(FONT_COLOR_DATA *cf, int begin, int end) { FONT_COLOR_DATA *newcf; BITMAP **gl; BITMAP *g; int num, c; if (beginbegin || end>cf->end) return NULL; newcf = _AL_MALLOC(sizeof *newcf); if (!newcf) return NULL; newcf->begin = begin; newcf->end = end; newcf->next = NULL; num = end - begin; gl = newcf->bitmaps = _AL_MALLOC(num * sizeof *gl); for (c=0; cbitmaps[begin - cf->begin + c]; gl[c] = create_bitmap_ex(bitmap_color_depth(g), g->w, g->h); blit(g, gl[c], 0, 0, 0, 0, g->w, g->h); } return newcf; } /* color_extract_font_range: * (color vtable entry) * Extract a range of characters from a color font */ static FONT *color_extract_font_range(FONT *f, int begin, int end) { FONT *fontout = NULL; FONT_COLOR_DATA *cf, *cfin; int first, last; if (!f) return NULL; /* Special case: copy entire font */ if (begin==-1 && end==-1) { } /* Copy from the beginning */ else if (begin == -1 && end > color_get_font_range_begin(f, -1)) { } /* Copy to the end */ else if (end == -1 && begin <= color_get_font_range_end(f, -1)) { } /* begin cannot be bigger than end */ else if (begin <= end && begin != -1 && end != -1) { } else { return NULL; } /* Get output font */ fontout = _AL_MALLOC(sizeof *fontout); fontout->height = f->height; fontout->vtable = f->vtable; fontout->data = NULL; /* Get real character ranges */ first = MAX(begin, color_get_font_range_begin(f, -1)); last = (end>-1) ? MIN(end, color_get_font_range_end(f, -1)) : color_get_font_range_end(f, -1); last++; cf = NULL; cfin = f->data; while (cfin) { /* Find the range that is covered by the requested range. */ /* Check if the requested and processed ranges at least overlap */ if (((first >= cfin->begin && first < cfin->end) || (last <= cfin->end && last > cfin->begin)) /* Check if the requested range wraps processed ranges */ || (first < cfin->begin && last > cfin->end)) { int local_begin, local_end; local_begin = MAX(cfin->begin, first); local_end = MIN(cfin->end, last); if (cf) { cf->next = color_copy_glyph_range(cfin, local_begin, local_end); cf = cf->next; } else { cf = color_copy_glyph_range(cfin, local_begin, local_end); fontout->data = cf; } } cfin = cfin->next; } return fontout; } /* color_merge_fonts: * (color vtable entry) * Merges font2 with font1 and returns a new font */ static FONT *color_merge_fonts(FONT *font1, FONT *font2) { FONT *fontout = NULL, *font2_upgr = NULL; FONT_COLOR_DATA *cf, *cf1, *cf2; if (!font1 || !font2) return NULL; /* Promote font 2 to colour if it is a monochrome font */ if (!is_color_font(font1)) return NULL; if (is_mono_font(font2)) { font2_upgr = upgrade_to_color(font2); /* Couldn't update font */ if (!font2_upgr) return NULL; } else font2_upgr = font2; if (!is_color_font(font2_upgr)) return NULL; /* Get output font */ fontout = _AL_MALLOC(sizeof *fontout); fontout->height = MAX(font1->height, font2->height); fontout->vtable = font1->vtable; cf = fontout->data = NULL; cf1 = font1->data; cf2 = font2_upgr->data; while (cf1 || cf2) { if (cf1 && (!cf2 || (cf1->begin < cf2->begin))) { if (cf) { cf->next = color_copy_glyph_range(cf1, cf1->begin, cf1->end); cf = cf->next; } else { cf = color_copy_glyph_range(cf1, cf1->begin, cf1->end); fontout->data = cf; } cf1 = cf1->next; } else { if (cf) { cf->next = color_copy_glyph_range(cf2, cf2->begin, cf2->end); cf = cf->next; } else { cf = color_copy_glyph_range(cf2, cf2->begin, cf2->end); fontout->data = cf; } cf2 = cf2->next; } } if (font2_upgr != font2) destroy_font(font2_upgr); return fontout; } /* color_transpose_font: * (color vtable entry) * Transpose all glyphs in a font */ static int color_transpose_font(FONT* f, int drange) { FONT_COLOR_DATA* cf = 0; if (!f) return -1; cf = (FONT_COLOR_DATA*)(f->data); while(cf) { FONT_COLOR_DATA* next = cf->next; cf->begin += drange; cf->end += drange; cf = next; } return 0; } /******** * vtable declarations ********/ FONT_VTABLE _font_vtable_mono = { font_height, mono_char_length, length, mono_render_char, mono_render, mono_destroy, mono_get_font_ranges, mono_get_font_range_begin, mono_get_font_range_end, mono_extract_font_range, mono_merge_fonts, mono_transpose_font }; FONT_VTABLE* font_vtable_mono = &_font_vtable_mono; FONT_VTABLE _font_vtable_color = { font_height, color_char_length, length, color_render_char, color_render, color_destroy, color_get_font_ranges, color_get_font_range_begin, color_get_font_range_end, color_extract_font_range, color_merge_fonts, color_transpose_font }; FONT_VTABLE* font_vtable_color = &_font_vtable_color; FONT_VTABLE _font_vtable_trans = { font_height, color_char_length, length, trans_render_char, color_render, color_destroy, color_get_font_ranges, color_get_font_range_begin, color_get_font_range_end, color_extract_font_range, color_merge_fonts, color_transpose_font }; FONT_VTABLE* font_vtable_trans = &_font_vtable_trans; /* font_has_alpha: * Returns TRUE if a color font has an alpha channel. */ int font_has_alpha(FONT *fnt) { FONT_COLOR_DATA *data; int ch; ASSERT(fnt); if (!is_color_font(fnt)) return FALSE; data = (FONT_COLOR_DATA *)(fnt->data); while (data) { for (ch = data->begin; ch != data->end; ++ch) if (_bitmap_has_alpha(data->bitmaps[ch - data->begin])) return TRUE; data = data->next; } return FALSE; } /* make_trans_font: * Modifes a font so glyphs are drawn with draw_trans_sprite. */ void make_trans_font(FONT *f) { ASSERT(f); ASSERT(f->vtable == font_vtable_color); f->vtable = font_vtable_trans; } /* is_trans_font: * Returns non-zero if the font passed is a bitmapped colour font using * draw_trans_sprite to render glyphs. */ int is_trans_font(FONT *f) { ASSERT(f); return (f->vtable == font_vtable_trans); } /* is_color_font: * returns non-zero if the font passed is a bitmapped colour font */ int is_color_font(FONT *f) { ASSERT(f); return (f->vtable == font_vtable_color || f->vtable == font_vtable_trans); } /* is_mono_font: * returns non-zero if the font passed is a monochrome font */ int is_mono_font(FONT *f) { ASSERT(f); return f->vtable == font_vtable_mono; } /* is_compatibe_font: * returns non-zero if the two fonts are of similar type */ int is_compatible_font(FONT *f1, FONT *f2) { ASSERT(f1); ASSERT(f2); return f1->vtable == f2->vtable; } /* extract_font_range: * Extracts a character range from a font f, and returns a new font containing * only the extracted characters. * Returns NULL if the character range could not be extracted. */ FONT *extract_font_range(FONT *f, int begin, int end) { if (f->vtable->extract_font_range) return f->vtable->extract_font_range(f, begin, end); return NULL; } /* merge_fonts: * Merges two fonts. May convert the two fonts to compatible types before * merging, in which case converting the type of f2 to f1 is tried first. */ FONT *merge_fonts(FONT *f1, FONT *f2) { FONT *f = NULL; if (f1->vtable->merge_fonts) f = f1->vtable->merge_fonts(f1, f2); if (!f && f2->vtable->merge_fonts) f = f2->vtable->merge_fonts(f2, f1); return f; } /* get_font_ranges: * Returns the number of character ranges in a font, or -1 if that information * is not available. */ int get_font_ranges(FONT *f) { if (f->vtable->get_font_ranges) return f->vtable->get_font_ranges(f); return -1; } /* get_font_range_begin: * Returns the starting character for the font in question, or -1 if that * information is not available. */ int get_font_range_begin(FONT *f, int range) { if (f->vtable->get_font_range_begin) return f->vtable->get_font_range_begin(f, range); return -1; } /* get_font_range_end: * Returns the last character for the font in question, or -1 if that * information is not available. */ int get_font_range_end(FONT *f, int range) { if (f->vtable->get_font_range_end) return f->vtable->get_font_range_end(f, range); return -1; } /* transpose_font: * Transposes all the glyphs in a font over a range drange. Returns 0 on * success, or -1 on failure. */ int transpose_font(FONT *f, int drange) { if (f->vtable->transpose_font) return f->vtable->transpose_font(f, drange); return -1; } /******** * Declaration of `_default_font' and `font' ********/ static FONT_MONO_DATA euro_monofont = { 0x20AC, 0x20AD, /* begin, end characters */ euro_data, /* the data set */ 0 /* next */ }; static FONT_MONO_DATA extended_a_monofont = { 0x100, 0x180, /* begin, end characters */ extended_a_data, /* the data set */ &euro_monofont /* next */ }; static FONT_MONO_DATA latin1_monofont = { 0x0A1, 0x100, /* begin, end characters */ latin1_data, /* the data set */ &extended_a_monofont /* next */ }; static FONT_MONO_DATA ascii_monofont = { 0x20, 0x80, /* begin, end characters */ ascii_data, /* the data set */ &latin1_monofont /* next */ }; static FONT default_font = { &ascii_monofont, /* first lot of data */ 8, /* height */ &_font_vtable_mono /* vtable */ }; FONT* font = &default_font; allegro-4.4.3.1/CMakeLists.txt0000664000175000017500000007372113437077643015052 0ustar siegesiege# XXX build chm files # XXX build devhelp files # XXX resources (keyboard/language) - pretty useless except on DOS # XXX install grabber.txt? # XXX png plugin for grabber # XXX what is fixbundle? # XXX applehelp bundle? # XXX projectbuilder application template? # XXX allegro.m4? # Ports that used to work which aren't supported yet: # Haiku/BeOS port # djgpp port # QNX port # BCC32 # Watcom # DMC # PSP port? #-----------------------------------------------------------------------------# # # CMake setup # cmake_minimum_required(VERSION 2.6 FATAL_ERROR) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Profile." FORCE) endif() # Restrict configuration types to the selected build type. # Note: This needs to be done before the project command set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE INTERNAL "internal") #-----------------------------------------------------------------------------# # # Build options # # Set the project name. project(ALLEGRO C CXX) if(WIN32) if(MINGW) # As of CMake 2.6.2, support for building .rc files with mingw seems to # be broken (uses wrong command line syntax) so we have to set this # variable manually. set(CMAKE_RC_COMPILE_OBJECT " -O coff -o -i ") if(NOT CMAKE_RC_COMPILER OR "${CMAKE_RC_COMPILER}" STREQUAL "") string(REGEX REPLACE "gcc(.exe)?$" "windres" GUESS_RC_COMPILER ${CMAKE_C_COMPILER}) find_program(CMAKE_RC_COMPILER ${GUESS_RC_COMPILER}) endif() endif(MINGW) enable_language(RC OPTIONAL) message(STATUS "CMAKE_RC_COMPILER: ${CMAKE_RC_COMPILER}") if(NOT CMAKE_RC_COMPILER) message(FATAL_ERROR "Please set CMAKE_RC_COMPILER manually, e.g. *-windres.") endif() endif(WIN32) set(ALLEGRO_VERSION 4.4.3) string(REGEX MATCH "^[0-9]+[.][0-9]+" ALLEGRO_SOVERSION ${ALLEGRO_VERSION}) # Mac OS X -compatibility_version. # XXX doesn't seem to work set(COMPAT_VERSION 4.4.0) set(ALLEGRO_DLL_SHORTVER 44) # Search in the `cmake' directory for additional CMake modules. list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) # Search for C header files in these directories. include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) # Put libraries into `lib'. set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) # Lists of all the source files. include(FileList) # Our own CMake macros and functions. include(Common) #-----------------------------------------------------------------------------# # # Build options # option(SHARED "Build shared library for main Allegro library and addons" on) set(BUILD_SHARED_LIBS ${SHARED}) # actual CMake variable # On some 64-bit platforms, libraries should be installed into `lib64' # instead of `lib'. Set this to 64 to do that. set(LIB_SUFFIX "" CACHE STRING "Suffix for 'lib' directories, e.g. '64'") option(MAGIC_MAIN "Enable magic main (Unix)" off) option(WANT_FRAMEWORKS "Want frameworks on Mac OS X" off) option(WANT_EMBED "Make frameworks embeddable in application bundles (Mac OS X)" on) set(FRAMEWORK_INSTALL_PREFIX "/Library/Frameworks" CACHE STRING "Directory in which to install Mac OS X frameworks") #-----------------------------------------------------------------------------# # # Unix platform checks # include(CheckIncludeFiles) include(CheckFunctionExists) include(CheckCSourceCompiles) include(CheckCSourceRuns) include(FindPkgConfig) include(TestBigEndian) if(UNIX) test_big_endian(ALLEGRO_BIG_ENDIAN) if(NOT ALLEGRO_BIG_ENDIAN) set(ALLEGRO_LITTLE_ENDIAN 1) endif(NOT ALLEGRO_BIG_ENDIAN) check_include_files(dirent.h ALLEGRO_HAVE_DIRENT_H) check_include_files(inttypes.h ALLEGRO_HAVE_INTTYPES_H) check_include_files(linux/awe_voice.h ALLEGRO_HAVE_LINUX_AWE_VOICE_H) check_include_files(linux/input.h ALLEGRO_HAVE_LINUX_INPUT_H) # On some systems including linux/joystick.h without sys/types.h results # in conflicting definitions of fd_set. check_include_files("sys/types.h;linux/joystick.h" ALLEGRO_HAVE_LINUX_JOYSTICK_H) check_include_files(linux/soundcard.h ALLEGRO_HAVE_LINUX_SOUNDCARD_H) check_include_files(machine/soundcard.h ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) check_include_files(soundcard.h ALLEGRO_HAVE_SOUNDCARD_H) check_include_files(stdint.h ALLEGRO_HAVE_STDINT_H) check_include_files(sys/io.h ALLEGRO_HAVE_SYS_IO_H) check_include_files(sys/stat.h ALLEGRO_HAVE_SYS_STAT_H) check_include_files(sys/time.h ALLEGRO_HAVE_SYS_TIME_H) check_include_files(sys/soundcard.h ALLEGRO_HAVE_SYS_SOUNDCARD_H) check_include_files(sys/utsname.h ALLEGRO_HAVE_SYS_UTSNAME_H) check_function_exists(getexecname ALLEGRO_HAVE_GETEXECNAME) check_function_exists(memcmp ALLEGRO_HAVE_MEMCMP) check_function_exists(mkstemp ALLEGRO_HAVE_MKSTEMP) check_function_exists(mmap ALLEGRO_HAVE_MMAP) check_function_exists(mprotect ALLEGRO_HAVE_MPROTECT) check_function_exists(sched_yield ALLEGRO_HAVE_SCHED_YIELD) check_function_exists(stricmp ALLEGRO_HAVE_STRICMP) check_function_exists(strlwr ALLEGRO_HAVE_STRLWR) check_function_exists(strupr ALLEGRO_HAVE_STRUPR) check_function_exists(sysconf ALLEGRO_HAVE_SYSCONF) check_c_source_compiles(" #include #include int main(void) { struct prpsinfo psinfo; ioctl(0, PIOCPSINFO, &psinfo); return 0; }" ALLEGRO_HAVE_SV_PROCFS_H ) check_c_source_compiles(" #include int main(void) { struct prpsinfo psinfo; psinfo.pr_argc = 0; return 0; }" ALLEGRO_HAVE_PROCFS_ARGCV ) check_c_source_compiles(" #include #include int main(void) { void *x = MAP_FAILED; }" MAP_FAILED_DEFINED) if(NOT MAP_FAILED_DEFINED) set(MAP_FAILED "((void *) -1)") endif() check_c_source_runs(" static int notsupported = 1; void test_ctor (void) __attribute__((constructor)); void test_ctor (void) { notsupported = 0; } int main(void) { return (notsupported); } " ALLEGRO_USE_CONSTRUCTOR) find_library(RT_LIBRARY rt) check_c_source_compiles(" #include int main(void) { struct timespec new_time_ns; clock_gettime(CLOCK_MONOTONIC, &new_time_ns); return 0; }" ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK ) if(MAGIC_MAIN) set(ALLEGRO_WITH_MAGIC_MAIN 1) endif(MAGIC_MAIN) # XXX const # XXX inline # XXX size_t endif(UNIX) #-----------------------------------------------------------------------------# # # Compiler and platform setup # option(STRICT_WARN "Halt at warnings" off) if(CMAKE_COMPILER_IS_GNUCC) set(COMPILER_GCC 1) set(ALLEGRO_GCC 1) set(WFLAGS "-W -Wall -Wno-unused-parameter") set(WFLAGS_C_ONLY "-Wdeclaration-after-statement") if(STRICT_WARN) set(WFLAGS "${WFLAGS} -Werror -Wpointer-arith") set(WFLAGS_C_ONLY "${WFLAGS_C_ONLY} -Wmissing-declarations") set(WFLAGS_C_ONLY "${WFLAGS_C_ONLY} -Wstrict-prototypes") endif(STRICT_WARN) endif(CMAKE_COMPILER_IS_GNUCC) if(MINGW) set(ALLEGRO_MINGW32 1) # Guess MINGDIR from the value of CMAKE_C_COMPILER if it's not set. if("$ENV{MINGDIR}" STREQUAL "") string(REGEX REPLACE "/bin/[^/]*$" "" MINGDIR "${CMAKE_C_COMPILER}") message(STATUS "Guessed MinGW directory: ${MINGDIR}") else("$ENV{MINGDIR}" STREQUAL "") file(TO_CMAKE_PATH "$ENV{MINGDIR}" MINGDIR) message(STATUS "Using MINGDIR: ${MINGDIR}") endif("$ENV{MINGDIR}" STREQUAL "") # Search in MINGDIR for headers and libraries. set(CMAKE_PREFIX_PATH "${MINGDIR}") # Install to MINGDIR if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX ${MINGDIR}) endif() message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") endif(MINGW) if(MSVC) set(COMPILER_MSVC 1) set(ALLEGRO_MSVC 1) set(WFLAGS "/W3 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE") endif(MSVC) if(WIN32) set(ALLEGRO_WINDOWS 1) endif() if(APPLE) set(ALLEGRO_MACOSX 1) set(ALLEGRO_DARWIN 1) # Hack to deal with Mac OS X 10.6. NSQuickDrawView is not defined by # NSQuickDrawView.h when compiling in 64-bit mode, and 64-bit mode is the # default when compiling on Snow Leopard. if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL i386) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386") endif() # The Mac port simply uses too many deprecated things. if(COMPILER_GCC) set(WFLAGS "${WFLAGS} -Wno-deprecated-declarations") endif(COMPILER_GCC) endif(APPLE) if(BEOS) if(CMAKE_SYSTEM_NAME STREQUAL Haiku) set(ALLEGRO_HAIKU 1) else(CMAKE_SYSTEM_NAME STREQUAL Haiku) set(ALLEGRO_BEOS 1) endif(CMAKE_SYSTEM_NAME STREQUAL Haiku) set(WFLAGS "-W -Wall -Wno-unused -Wno-multichar") set(WFLAGS_C_ONLY "") set(WFLAGS_CXX_ONLY "-Wno-ctor-dtor-privacy") endif(BEOS) if(UNIX AND NOT APPLE AND NOT BEOS) set(ALLEGRO_UNIX 1) endif() if(PSP) set(ALLEGRO_PSP 1) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -G0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -G0 -fno-exceptions -fno-rtti") endif(PSP) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WFLAGS} ${WFLAGS_C_ONLY}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WFLAGS} ${WFLAGS_CXX_ONLY}") if(NOT BUILD_SHARED_LIBS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DALLEGRO_STATICLINK") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DALLEGRO_STATICLINK") endif() set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUGMODE=1") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUGMODE=1") list(APPEND CMAKE_BUILD_TYPES Profile) mark_as_advanced( CMAKE_C_FLAGS_PROFILE CMAKE_CXX_FLAGS_PROFILE CMAKE_EXE_LINKER_FLAGS_PROFILE ) if(COMPILER_GCC) set(CMAKE_C_FLAGS_PROFILE "-pg" CACHE STRING "profiling flags") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE}" CACHE STRING "profiling flags") set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-pg" CACHE STRING "profiling flags") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "-pg" CACHE STRING "profiling flags") endif(COMPILER_GCC) if(COMPILER_MSVC) set(CMAKE_C_FLAGS_PROFILE "-Gd -Ox" CACHE STRING "profiling flags") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE}" CACHE STRING "profiling flags") set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-profile" CACHE STRING "profiling flags") endif(COMPILER_MSVC) #-----------------------------------------------------------------------------# # Not sure if we want to support disabling these any more. set(ALLEGRO_COLOR8 1) set(ALLEGRO_COLOR16 1) set(ALLEGRO_COLOR24 1) set(ALLEGRO_COLOR32 1) set(ALLEGRO_NO_ASM 1) # ALLEGRO_MMX left undefined # ALLEGRO_SSE left undefined #-----------------------------------------------------------------------------# # # Unix modules # option(WANT_MODULES "Use modules for drivers (Unix)" on) if(WANT_MODULES AND ALLEGRO_UNIX) set(ALLEGRO_WITH_MODULES 1) set(ALLEGRO_MODULES_PATH ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/allegro/${ALLEGRO_VERSION}) install(FILES ${CMAKE_SOURCE_DIR}/modules.lst DESTINATION "${ALLEGRO_MODULES_PATH}" ) endif(WANT_MODULES AND ALLEGRO_UNIX) function(add_our_module nm files) if(ALLEGRO_WITH_MODULES) add_library(${nm} MODULE ${files}) set_target_properties(${nm} PROPERTIES PREFIX "" COMPILE_FLAGS -DALLEGRO_MODULE ) target_link_libraries(${nm} ${ARGN}) install(TARGETS ${nm} DESTINATION "${ALLEGRO_MODULES_PATH}" ) endif(ALLEGRO_WITH_MODULES) endfunction(add_our_module) #-----------------------------------------------------------------------------# # # Platform drivers # set(PLATFORM_SOURCES) set(PLATFORM_LIBS) # always link with these libraries set(PLATFORM_LIBS_NON_MODULES) # only link with these if modules disabled set(PLATFORM_LIBS_MODULES) # only link with these if modules enabled # -- Unix -- option(WANT_OSS "Build OSS support" on) option(WANT_ALSA "Build ALSA support" on) option(WANT_JACK "Build JACK support" on) option(WANT_SGIAUDIO "Build SGI audio support" on) if(ALLEGRO_UNIX) # not MACOSX find_package(Threads) if(NOT CMAKE_USE_PTHREADS_INIT) message(FATAL_ERROR "Unix port requires pthreads support.") endif() set(ALLEGRO_HAVE_LIBPTHREAD 1) list(APPEND PLATFORM_LIBS m ${CMAKE_THREAD_LIBS_INIT}) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_UNIX_FILES}) find_library(DLOPEN_LIBRARY dl) mark_as_advanced(DLOPEN_LIBRARY) if(DLOPEN_LIBRARY) list(APPEND PLATFORM_LIBS_MODULES ${DLOPEN_LIBRARY}) endif() if(ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK) list(APPEND PLATFORM_LIBS ${RT_LIBRARY}) endif(ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK) if(WANT_OSS) include(AllegroFindOSS) if(OSS_FOUND) set(ALLEGRO_WITH_OSSDIGI 1) set(ALLEGRO_WITH_OSSMIDI 1) include_directories(SYSTEM ${OSS_INCLUDE_DIR}) endif(OSS_FOUND) endif(WANT_OSS) if(WANT_ALSA) pkg_check_modules(ALSA alsa) if(ALSA_FOUND) # ALSA 0.5 is beyond obsolete. set(ALLEGRO_ALSA_VERSION 9) set(ALLEGRO_WITH_ALSADIGI 1) set(ALLEGRO_WITH_ALSAMIDI 1) include_directories(SYSTEM ${ALSA_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBS_NON_MODULES ${ALSA_LIBRARIES}) add_our_module(alleg-alsadigi src/unix/alsa9.c ${ALSA_LIBRARIES}) add_our_module(alleg-alsamidi src/unix/alsamidi.c ${ALSA_LIBRARIES}) endif(ALSA_FOUND) endif(WANT_ALSA) if(WANT_JACK) pkg_check_modules(JACK jack) if(JACK_FOUND) set(ALLEGRO_WITH_JACKDIGI 1) include_directories(SYSTEM ${JACK_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBS_NON_MODULES ${JACK_LIBRARIES}) add_our_module(alleg-jack src/unix/jack.c ${JACK_LIBRARIES}) endif(JACK_FOUND) endif(WANT_JACK) # This is untested. if(WANT_SGIAUDIO) check_library_exists(audio alOpenPort "" SGIAUDIO_FOUND) if(SGIAUDIO_FOUND) set(ALLEGRO_WITH_SGIALDIGI 1) list(APPEND PLATFORM_LIBS_NON_MODULES audio) add_our_module(alleg-sgialdigi src/unix/sgial.c audio) endif(SGIAUDIO_FOUND) endif(WANT_SGIAUDIO) # aRts is obsolete # esd is obsolete endif(ALLEGRO_UNIX) # -- X11 -- option(WANT_X11 "Want X11 support (Unix)" on) if(ALLEGRO_UNIX AND WANT_X11) find_package(X11) if(X11_FOUND) set(ALLEGRO_WITH_XWINDOWS 1) endif() endif() if(ALLEGRO_WITH_XWINDOWS) include_directories(SYSTEM ${X11_INCLUDE_DIR}) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_X_FILES}) list(APPEND PLATFORM_LIBS ${X11_LIBRARIES}) if(X11_XShm_FOUND) set(ALLEGRO_XWINDOWS_WITH_SHM 1) list(APPEND PLATFORM_LIBS ${X11_Xext_LIB}) endif() if(X11_Xcursor_FOUND) set(ALLEGRO_XWINDOWS_WITH_XCURSOR 1) list(APPEND PLATFORM_LIBS ${X11_Xcursor_LIB}) endif() if(X11_Xcursor_FOUND) set(ALLEGRO_XWINDOWS_WITH_XCURSOR 1) list(APPEND PLATFORM_LIBS ${X11_Xcursor_LIB}) endif() if(X11_Xpm_FOUND) set(ALLEGRO_XWINDOWS_WITH_XPM 1) list(APPEND PLATFORM_LIBS ${X11_Xpm_LIB}) endif() find_library(X11_Xxf86vm_LIB Xxf86vm ${X11_LIB_SEARCH_PATH}) mark_as_advanced(X11_Xxf86vm_LIB) if(X11_xf86vmode_FOUND) set(ALLEGRO_XWINDOWS_WITH_XF86VIDMODE 1) list(APPEND PLATFORM_LIBS ${X11_Xxf86vm_LIB}) endif() check_library_exists(X11 XOpenIM "${X11_LIB_SEARCH_PATH}" XIM_FOUND) if(XIM_FOUND) set(ALLEGRO_XWINDOWS_WITH_XIM 1) endif(XIM_FOUND) check_library_exists(Xxf86dga XDGAQueryExtension "${X11_LIB_SEARCH_PATH}" XDGA_FOUND) if(XDGA_FOUND) set(ALLEGRO_XWINDOWS_WITH_XF86DGA2 1) list(APPEND PLATFORM_LIBS_NON_MODULES Xxf86dga ${X11_LIBRARIES}) add_our_module(alleg-dga2 src/x/xdga2.c Xxf86dga ${X11_LIBRARIES}) endif() endif(ALLEGRO_WITH_XWINDOWS) # -- Linux console -- option(WANT_LINUX_CONSOLE "Want Linux console support (Linux)" off) option(WANT_LINUX_VGA "Want Linux console VGA driver (Linux)" on) option(WANT_LINUX_FBCON "Want Linux console fbcon driver (Linux)" on) option(WANT_LINUX_SVGALIB "Want Linux console SVGAlib driver (Linux)" on) option(WANT_LINUX_TSLIB "Want Linux console tslib mouse driver (Linux)" on) if(WANT_LINUX_CONSOLE AND CMAKE_SYSTEM_NAME STREQUAL Linux) set(ALLEGRO_LINUX 1) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_LINUX_FILES}) if(WANT_LINUX_VGA) set(ALLEGRO_LINUX_VGA 1) add_our_module(alleg-vga src/misc/vga.c) endif() if(WANT_LINUX_FBCON) check_c_source_compiles(" #include int main(void) { int x = FB_SYNC_ON_GREEN; return 0; }" CAN_FBCON) if(CAN_FBCON) set(ALLEGRO_LINUX_FBCON 1) add_our_module(alleg-fbcon src/linux/fbcon.c) endif() endif() if(WANT_LINUX_SVGALIB) find_package(Svgalib) if(SVGALIB_FOUND) set(ALLEGRO_LINUX_SVGALIB 1) include_directories(SYSTEM ${SVGALIB_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${SVGALIB_LIBRARY}) check_c_source_compiles(" #include int main(void) { int x = vga_version; return 0; }" ALLEGRO_LINUX_SVGALIB_HAVE_VGA_VERSION) list(APPEND PLATFORM_LIBS_NON_MODULES ${SVGALIB_LIBRARY}) add_our_module(alleg-svgalib src/linux/svgalib.c ${SVGALIB_LIBRARY}) endif() endif() if(WANT_LINUX_TSLIB) find_package(Tslib) if(TSLIB_FOUND) set(ALLEGRO_LINUX_TSLIB 1) include_directories(SYSTEM ${TSLIB_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${TSLIB_LIBRARY}) list(APPEND PLATFORM_LIBS ${TSLIB_LIBRARY}) endif() endif() endif(WANT_LINUX_CONSOLE AND CMAKE_SYSTEM_NAME STREQUAL Linux) # -- Windows -- if(WIN32) find_package(DDraw) find_package(DInput) find_package(DSound) find_package(DXGuid) if(NOT DDRAW_FOUND OR NOT DINPUT_FOUND OR NOT DSOUND_FOUND OR NOT DXGUID_FOUND) if(MSVC) message(FATAL_ERROR "DirectX required for Windows port. You might need to add DirectX include and lib directories to your INCLUDE and LIB environment variables. ") elseif(MINGW) message(FATAL_ERROR "DirectX required for Windows port. Get it from the Allegro web site (dx80_mgw.zip).") else() message(FATAL_ERROR "DirectX required for Windows port.") endif() endif() include_directories(SYSTEM ${DDRAW_INCLUDE_DIR} ${DINPUT_INCLUDE_DIR} ${DSOUND_INCLUDE_DIR} ${DXGUID_INCLUDE_DIR} ) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_WIN_FILES}) list(APPEND PLATFORM_LIBS kernel32 user32 gdi32 comdlg32 ole32 ${DINPUT_LIBRARIES} ${DDRAW_LIBRARIES} ${DXGUID_LIBRARIES} winmm ${DSOUND_LIBRARIES} ) endif(WIN32) # -- Haiku/BeOS -- if(BEOS) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_BEOS_FILES}) list(APPEND PLATFORM_LIBS game midi device) endif(BEOS) # -- Mac OS X -- if(ALLEGRO_MACOSX) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_MACOSX_FILES}) if(NOT SHARED) list(APPEND PLATFORM_SOURCES src/macosx/main.m) endif(NOT SHARED) find_library(COCOA_LIBRARY Cocoa) find_library(CARBON_LIBRARY Carbon) find_library(IOKIT_LIBRARY IOKit) find_library(COREAUDIO_LIBRARY CoreAudio) find_library(AUDIOUNIT_LIBRARY AudioUnit) find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox) find_package(QuickTime) mark_as_advanced(COCOA_LIBRARY CARBON_LIBRARY IOKIT_LIBRARY) mark_as_advanced(COREAUDIO_LIBRARY AUDIOUNIT_LIBRARY AUDIOTOOLBOX_LIBRARY) mark_as_advanced(QUICKTIME_INCLUDE_DIR QUICKTIME_LIBRARY) list(APPEND PLATFORM_LIBS ${COCOA_LIBRARY} ${CARBON_LIBRARY} ${IOKIT_LIBRARY} ${COREAUDIO_LIBRARY} ${AUDIOUNIT_LIBRARY} ${AUDIOTOOLBOX_LIBRARY} ${QUICKTIME_LIBRARY} ) endif(ALLEGRO_MACOSX) # -- PSP -- if(PSP) include_directories(SYSTEM ${PSPSDK_PATH}/include) link_directories(${PSPSDK_PATH}/lib) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_PSP_FILES}) list(APPEND PLATFORM_LIBS m pspaudio pspgu psprtc pspdebug pspdisplay pspge pspctrl pspsdk c pspnet pspnet_inet pspnet_resolver psputility pspuser pspkernel) endif(PSP) #-----------------------------------------------------------------------------# # # Generate and install headers # set(ALLEGRO_PUBLIC_HEADERS) macro(add_headers location) list(APPEND ALLEGRO_PUBLIC_HEADERS ${ARGN}) # We reuse MACOSX_PACKAGE_LOCATION on non-Mac platforms as well. set_source_files_properties(${ARGN} PROPERTIES MACOSX_PACKAGE_LOCATION Headers/${location} ) endmacro(add_headers) configure_file( ${CMAKE_SOURCE_DIR}/include/allegro/platform/alplatf.h.cmake ${CMAKE_BINARY_DIR}/include/allegro/platform/alplatf.h @ONLY ) add_headers(allegro/platform ${CMAKE_BINARY_DIR}/include/allegro/platform/alplatf.h ) if(UNIX) configure_file( ${CMAKE_SOURCE_DIR}/include/allegro/platform/alunixac.h.cmake ${CMAKE_BINARY_DIR}/include/allegro/platform/alunixac.h ) add_headers(allegro/platform ${CMAKE_BINARY_DIR}/include/allegro/platform/alunixac.h ) endif(UNIX) add_headers("" include/allegro.h) add_headers(allegro ${ALLEGRO_INCLUDE_ALLEGRO_FILES}) add_headers(allegro/inline ${ALLEGRO_INCLUDE_ALLEGRO_INLINE_FILES}) add_headers(allegro/internal ${ALLEGRO_INCLUDE_ALLEGRO_INTERNAL_FILES}) add_headers(allegro/platform ${ALLEGRO_INCLUDE_ALLEGRO_PLATFORM_FILES}) # Platform-specific top-level headers. if(ALLEGRO_LINUX) add_headers("" include/linalleg.h) endif(ALLEGRO_LINUX) if(APPLE) add_headers("" include/osxalleg.h) endif(APPLE) if(WIN32) add_headers("" include/winalleg.h) endif(WIN32) if(ALLEGRO_WITH_XWINDOWS) add_headers("" include/xalleg.h) endif(ALLEGRO_WITH_XWINDOWS) if(BEOS) add_headers("" include/bealleg.h) endif(BEOS) #-----------------------------------------------------------------------------# # # Main library # # On Unix/Mac we don't ever use a -static postfix. if(CMAKE_BUILD_TYPE STREQUAL Debug) set(BUILD_TYPE_SUFFIX -debug) elseif(CMAKE_BUILD_TYPE STREQUAL Profile) set(BUILD_TYPE_SUFFIX -profile) else() set(BUILD_TYPE_SUFFIX "") endif() if(ALLEGRO_MODULES_PATH) set(ALLEGRO_MODULES_PATH_FLAG "-DALLEGRO_MODULES_PATH='\"${ALLEGRO_MODULES_PATH}\"'") endif(ALLEGRO_MODULES_PATH) if(APPLE) # CMake 2.6.2 onwards passes these flags automatically. if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} STREQUAL 2.6 AND ${CMAKE_PATCH_VERSION} LESS 2) set(ALLEGRO_LINK_FLAGS "-compatibility_version ${COMPAT_VERSION} -current_version ${ALLEGRO_VERSION}") endif() endif(APPLE) add_our_library(allegro ${ALLEGRO_SRC_FILES} ${ALLEGRO_SRC_C_FILES} ${PLATFORM_SOURCES} ${ALLEGRO_PUBLIC_HEADERS} ) if(WIN32 AND SHARED) set(allegro_OUTPUT_NAME alleg${ALLEGRO_DLL_SHORTVER}) else() set(allegro_OUTPUT_NAME alleg) endif() set_target_properties(allegro PROPERTIES COMPILE_FLAGS "-DALLEGRO_SRC ${ALLEGRO_MODULES_PATH_FLAG}" LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" OUTPUT_NAME ${allegro_OUTPUT_NAME} VERSION ${ALLEGRO_VERSION} SOVERSION ${ALLEGRO_SOVERSION} ) if(WIN32) if(SHARED) # Make mingw not add lib prefix to DLL, to match MSVC. set_target_properties(allegro PROPERTIES PREFIX "" ) else(SHARED) # Add a -static postfix on the main library for Windows. # In earlier versions of Allegro this was "_s". set_target_properties(allegro PROPERTIES POSTFIX "-static" DEBUG_POSTFIX "-debug-static" PROFILE_POSTFIX "-profile-static" ) endif(SHARED) endif(WIN32) set_our_framework_properties(allegro Allegro) set(link_with ${PLATFORM_LIBS}) if(ALLEGRO_WITH_MODULES) list(APPEND link_with ${PLATFORM_LIBS_MODULES}) else() list(APPEND link_with ${PLATFORM_LIBS_NON_MODULES}) endif() target_link_libraries(allegro ${link_with}) sanitize_cmake_link_flags(static_link_with ${link_with}) set_target_properties(allegro PROPERTIES static_link_with "${static_link_with}" ) install_our_library(allegro) if(NOT WANT_FRAMEWORKS) install_our_headers(${ALLEGRO_PUBLIC_HEADERS}) endif(NOT WANT_FRAMEWORKS) if(APPLE AND SHARED OR WANT_FRAMEWORKS) add_our_library(alleg-main STATIC src/macosx/main.m ) set_target_properties(alleg-main PROPERTIES OUTPUT_NAME alleg-main${BUILD_TYPE_SUFFIX} COMPILE_FLAGS -DALLEGRO_SRC ) target_link_libraries(allegro alleg-main) install_our_library(alleg-main) endif(APPLE AND SHARED OR WANT_FRAMEWORKS) if(PSP) add_our_library(alleg-main STATIC src/psp/pmain.c ) set_target_properties(alleg-main PROPERTIES OUTPUT_NAME alleg-main${BUILD_TYPE_SUFFIX} COMPILE_FLAGS -DALLEGRO_SRC ) target_link_libraries(alleg-main pspuser pspkernel) target_link_libraries(allegro alleg-main) install_our_library(alleg-main) endif(PSP) #-----------------------------------------------------------------------------# # # allegro-config script # if(UNIX) # including MACOSX set(prefix "${CMAKE_INSTALL_PREFIX}") set(INCLUDE_PREFIX "${CMAKE_INSTALL_PREFIX}") # not sure what this is if(BUILD_SHARED_LIBS) set(LINK_WITH_STATIC_LIBS no) else() set(LINK_WITH_STATIC_LIBS yes) endif() set(LIB_TO_LINK alleg${BUILD_TYPE_SUFFIX}) if(APPLE) set(LDFLAGS "-framework Cocoa -lalleg-main") else(APPLE) set(LDFLAGS "") endif(APPLE) sanitize_cmake_link_flags(LIBS ${PLATFORM_LIBS} ${PLATFORM_LIBS_NON_MODULES} ${PLATFORM_LIBS_MODULES} ) if(APPLE) # XXX untested set(ACCEPT_FRAMEWORKS yes) if(BUILD_SHARED_LIBS) set(FRAMEWORKS "-framework Cocoa -framework Allegro -lalleg-main${BUILD_TYPE_SUFFIX}") else(BUILD_SHARED_LIBS) set(FRAMEWORKS "-framework Cocoa -framework Allegro -lalleg-main${BUILD_TYPE_SUFFIX} -framework Carbon -framework IOKit -framework System -framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework QuickTime") endif(BUILD_SHARED_LIBS) else() set(ACCEPT_FRAMEWORKS no) set(FRAMEWORKS "") endif() configure_file( ${CMAKE_SOURCE_DIR}/misc/allegro-config.in ${CMAKE_BINARY_DIR}/allegro-config @ONLY ) install(PROGRAMS ${CMAKE_BINARY_DIR}/allegro-config DESTINATION bin ) endif(UNIX) #-----------------------------------------------------------------------------# # # Addons # option(WANT_ALLEGROGL "Enable AllegroGL" on) option(WANT_LOADPNG "Enable loadpng" on) option(WANT_LOGG "Enable logg" on) option(WANT_JPGALLEG "Enable JPGAlleg" on) if (BUILD_SHARED_LIBS) set(ADDON_LINKAGE SHARED) else() set(ADDON_LINKAGE STATIC) endif() if(WANT_FRAMEWORKS) set(ADDON_LINKAGE SHARED) endif() if(WANT_ALLEGROGL) add_subdirectory(addons/allegrogl) endif() if(WANT_LOADPNG) add_subdirectory(addons/loadpng) endif() if(WANT_LOGG) add_subdirectory(addons/logg) endif() if(WANT_JPGALLEG) add_subdirectory(addons/jpgalleg) endif() #-----------------------------------------------------------------------------# # # pkg-config files - after addons to get properties # set(PKG_CONFIG_FILES allegro allegrogl jpgalleg loadpng logg ) if(UNIX) set(prefix "${CMAKE_INSTALL_PREFIX}") set(INCLUDE_PREFIX "\${prefix}") set(bindir "\${exec_prefix}/bin") set(includedir "\${prefix}/include") set(libdir "\${exec_prefix}/lib${LIB_SUFFIX}") set(lib_type "${BUILD_TYPE_SUFFIX}") # We only use -static suffixes on Windows, for the main library. set(lib_linkage "") foreach(name ${PKG_CONFIG_FILES}) set(target ${name}) # For static linking: get extra libraries to link with. get_target_property(link_with ${target} static_link_with) configure_file( misc/${name}.pc.in ${LIBRARY_OUTPUT_PATH}/pkgconfig/${name}${lib_type}.pc @ONLY ) install(FILES ${LIBRARY_OUTPUT_PATH}/pkgconfig/${name}${lib_type}.pc DESTINATION "lib${LIB_SUFFIX}/pkgconfig" ) endforeach(name) endif(UNIX) #-----------------------------------------------------------------------------# # # Documentation # add_subdirectory(docs) #-----------------------------------------------------------------------------# # # Samples - after addons because skater can use AllegroGL # option(WANT_EXAMPLES "Build example programs" on) if(WANT_EXAMPLES) add_subdirectory(examples) add_subdirectory(demos/shooter) add_subdirectory(demos/skater) endif(WANT_EXAMPLES) #-----------------------------------------------------------------------------# # # Tools - after addons because of grabber plugins # option(WANT_TOOLS "Build tool programs" on) if(WANT_TOOLS) add_subdirectory(tools) # Note to packagers: setup is mostly a historical footnote on modern # operating systems. Do not feel the need to package it. add_subdirectory(setup) endif(WANT_TOOLS) #-----------------------------------------------------------------------------# # # Tests # option(WANT_TESTS "Build test programs" on) if(WANT_TESTS) add_subdirectory(tests) endif(WANT_TESTS) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro-4.4.3.1/resource/0000775000175000017500000000000013437077643014127 5ustar siegesiegeallegro-4.4.3.1/resource/language/0000775000175000017500000000000013437077643015712 5ustar siegesiegeallegro-4.4.3.1/resource/language/notext.cfg0000664000175000017500000001224713437077643017722 0ustar siegesiegelanguage_name = Norvegian [language] AWE32_detection_failed_on_port_0x%04x = Søk etter AWE32 feilet på port 0x%04x BLASTER_environment_variable_has_no_E_section = BLASTER miljøvariabelen har ingen E seksjon Error_setting_video_mode = Feil ved setting av grafikk modus Graphics_Mode = Grafikk Modus Insufficient_video_memory = Utilstrekkelig grafikkhukommelse Hardware_acceleration_not_available = Maskinvareaksellerasjon ikke tilgjengelig Mode-X_only_supports_8_bit_color = Mode-X støtter kun 8-bits fargeoppløsning Not_a_valid_VGA_resolution = Ugyldig VGA resolusjon Not_a_VGA_mode-X_resolution = Ugyldig Mode-X resolusjon Obsolete_VBE/AF_version_(need_2.0_or_greater) = Foreldet VBE/AF versjon (trenger 2.0 eller høyere) Older_SB_version_detected = Eldre SB versjon funnet Resolution_not_supported = Resolusjon støttes ikke Set_throttle_to_maximum = Set akselleratoren til full Set_throttle_to_minimum = Set akselleratoren til minimum Standard_joystick = Standardjoystick VBE/AF_Plug_and_Play_initialisation_failed = VBE/AF PnP initialisering feilet VESA_function_0x4F02_failed = VESA funksjon 0x4F02 feilet VESA_function_0x4F06_failed = VESA funksjon 0x4F06 feilet VGA_only_supports_8_bit_color = VGA støtter kun 8-bits fargeoppløsning Virtual_screen_size_too_large = Virtuel skjerm for stor Xtended_mode_only_supports_640x400 = Xtended modus støtter kun 640x400 resolusjon Xtended_mode_only_supports_8_bit_color = Xtended modus støtter kun 8-bits fargeoppløsning %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) på port %X, som bruker IRQ %d og DMA kanal %d %s_does_not_support_audio_input = %s støtter ikke lyd input %s_does_not_support_MIDI_input = %s støtter ikke MIDI input %s_not_found = %s ikke funnet %s_on_port_%X = %s på port %X 4-button_joystick = joystick med 4 knapper 6-button_joystick = joystick med 6 knapper 8-button_joystick = joystick med 8 knapper AWE32_driver:_had_trouble_with_the_embedded_data = AWE32 driver: hadde problemer med intern data AWE32_not_detected = AWE32 ikke funnet Bad_VBE/AF_driver_ID_string = Ugjyldig VBE/AF driver ID streng Banked_framebuffer_not_available = Banked framebuffer ikke tilgjengelig BLASTER_environment_variable_not_set = BLASTER miljøvariabel ikke satt Can't_find_VBEAF.DRV = Kan ikke finne VBEAF.DRV Can't_make_linear_screen_bitmap = Kan ikke oprette lineert skjermbitmap Can't_map_memory_for_VBE/AF = Kan ikke kartlegge hukommelse til VBE/AF Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Kan ikke bruke SB MIDI grensesnittet samtidig som DSP Cancel = Avbryt Centre_the_hat = Sentrer hatten DIGMID_patch_set_not_found = DIGMID-patchene ikke funnet Disk_Error = Diskfeil Dual_joysticks = Dual joysticker Dual_OPL2_synths = Dual OPL2 synther Error_reading_.IBK_file_'%s' = Feil under lesingen av .IBK fil '%s' ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) på port %X, som bruker IRQ %d og DMA kanal %d ESS_AudioDrive_not_found = ESS AudioDrive ikke funnet Failed_to_set_VBE/AF_mode = Feil ved setting av VBE/AF grafikk modus Hardware_scrolling_not_supported = Maskinvare skrolling ikke tilgjengelig Hat = Hatt Insufficient_%s_voices_available = Utilstrekkelig %s stemmer til rådighet Linear_framebuffer_not_available = Lineer framebuffer ikke tilgjengelig Move_stick_2_to_the_bottom_right = Flytt joystick 2 til nedre høyre hjørne Move_stick_2_to_the_top_left = Flytt joystick 2 til øvre venstre hjørne Move_stick_to_the_bottom_right = Flytt joysticken til nedre høyre hjørne Move_stick_to_the_top_left = Flytt joysticken til øvre venstre hjørne Move_the_hat_down = Flytt hatten ned Move_the_hat_left = Flytt hatten til venstre Move_the_hat_right = Flytt hatten til høyre Move_the_hat_up = Flytt hatten opp MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 og %s er i konflikt ved IRQ %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI grensesnitt på port %X, som bruker IRQ %d MPU-401_not_found = MPU-401 ikke funnet OPL_synth_not_found = OPL synth ikke funnet OPL2_synth = OPL2 synth OPL3_synth = OPL3 synth OPL3_synth_not_found = OPL3 synth ikke funnet SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibel på port 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = SB output-driver må installeres før input kan leses SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF-drivere støtter ikke vide virtuelle skjermer Second_OPL2_synth_not_found = Finner ikke OPL2 synth nummer 2 Software_wavetable_synth = Emulert wavetable synth Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI grensesnitt på port %X Sound_Blaster_not_found = Sound Blaster ikke funnet Sound_system_not_installed = Lydsystem ikke installert The_sound_of_silence = Lyden av stilhet Throttle = Aksellerator unused = ubrukt VBE_%d.0_not_available = VBE %d.0 ikke tilgjengelig VBE_mode_not_available = VBE-modus ikke tilgjengelig VBE/AF_device_not_present = VBE/AF-enhet ikke tilgjengelig VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF nær-pekere ikke støttet på denne platformen VESA_mode_0x100_not_available = VESA-modus 0x100 ikke tilgjengelig VESA_not_available = VESA ikke tilgjengelig VESA_protected_mode_interface_not_available = VESA beskyttet modus grensesnitt ikke tilgjengelig allegro-4.4.3.1/resource/language/nltext.cfg0000664000175000017500000001270613437077643017717 0ustar siegesiegelanguage_name = Dutch [language] %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) op poort %X, gebruikt IRQ %d en DMA-kanaal %d %s_does_not_support_audio_input = %s ondersteund geen audio invoer %s_does_not_support_MIDI_input = %s ondersteund geen MIDI invoer %s_not_found = %s niet gevonden %s_on_port_%X = %s op poort %X 4-button_joystick = joystick met 4 knoppen 6-button_joystick = joystick met 6 knoppen 8-button_joystick = joystick met 8 knoppen AWE32_detection_failed_on_port_0x%04x = Automatische herkenning van de AWE32 op poort 0x%04x niet gelukt AWE32_driver:_had_trouble_with_the_embedded_data = AWE32-stuurprogramma: probleem met ingebouwde gegevens AWE32_not_detected = AWE32 niet gevonden Bad_VBE/AF_driver_ID_string = Ongeldige VBE/AF-stuurprogramma ID-String Banked_framebuffer_not_available = Banked Framebuffer niet verkrijgbaar BLASTER_environment_variable_has_no_E_section = BLASTER-omgevingsvariabele bevat geen E-gedeelte BLASTER_environment_variable_not_set = BLASTER-omgevingsvariabele niet ingesteld Can't_find_VBEAF.DRV = VBEAF.DRV niet gevonden Can't_make_linear_screen_bitmap = Fout bij het creeren van de lineaire beeldschermbitmap Can't_map_memory_for_VBE/AF = Geheugen-map voor VBE/AF mislukt Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = de SB MIDI-interface en DSP kunnen niet tegelijk gebruikt worden Cancel = Annuleren Centre_the_hat = Centreer de kop digital = digitaal DIGMID_patch_set_not_found = DIGMID-Soundset niet gevonden Disk_Error = Schijffout Dual_joysticks = Dual Joysticks Dual_OPL2_synths = Dual OPL2 Synths Error_reading_.IBK_file_'%s' = Fout bij het lezen van .IBK-data '%s' Error_setting_video_mode = Fout bij het instellen van de grafische modus ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) op poort %X, gebruikt IRQ %d en DMA-kanaal %d ESS_AudioDrive_not_found = ESS AudioDrive niet gevonden Failed_to_set_VBE/AF_mode = Instellen VBE/AF modus mislukt Flightstick_Pro = Flightstick Pro Graphics_Mode = Grafische modus Hardware_acceleration_not_available = Hardwareversnelling niet toegankelijk Hardware_scrolling_not_supported = Hardwarescrolling niet ondersteund Hat = kop Insufficient_%s_voices_available = Onvoldoende %s stemmen verkrijgbaar Insufficient_video_memory = Ontoereikend videogeheugen Linear_framebuffer_not_available = lineaire framebuffer nicht verkrijgbaar MIDI = MIDI Mode-X_only_supports_8_bit_color = Mode-X ondersteund slechts 256 (8bits) kleuren Move_stick_2_to_the_bottom_right = beweeg Joystick 2 naar rechtsonder Move_stick_2_to_the_top_left = beweeg Joystick 2 naar linksboven Move_stick_to_the_bottom_right = beweeg de Joystick naar rechtsonder Move_stick_to_the_top_left = beweeg de Joystick naar linksboven Move_the_hat_down = beweeg de kop naar onder Move_the_hat_left = beweeg de kop naar links Move_the_hat_right = beweeg de kop naar rechts Move_the_hat_up = beweeg de kop naar boven MPU-401_and_%s_conflict_over_IRQ_%d = Conflict tussen MPU-401 en %s voor IRQ %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI-Interface op poort %X, gebruikt IRQ %d MPU-401_not_found = MPU-401 niet gevonden Not_a_valid_VGA_resolution = Geen geldige VGA resolutie Not_a_VGA_mode-X_resolution = Geen geldige VGA Mode-X resolutie Obsolete_VBE/AF_version_(need_2.0_or_greater) = Verouderde VBE/AF-versie (v2.0 of hoger nodig) OK = OK Older_SB_version_detected = Oudere SB-versie gevonden OPL_synth_not_found = OPL-synth niet gevonden OPL2_synth = OPL2 synth OPL3_synth = OPL3 synth OPL3_synth_not_found = OPL3-synth niet gevonden Resolution_not_supported = beeldschermresulutie niet ondersteund SB_AWE32/compatible_on_port_0x%04x = SB AWE32/compatibel op poort 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = SB uitvoer stuurprogramma moet geinstalleerd worden, alvorens SB-invoer plaats kan vinden SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF stuurprogramma ondersteund geen brede virtuele beeldschermen Second_OPL2_synth_not_found = tweede OPL2-synth niet gevonden Set_throttle_to_maximum = zet throttle op het maximum Set_throttle_to_minimum = zet throttle op het Minimum Software_wavetable_synth = Software-Wavetable synthese Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI-Interface op poort %X Sound_Blaster_not_found = Sound Blaster niet gevonden Sound_system_not_installed = Soundsystem niet geinstaleerd Standard_joystick = Standaard-Joystick Stick = Stuurknuppel The_sound_of_silence = volmaakte stilte Throttle = throttle unused = ongebruikt VBE_%d.0_not_available = VBE %d.0 niet verkrijgbaar VBE_mode_not_available = VBE-modus niet toegankelijk VBE/AF_device_not_present = VBE/AF-apparaat niet aanwezig VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF-nearptrs worden op dit platform niet ondersteund VBE/AF_Plug_and_Play_initialisation_failed = VBE/AF-Plug&Play-initialisering mislukt VESA_function_0x4F02_failed = VESA-functie 0x4F02 mislukt VESA_function_0x4F06_failed = VESA-functie 0x4F06 mislukt VESA_mode_0x100_not_available = VESA-Modus 0x100 niet verkrijgbaar VESA_not_available = VESA niet toegankelijk VESA_protected_mode_interface_not_available = VESA-Protected-Mode-Interface niet verkrijgbaar VGA_only_supports_8_bit_color = VGA ondersteund slechts 256 kleuren Virtual_screen_size_too_large = virtuele schermgrootte te groot Wingman_Extreme = Wingman Extreme Xtended_mode_only_supports_640x400 = Xtended-Mode ondersteund slects 640x400 beeldpunten Xtended_mode_only_supports_8_bit_color = Xtended-Modus ondersteund slechts 256 kleuren allegro-4.4.3.1/resource/language/fitext.cfg0000664000175000017500000001240113437077643017674 0ustar siegesiegelanguage_name = Suomi [language] AWE32_detection_failed_on_port_0x%04x = AWE 32:ta ei voitu tunnistaa porttiosoitteesta 0x%04x BLASTER_environment_variable_has_no_E_section = BLASTER-ympäristömuuttujassa ei ole E-kohtaa Error_setting_video_mode = Näyttötilan vaihto ei onnistunut Graphics_Mode = Näyttötila Insufficient_video_memory = Näyttömuisti ei riitä Hardware_acceleration_not_available = Laitteistokiihdytystä ei ole Mode-X_only_supports_8_bit_color = Mode-X tukee vain 8 bitin värejä Not_a_valid_VGA_resolution = Ei käypä VGA-resoluutio Not_a_VGA_mode-X_resolution =Ei käypä VGA mode-X -resoluutio Obsolete_VBE/AF_version_(need_2.0_or_greater) = Vanhentunut VBE/AF versio (pitäisi olla 2.0 tai suurempi) Older_SB_version_detected = Vanha SB-versio tunnistettu Resolution_not_supported = Resoluutiota ei ole tuettu Set_throttle_to_maximum = Käännä kaasu maksimiin Set_throttle_to_minimum = Käännä kaasu minimiin Standard_joystick = Normaali joystick VBE/AF_Plug_and_Play_initialisation_failed = VBE/AF Plug & Play alustus epäonnistui VESA_function_0x4F02_failed = VESA-funktio 0x4F02 epäonnistui VESA_function_0x4F06_failed = VESA-funktio 0x4F06 epäonnistui VGA_only_supports_8_bit_color = VGA tukee vain 8 bitin värejä Virtual_screen_size_too_large = Virtuaaliruudun koko on liian iso Xtended_mode_only_supports_640x400 = Xtended-tila tukee vain 640x400-resoluutiota Xtended_mode_only_supports_8_bit_color = Xtended-tila tukee vain 8 bitin värejä %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) portissa %X, käyttää IRQ:ta n:o %d ja DMA-kanavaa n:o %d %s_does_not_support_audio_input = %s ei tue audiosisääntuloa %s_does_not_support_MIDI_input = %s ei tue MIDI-sisääntuloa %s_not_found = %s ei löytynyt %s_on_port_%X = %s portissa %X 4-button_joystick = 4-nappinen joystick 6-button_joystick = 6-nappinen joystick 8-button_joystick = 8-nappinen joystick AWE32_driver:_had_trouble_with_the_embedded_data = AWE32-ajuri: ongelmia upotetun datan kanssa AWE32_not_detected = AWE32:a ei tunnistettu Bad_VBE/AF_driver_ID_string = Väärä VBE/AF-ajurin tunnistusmerkkijono Banked_framebuffer_not_available = Pankitettu ikkunapuskuri ei toimi BLASTER_environment_variable_not_set = BLASTER-ympäristömuuttujaa ei ole asetettu Can't_find_VBEAF.DRV = VBEAF.DRV-tiedostoa ei löytynyt Can't_make_linear_screen_bitmap = Ei voi tehdä lineaarista ruutubittikarttaa Can't_map_memory_for_VBE/AF = Ei voi kartoittaa muistia VBE/AF:lle Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = SB MIDI -liittymä ja DSP eivät toimi samanaikaisesti Cancel = Peruuta Centre_the_hat = Keskitä hattu DIGMID_patch_set_not_found = DIGMID-instrumentteja ei löytynyt Disk_Error = Levyvirhe Dual_joysticks = Kaksi joystickia Dual_OPL2_synths = Kaksi OPL2-piiriä Error_reading_.IBK_file_'%s' = Virhe luettaessa .IBK-tiedostoa '%s' ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) portissa %X, käyttää IRQ:ta n:o %d ja DMA-kanavaa n:o %d ESS_AudioDrive_not_found = ESS AudioDrivea ei löytynyt Failed_to_set_VBE/AF_mode = VBE/AF-tilan asetus epäonnistui Hardware_scrolling_not_supported = Laitteistovieritystä ei ole tuettu Hat = Hattu Insufficient_%s_voices_available = Liian vähän %s-ääniä saatavissa Linear_framebuffer_not_available = Lineaarinen ikkunapuskuri ei toimi Move_stick_2_to_the_bottom_right = Väännä tikku 2 alaoikeaan Move_stick_2_to_the_top_left = Väännä tikku 2 ylävasempaan Move_stick_to_the_bottom_right = Väännä tikku alavasempaan Move_stick_to_the_top_left = Väännä tikku yläoikeaan Move_the_hat_down = Käännä hattu alas Move_the_hat_left = Käännä hattu vasemmalle Move_the_hat_right = Käännä hattu oikealle Move_the_hat_up = Käännä hattu ylös MPU-401_and_%s_conflict_over_IRQ_%d = Ristiriita IRQ %d:n kanssa laitteiden MPU-401 ja %s välillä MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI -liitäntä portissa %X, käyttää IRQ:ta n:o %d MPU-401_not_found = MPU-401 ei löytynyt OPL_synth_not_found = OPL-piiriä ei löytynyt OPL2_synth = OPL2-piiri OPL3_synth = OPL3-piiri OPL3_synth_not_found = OPL3-piiriä ei löytynyt SB_AWE32/compatible_on_port_0x%04x = SB AWE32/yhteensopiva poritssa 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = SB-ulostulon ajuri täytyy alustaa ennenkuin sisääntuloa voidaan lukea SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTechin VBE/AF-ajurit eivät tue laajoja virtuaaliruutuja Second_OPL2_synth_not_found = Toista OPL2-piiriä ei löytynyt Software_wavetable_synth = Ohjelmallinen wavetablesynteesi Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI -liittymä portissa %X Sound_Blaster_not_found = Sound Blasteria ei löytynyt Sound_system_not_installed = Äänijärjestelmää ei ole asennettu The_sound_of_silence = Hiljaisuuden ääni Throttle = Kaasu unused = käyttämätön VBE_%d.0_not_available = VBE %d.0:a ei löydy VBE_mode_not_available = VBE-tila ei ole käytettävissä VBE/AF_device_not_present = VBE/AF-laitetta ei löydy VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF nearptrs ei ole tuettu tällä alustalla VESA_mode_0x100_not_available = VESA-tilaa 0x100 ei ole VESA_not_available = VESA ei ole käytettävissä VESA_protected_mode_interface_not_available = VESA:n suojatun tilan liittymä ei ole käytettävissä allegro-4.4.3.1/resource/language/ittext.cfg0000664000175000017500000003014113437077643017713 0ustar siegesiegelanguage_name = Italian [language] %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d Hz), porta %X, IRQ %d e DMA %d %s_does_not_support_audio_input = %s non supporta input audio %s_does_not_support_MIDI_input = %s non supporta input MIDI %s_not_found = %s non trovato %s_on_port_%X = %s sulla porta %X 4-button_joystick = Joystick con 4 bottoni 6-button_joystick = Joystick con 6 bottoni 8-button_joystick = Joystick con 8 bottoni Aim = Puntamento Aim_X = Puntamento asse X Aim_Y = Puntamento asse Y Analogue_Buttons = Bottoni approx. = ca AWE32_detection_failed_on_port_0x%04x = Ricerca AWE32 fallita sulla porta 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = driver AWE32: problemi coi dati incorporati AWE32_not_detected = AWE32 non rilevata Back = Indietro Bad_VBE/AF_driver_ID_string = Stringa ID per VBE/AF errata Banked_framebuffer_not_available = Banked framebuffer non disponibile BLASTER_environment_variable_has_no_E_section = Variabile di ambiente BLASTER non ha la sezione E BLASTER_environment_variable_not_set = Variabile di ambiente BLASTER non settata Blue = Blu Button_1 = Bottone 1 Button_2 = Bottone 2 Button_3 = Bottone 3 Button_4 = Bottone 4 Button_5 = Bottone 5 Can't_find_VBEAF.DRV = Non trovo VBEAF.DRV Can't_make_linear_screen_bitmap = Non posso creare una bitmap lineare sullo schermo Can't_map_memory_for_VBE/AF = Non posso mappare memoria per VBE/AF Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Non posso usare l'interfaccia SB_MIDI e il DSP contemporaneamente Cancel = Cancella Centre_the_hat = Centra il cappello Can_not_allocate_audio_buffer = Non posso allocare il buffer audio Can_not_create_XImage = Non posso creare una XImage Cannot_enable_linear_addressing = Non posso attivare l'indirizzamento lineare Can_not_get_channel_setup = Non posso ottenere la configurazione del canale Can_not_get_video_mode_settings = Non posso ottenere i settaggi del modo video Can_not_grab_keyboard = Non posso ottenere la tastiera Can_not_grab_mouse = Non posso ottenere il mouse Can_not_init_software_mixer = Non posso inizializzare il mixer software Can_not_install_colormap = Non posso installare la mappa dei colori Can_not_obtain_user_name = Non posso identificare il nome dell'utente Can_not_open_card/pcm_device = Non posso aprire il dispositivo della scheda sonora o pcm Cannot_open_default_visual! = Non posso aprire il visual di default! Can_not_open_framebuffer = Non posso aprire il framebuffer Cannot_open_palemu/trueemu_visual! = Non posso aprire il visual di emulazione pal/true Can_not_query_DirectVideo = Non posso richiedere il DirectVideo Can_not_set_channel_parameters = Non posso settare i parametri del canale Can_not_set_video_mode = Non posso settare il modo video Can_not_switch_to_DGA_mode = Non posso andare in modalita' DGA Can't_map_framebuffer_%s = Non posso mappare il framebuffer su %s Can't_open_framebuffer_%s = Non posso aprire il framebuffer su %s Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Scheda %d, dispositivo %d: %d bits, %s, %d bps, %s C_Down = C in basso Circle = Cerchio C_Left = C a sinistra Could_not_find_GRIP.GLL = GRIP.GLL non trovato Could_not_initialize_GrIP_system = Impossibile inizializzare il sistema GrIP Couldn't_allocate_screen_bitmap! = Non posso allocare il bitmap screen! C_Right = C a destra Cross = Croce C_Up = C in alto Device_connected_is_not_a_Wingman_Warrior = Il dispositivo connesso non e' un Wingman Warrior DGA_1.0_is_required = E' necessaria la DGA 1.0 DGA_2.0_or_newer_is_required = E' necessaria la DGA 2.0 o superiore DGA_extension_is_not_supported = Estensione DGA non supportata Dial = Componi digital = digitale Digital_input_driver_not_found = Dispositivo di input digitale non trovato Digital_sound_driver_not_found = Driver per il suono digitale non trovato DIGMID_patch_set_not_found = set di patch DIGMID non trovato Direction_Pad = Pad direzionale Direction_Pad_X = Asse X del pad direzionale Direction_Pad_Y = Asse Y del pad direzionale DirectVideo_is_not_supported = DirectVideo non supportato Disk_Error = Errore di disco Dual_joysticks = Doppio joystick Dual_OPL2_synths = Doppio sintetizzatore OPL2 Error_finding_our_VT:_%s = Errore cercando il VT: %s Error_setting_VGA_video_mode = Errore nel settaggio della modalita' video VGA Error_reading_.IBK_file_'%s' = Errore nel leggere il file .IBK '%s' Error_setting_video_mode = Errore nel settaggio della modalita' video ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz), porta %X, IRQ %d e DMA %d ESS_AudioDrive_not_found = ESS AudioDrive non trovato Failed_to_init_digital_input_driver = Inizializzazione del driver di input digitale fallita Failed_to_init_digital_sound_driver = Inizializzazione del driver sonoro digitale fallita Failed_to_init_MIDI_input_driver = Inizializzazione del driver di input MIDI fallita Failed_to_init_MIDI_music_driver = Inizializzazione del driver sonoro MIDI fallita Fatal_error:_unable_to_activate_the_Allegro_system = Errore fatale: impossibile attivare il sistema Allegro Fatal_error:_unable_to_set_GFX_SAFE = Errore fatale: impossibile settare il modo GFX_SAFE Failed_to_set_VBE/AF_mode = Ho fallito nel settare il modo VBE/AF Flightstick_Pro = Flightstick Pro Framebuffer_ioctl()_failed = ioctl() su framebuffer fallito Framebuffer_resolution_not_available = Risoluzione framebuffer non disponibile Getting_buffer_size:_%s = Ottenendo la dimensione del buffer: %s Green = Verde Graphics_Mode = Modo Grafico Hardware_acceleration_not_available = Accelerazione Hardware non disponibile Hardware_scrolling_not_supported = Scrolling Hardware non supportato Hat = Cappello I_Button = Bottone I IF-SEGA2/PCI:__create_linear_mapping_error = IF-SEGA2/PCI: errore di creazione mappatura lineare IF-SEGA2/PCI:__create_selector_error = IF-SEGA2/PCI: errore di creazione del selettore IF-SEGA2/PCI:_device_not_found = IF-SEGA2/PCI: dispositivo non trovato IF-SEGA2/PCI:_read_configuration_dword_error = IF-SEGA2/PCI: errore di lettura dword di configurazione II_Button = Bottone II Input_is_not_supported = Input non supportato Insufficient_%s_voices_available = Insufficienti voci disponibili con %s Insufficient_video_memory = Insufficiente memoria video Internal_error = Errore interno L1_Button = Bottone L1 Left = Sinistra Left_Stick = Manopola sinistra Left_Stick_X = Asse X della manopola sinistra Left_Stick_Y = Asse Y della manopola sinistra Linear_framebuffer_not_available = Linear framebuffer non disponibile MIDI_input_driver_not_found = Driver di input MIDI non trovato MIDI_music_driver_not_found = Driver sonoro MIDI non trovato Mode-X_only_supports_8_bit_color = Mode-X supporta solo 8 bit di colore Move_stick_2_to_the_bottom_right = Muovi il joystick 2 in basso a destra Move_stick_2_to_the_top_left = Muovi il joystick 2 in alto a sinistra Move_stick_to_the_bottom_right = Muovi il joystick in basso a destra Move_stick_to_the_top_left = Muovi il joystick in alto a sinistra Move_the_hat_down = Muovi il cappello giu Move_the_hat_left = Muovi il cappello a sinistra Move_the_hat_right = Muovi il cappello a destra Move_the_hat_up = Muovi il cappello su MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 e %s hanno un conflitto sul IRQ %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = Interfaccia MIDI MPU-401 , porta %X, IRQ %d MPU-401_not_found = MPU-401 non trovata No_GrIP_devices_available = Nessun dispositivo GrIP disponibile No_joysticks_found = Nessun joystick trovato No_server = Il server non e' presente No_support_synth_type_found = Supporto di sintesi musicale non trovato Not_enough_memory = Non c'e' abbastanza memoria Not_a_valid_VGA_resolution = Risoluzione VGA non valida Not_a_VGA_mode-X_resolution = Risoluzione VGA Mode-X non valida Not_in_stereo_or_mono_mode = Non in modalita' stereo o mono no_vsync = vsync non disponibile No_window = Finestra non disponibile Obsolete_VBE/AF_version_(need_2.0_or_greater) = Versione di VBE/AF obsoleta (hai bisogno della 2.0 o superiore) OK = OK Older_SB_version_detected = Trovata una versione della Sound Blaster piu vecchia OPL_synth_not_found = Sintetizzatore OPL non trovato OPL2_synth = Sintetizzatore OPL2 OPL3_synth = Sintetizzatore OPL3 OPL3_synth_not_found = Sintetizzatore OPL3 non trovato OSS_output_driver_must_be_installed_before_input_can_be_read = Il driver OSS di output deve essere installato prima di quello di input PCI_BIOS_not_installed = PCI BIOS non installato Position = Posizione Position_X = Posizione X Position_x = Posizione X Position_y = Posizione Y Red = Rosso Requested_mode_not_available! = Modo richiesto non disponibile! Required_VGA_mode_not_supported = Modo VGA richiesto non supportato Resolution_not_supported = Risoluzione non supportata Right = Destra Right_Stick = Manopola destra Right_Stick_X = Asse X della manopola destra Right_Stick_Y = Asse Y della manopola destra SB_AWE32/compatible_on_port_0x%04x = SB AWE32 compatibile sulla porta 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = Il driver di output della Sound Blaster va installato prima della lettura in input SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = I driver Scitech VBE/AF non supportano ampi schermi virtuali Second_OPL2_synth_not_found = Secondo sintetizzatore OPL2 non trovato Select = Seleziona Set_throttle_to_maximum = Poni la potenza al massimo Set_throttle_to_minimum = Poni la potenza al minimo Setting_DSP_parameters:_%s = Settaggio parametri DSP: %s Setting_fragment_size:_%s = Settaggio dimensione di frammento: %s %s_must_only_be_writeable_by_root = %s puo' essere scritto solo da root Software_wavetable_synth = Sintetizzatore da Wavetable software Sound_Blaster_MIDI_interface_on_port_%X = Interfaccia Sound Blaster MIDI sulla porta %X Sound_Blaster_not_found = Sound Blaster non trovata Sound_system_not_installed = Sistema Sonoro non installato Soundscape_not_found = Soundscape non trovata Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) sulla porta %X, IRQ %d, DMA %d e waveport %X Square = Quadrato Standard_joystick = Joystick standard Stick = Manopola Stick_%d = Manopola %d Stick_X = Asse X della manopola Stick_Y = Asse Y della manopola SWIFT_Device_not_detected = Dispositivo SWIFT non trovato This_driver_needs_local_display = Questo driver necessita display locale This_driver_needs_root_privileges = Questo driver necessita dei permessi di root The_sound_of_silence = Il suono del silenzio Throttle = Potenza Triangle = Triangolo Unable_to_control_VT_switching = Impossibile controllare il cambio VT Unable_to_find_a_suitable_graphics_driver = Impossibile trovare un driver grafico adeguato Unable_to_find_a_usable_VT = Impossibile trovare un VT utilizzabile Unable_to_map_video_memory = Impossibile mappare la memoria video Unable_to_open = Impossibile aprire Unable_to_open_%s:_%s = Impossibile aprire %s: %s Unable_to_reopen_new_console = Impossibile riaprire una nuova console Unsupported_color_depth = Profondita' di colore non supportata Unsupported_memory_layout = Layout di memoria non supportato Unsupported_sample_format = Formato del campione non supportato Unsupported_screen_size = Dimensione dello schermo non supportata unused = non utilizzato VBE_%d.0_not_available = VBE %d.0 non disponibile VBE_mode_not_available = Modo VBE non disponibile VBE/AF_device_not_present = Periferica VBE/AF non presente VBE/AF_nearptrs_not_supported_on_this_platform = Puntatori near di VBE/AF non supportati su questa piattaforma VBE/AF_Plug_and_Play_initialisation_failed = Inizializzazione Plug and Play di VBE/AF fallita VESA_function_0x4F02_failed = Funzione VESA 0x4F02 fallita VESA_function_0x4F06_failed = Funzione VESA 0x4F06 fallita VESA_mode_0x100_not_available = Modo 0x100 di VESA non disponibile VESA_not_available = VESA non disponibile VESA_protected_mode_interface_not_available = Interfaccia al modo protetto di VESA non disponibile VGA_only_supports_8_bit_color = VGA supporta solo modalita a 8 bit VidMode_extension_is_not_supported = L'estensione VidMode non e' supportata Virtual_screen_size_too_large = Dimesione dello schermo virtuale troppo grossa VT_WAITACTIVE_failure = VT WAITACTIVE fallito Wingman_Extreme = Wingman Extreme Xtended_mode_only_supports_640x400 = Xtended mode supporta solo il 640x400 Xtended_mode_only_supports_8_bit_color = Xtended mode supporta solo modi a 8 bit Yellow = Giallo allegro-4.4.3.1/resource/language/pttext.cfg0000664000175000017500000002556313437077643017736 0ustar siegesiegelanguage_name = Portugues [language] AAWE32_detection_failed_on_port_0x%04x = Falha na deteccao de AWE32 na porta 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = driver AWE32: problemas com os dados encravados AWE32_not_detected = AWE32 nao detectado Aim = Mira Aim_X = Mira X Aim_y = Mira y Analogue_Buttons = Botoes Analogicos Autodetect = Autodetectar BLASTER_environment_variable_has_no_E_section = a variavel ambiente BLASTER nao tem secao E! BLASTER_environment_variable_not_set = Nao existe a variavel de ambiente BLASTER Back = Voltar Bad_VBE/AF_driver_ID_string = String ID do driver VBE/AF nao reconhecida Banked_framebuffer_not_available = framebuffer margeavel nao disponivel C_Down = C Abaixo C_Left = C Esquerdo C_Right = C Direito C_Up = C Acima Cancel = Cancelar Can_not_allocate_audio_buffer = Impossivel alocar buffer de Audio Can_not_create_XImage = Impossivel criar imagem do modo X Cannot_enable_linear_adressing = Impossivel ativar adressamento de memoria linear Can_not_get_video_mode_settings = Nao foi possivel acessar as propriedades do modo de Video Can_not_grab_keyboard = Nao foi possivel acessar o teclado Can_not_grab_mouse = Nao foi possivel acessar o mouse Can_not_init_software_mixer = Impossivel inicializar o software mixer Can_not_install_colormap = Imposssivel instalar o mapa de cores Can_not_obtain_user_name = Impossivel obter o nome do usuario Cannot_open_card/pcm_device = Nao foi possivel abrir o dispositivo card/pcm Cannot_open_default_visual! = Nao foi possivel abrir o visual padrao! Cannot_open_palemu/trueemu_visual! = Nao foi possivel abrir o visual de emulacao de paleta ou de emulacao de cores! Can_not_query_DirectVideo = Impossivel comunicar com o DirectVideo Cannot_set_playback_format = Impossivel ajustar o formato de playback Can_not_switch_to_DGA_mode = Nao foi possivel mudar para modo DGA Can't_find_VBEAF.DRV = Arquivo VBEAF.DRV nao encontrado Can't_make_linear_screen_bitmap = Impossivel criar bitmap da tela linear Can't_map_framebuffer_%s = Impossivel mapear framebuffer %s Can't_map_memory_for_VBE/AF = Impossivel mapear memoria para VBE/AF Can't_open_framebuffer_%s = Impossivel abrir framebuffer %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Impossivel usar interface SB MIDI e a interface DSP ao mesmo tempo Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Card #%d, dispositivo #%d: %d bits, %s, %d bps, %s Centre_the_hat = Centralize o manche Circle = Circulo Could_not_find_GRIP.GLL = Nao foi possivel encontrar o arquivo GRIP.GLL Could_not_initialize_GrIP_system = Nao foi possivel inicializar o sistema GrIP Couldn't_allocate_screen_bitmap! = Falha na alocacao do bitmap da tela! Cross = Cruzamento DGA_extension_is_not_supported = Extensao DGA nao e suportada DIGMID_patch_set_not_found = DIGMID patch set nao encontrado Device_connected_is_not_a_Wingman_Warrior = Dispositivo conectado nao e um Wingman Warrior Dial = Discar Digital_input_driver_not_found = Driver digital de entrada nao encontrado Digital_sound_driver_not_found = Driver de som digital nao encontrado DirectVideo_is_not_supported = DirectVideo nao e suportado Direction_Pad = Botao direcional Direction_Pad_X = Direcional X Direction_Pad_Y = Direcional Y Dual_OPL2_synths = Duplo sintonizador OPL2 ESS_AudioDrive_not_found = Drive de Audio ESS nao foi encontrado ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) na porta %X, usando IRQ %d e canal DMA %d Error_finding_our_VT:_%s = Erro procurando o VT: %s Error_reading_.IBK_file_'%s' = Erro lendo o arquivo .IBK: '%s' Error_setting_VGA_video_mode = Erro inicializando o modo de video VGA Failed_to_init_MIDI_input_driver = Falha na inicializacao do driver de entrada MIDI Failed_to_init_MIDI_music_driver = Falha na inicializacao do driver de musica MIDI Failed_to_init_digital_input_driver = Falha na inicializacao do driver de entrada digital Failed_to_init_digital_sound_driver = Falha na inicializacao do driver de som digital Failed_to_set_VBE/AF_mode = Failha na inicializacao do modo VBE/AF Fatal_error:_unable_to_activate_the_Allegro_system = Erro Fatal: impossivel ativar o sistema Allegro Fatal_error:_unable_to_set_GFX_SAFE = Erro Fatal: Nao foi possivel inicializar com GFX_SAFE Framebuffer_ioctl()_failed = Framebuffer ioctl() falhou Framebuffer_resolution_not_available = Resolucao de framebuffer nao disponivel Getting_buffer_size:_%s = Descobrindo o tamanho do buffer: %s Graphics_Mode = Modo grafico Green = Verde Hardware_acceleration_not_available = Aceleracao de Hardware nao disponivel Hardware_scrolling_not_supported = Rollagem de Hardware nao suportada Hat = Manche I_Button = Botao I II_Button = Botao II Input_is_not_supported = Entrada nao suportada Insufficient_video_memory = Memoria de video insuficiente Internal_error = Falha Interna L1_Button = Botao L1 L2 = Botao L2 L3 = Botao L3 Left = Esquerda Left_Stick = Direcional da esquerda Left_Stick_X = Direcional da esquerda X Left_Stick_Y = Direcional da esquerda Y Linear_framebuffer_not_available = Framebuffer linear nao disponivel Linux_MS_Intellimouse = Linux MS Intellimouse Linux_PS/2_Intellimouse = Linux PS/2 Intellimouse MIDI_input_driver_not_found = O driver de entrada MIDI nao foi encontrado MIDI_music_driver_not_found = O driver de musica MIDI nao foi encontrado MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = interface MPU-401 MIDI na porta %X, usando IRQ %d MPU-401_and_%s_conflict_over_IRQ_%d = Conflito entre MPU-401 e %s sobre o IRQ %d MPU-401_not_found = MPU-401 nao encontrado Mode-X_only_supports_8_bit_color = Modo-X so suporta cores de 8 bits Move_stick_2_to_the_bottom_right = Mova o segundo direcional para baixo e para direita Move_stick_2_to_the_top_left = Mova o segundo direcional para cima e para esquerda Move_stick_to_the_bottom_right = Mova o direcional para baixo e para direita Move_stick_to_the_top_left = Mova o direcional para cima e para e esquerda Move_the_hat_down = Mova o manche para baixo Move_the_hat_left = Mova o manche para esquerda Move_the_hat_right = Mova o manche para direita Move_the_hat_up = Mova o manche para cima No_GrIP_devices_available = Nenhum dispositivo GrIP disponivel No_joysticks_found = Nenhum joystick foi encontrado No_server = Nenhum servidor Not_a_VGA_mode-X_resolution = Nao e uma resolucao VGA modo-X Not_a_valid_VGA_resolution = Resolucao VGA invalida Not_enough_memory = Falta de memoria Not_in_stereo_or_mono_mode = Nao e um modo estereo ou mono No_window = Sem window OK = OK OPL2_synth = sintetizador OPL2 OPL3_synth = sintetizador OPL3 OPL3_synth_not_found = sintetizador OPL3 nao encontrado OPL_synth_not_found = sintetizador OPL nao encontrado Obsolete_VBE/AF_version_(need_2.0_or_greater) = Versao VBE/AF obsoleta (precisa-se da versao 2.0 ou melhor) Older_SB_version_detected = Versao SB antiga detectada Pad = Controle Position = Posicao Position_X = Posicao X Position_y = Posicao y Red = Vermelho Requested_mode_not_available! = Modo requerido nao disponivel! Required_VGA_mode_not_supported = Modo VGA nao suportado Resolution_not_supported = Resolucao nao suportada Right = Direita Right_Stick = Direcional da direita Right_Stick_X = Direcional da direita X Right_Stick_Y = Direcional da direita Y SB_AWE32/compatible_on_port_0x%04x = SB AWE32/compativel na porta 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = Driver de saida SB precisa ser instalado antes que dados possam ser lidos dele SWIFT_Device_not_detected = Dispositivo SWIFT nao detectado SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = Drivers SciTech VBE/AF nao suportam telas virtuais amplas Second_OPL2_synth_not_found = Segundo sintetixador OPL2 nao encontrado Select = Selecionar Set_throttle_to_maximum = Ativar acelerador ao maximo Set_throttle_to_minimum = Ativar acelerador ao minimo Setting_DSP_parameters:_%s = Ativando os parametros DSP: %s Setting_fragment_size:_%s = Ativando o tamanho de fragmento: %s Software_wavetable_synth = Sintetizador de tabelas de ondas suportado por software Sound_Blaster_MIDI_interface_on_port_%X = Interface Sound Blaster MIDI na porta %X Sound_Blaster_not_found = Sound Blaster nao encontrado Soundscape_not_found = Soundscape nao encontrado Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) na porta %X, usando IRQ %d, canal DMA %d e waveport %X Sound_system_not_installed = Sistema de som nao instalado Spinner = Espinha Dorsal Square = Quadrado Start = Comecar Stick = Direcional Stick_X = Direcional X Stick_Y = Direcional Y Stick_%d = Direcional %d The_sound_of_silence = O som do silencio This_driver_needs_local_display = Esse driver precisa de um display local This_driver_needs_root_privileges = Esse driver precisa de privilegios de esqudrinhamento Throttle = Aceleracao Triangle = Triangulo Trigger = Gatilho Twist = Torcao Unable_to_control_VT_switching = Incapacidade de controlar a mudanca de VT Unable_to_find_a_suitable_graphics_driver = Imcapaz de achar um driver grafico apropriado Unable_to_find_a_usable_VT = Incapaz de achar um VT usavel Unable_to_map_video_memory = Impossivel mapear a memoria de video Unable_to_open = Impossivel abrir Unable_to_open_%s:_%s = Impossivel abrir %s: %s Unable_to_reopen_new_console = Impossivel reabrir um novo console Unsupported_color_depth = Profundidade de cor nao suportada Unsupported_memory_layout = Layout de memoria nao suportado Unsupported_sample_format = Formato sample nao suportado Unsupported_screen_size = Tamanho de tela nao suportado VBE/AF_Plug_and_Play_initialisation_failed = Inicializacao VBE/AF Plug and Play falhou VBE/AF_device_not_present = Dispositivo VBE/AF nao presente VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF nearptrs nao suportado nessa plataforma VBE_%d.0_not_available = VBE %d.0 nao disponivel VESA_function_0x4F02_failed = funcao VESA 0x4F02 falhou VESA_function_0x4F06_failed = funcao 0x4F06 falhou VESA_mode_0x100_not_available = modo VESA 0x100 nao disponivel VESA_not_available = VESA nao disponivel VESA_protected_mode_interface_not_available = interface de modo protegido VESA nao disponivel VGA_only_supports_8_bit_color = VGA do suporta cores de 8 bits VT_WAITACTIVE_failure = Falha VT_WAITACTIVE VidMode_extension_is_not_supported = Extensao VidMode nao suportada Virtual_screen_size_too_large = Tela virtual muito grande Wingman_Warrior_not_connected = Wingman Warrior nao conectado Xtended_mode_only_supports_640x400 = Modo Xtended so suporta 640x400 Xtended_mode_only_supports_8_bit_color = Modo Xtended so suporta cores de 8 bits Yellow = Amarelo approx. = aproximadamente fb_mode_%dx%d = modo_fb_%dx%d no_vsync = sem vsync %s:_%d_bits,_%s,_%d_bps,_%s = %s: %d bits, %s, %d bps, %s %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) na porta %X, usando IRQ %d e canal DMA %d %s_does_not_support_MIDI_input = %s nao suporta entrada de MIDI %s_does_not_support_audio_input = %s nao suporta entrada de audio %s_must_only_be_writeable_by_root = %s precisa ser somente sobrescrevivle pela raiz %s_not_found = %s nao encontrado %s_on_port_%X = %s na porta %X unused = nao usado allegro-4.4.3.1/resource/language/cztext.cfg0000664000175000017500000003763113437077643017726 0ustar siegesiegelanguage_name = Czech [language] A = A AWE32_detection_failed_on_port_0x%04x = Detekce AWE32 na portu 0x%04x selhala AWE32_driver:_had_trouble_with_the_embedded_data = Ovladač AWE32: problém s vloženými daty AWE32_not_detected = AWE32 nenalezen Aim = Aim Aim_X = Aim X Aim_y = Aim y Analogue_Buttons = Analogová tlačítka Autodetect = Autodetekce B = B B1 = B1 B2 = B2 B3 = B3 B4 = B4 B5 = B5 B6 = B6 B7 = B7 B8 = B8 BLASTER_environment_variable_has_no_E_section = Proměnná prostředí BLASTER nemá žádnou sekci E BLASTER_environment_variable_not_set = Proměnná prostředí BLASTER není nastavena Back = Back Bad_VBE/AF_driver_ID_string = Špatný identifikátor VBE/AF ovladače Banked_framebuffer_not_available = Banked framebuffer není dostupný Blue = Blue C = C C_Down = C Down C_Left = C Left C_Right = C Right C_Up = C Up Cancel = Zrušit Can_not_allocate_audio_buffer = Nelze alokovat audio buffer Can_not_create_XImage = Nelze vytvořit XImage Cannot_enable_linear_addressing = Nelze povolit lineární adresování Can_not_get_video_mode_settings = Nelze zjistit nastavení grafického módu Can_not_grab_keyboard = Nelze získat vládu nad klávesnicí Can_not_grab_mouse = Nelze získat vládu nad myší Can_not_init_software_mixer = Nelze inicializovat softwarový mixer Can_not_install_colormap = Nelze instalovat mapu barev Can_not_obtain_user_name = Nelze zjistit jméno uživatele Can_not_open_card/pcm_device = Nelze otevřít karetní/pcm zařízení Cannot_open_default_visual! = Nelze otevřít default visual! Cannot_open_palemu/trueemu_visual! = Nelze otevřít palemu/trueemu visual! Can_not_query_DirectVideo = Nelze se dotazovat DirectVidea Cannot_set_playback_format = Nelze nastavit formát playbacku Can_not_set_video_mode = Nelze nastavit grafický mód Can_not_switch_to_DGA_mode = Nelze se přepnout do DGA módu Can't_find_VBEAF.DRV = Nelze najít VBEAF.DRV Can't_make_linear_screen_bitmap = Nelze vytvořit lineární obrazovou bitmapu Can't_map_framebuffer_%s = Nelze namapovat framebuffer %s Can't_map_memory_for_VBE/AF = Nelze namapovat paměť pro VBE/AF Can't_open_framebuffer_%s = Nelze otevřít framebuffer %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Nelze použít SB MIDI a DSP najednou Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Karta #%d, zařízení #%d: %d bitů, %s, %d bps, %s Centre_the_hat = Vycentrujte klobouček Circle = Circle Could_not_find_GRIP.GLL = Nelze najít GRIP.GLL Could_not_initialize_GrIP_system = Nelze inicializovat GrIP systém Couldn't_allocate_screen_bitmap! = Nelze alokovat obrazovou bitmapu! Cross = Cross DGA_extension_is_not_supported = DGA rozšíření není podporováno DIGMID_patch_set_not_found = Datový soubor pro DIGMID nenalezen Device_connected_is_not_a_Wingman_Warrior = Připojené zařízení není Wingman Warrior Dial = Dial Digital_input_driver_not_found = Ovladač audio vstupu nebyl nalezen Digital_sound_driver_not_found = Ovladač audio výstupu nebyl nalezen DirectVideo_is_not_supported = DirectVideo není podporováno Direction_Pad = Direction Pad Direction_Pad_X = Direction Pad X Direction_Pad_Y = Direction Pad Y Dual_OPL2_synths = Duální OPL2 syntezátor ESS_AudioDrive_not_found = ESS AudioDrive nenalezen ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) na portu %X, s IRQ %d a DMA kanálem %d Error_finding_our_VT:_%s = Chyba při hledání našeho VT: %s Error_reading_.IBK_file_'%s' = Chyba při čtení .IBK souboru '%s' Error_setting_VGA_video_mode = Chyba při nastavování VGA módu Failed_to_init_MIDI_input_driver = Nelze inicializovat MIDI vstup Failed_to_init_MIDI_music_driver = Nelze inicializovat MIDI výstup Failed_to_init_digital_input_driver = Nelze inicializovat audio vstup Failed_to_init_digital_sound_driver = Nelze inicializovat audio výstup Failed_to_set_VBE/AF_mode = Nelze nastavit VBE/AF mód Fatal_error:_unable_to_activate_the_Allegro_system = Fatální chyba: nepodařilo se aktivovat Allegro Fatal_error:_unable_to_set_GFX_SAFE = Fatální chyba: nepodařilo se nastavit GFX_SAFE Framebuffer_ioctl()_failed = Framebuffer ioctl() selhal Framebuffer_resolution_not_available = Framebuffer rozlišení není dostupné Getting_buffer_size:_%s = Chyba při zjišťování velikosti bufferu: %s Graphics_Mode = Grafický mód Green = Green Hardware_acceleration_not_available = Hardwarová akcelerace není dostupná Hardware_scrolling_not_supported = Hardwarové skrolování není podporováno Hat = Hat I_Button = I Button II_Button = II Button Input_is_not_supported = Vstup není podporován Insufficient_video_memory = Nedostatečná video paměť Internal_error = Interní chyba L = L L1 = L1 L1_Button = L1 Button L2 = L2 L3 = L3 Left = Left Left_Stick = Left Stick Left_Stick_X = Left Stick X Left_Stick_Y = Left Stick Y Linear_framebuffer_not_available = Linear framebuffer není dostupný Linux_MS_Intellimouse = Linux MS Intellimouse Linux_PS/2_Intellimouse = Linux PS/2 Intellimouse M = M MIDI = MIDI MIDI_input_driver_not_found = Ovladač MIDI vstupu nebyl nalezen MIDI_music_driver_not_found = Ovladač MIDI výstupu nebyl nalezen MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI rozhraní na portu %X, s IRQ %d MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 a %s mají konflikt o IRQ %d MPU-401_not_found = MPU-401 nenalezen Mode-X_only_supports_8_bit_color = Mode-X podporuje pouze 8-bitové barvy Move_stick_2_to_the_bottom_right = Pohněte druhou pákou vpravo dolů Move_stick_2_to_the_top_left = Pohněte druhou pákou vlevo nahoru Move_stick_to_the_bottom_right = Pohněte pákou vpravo dolů Move_stick_to_the_top_left = Pohněte pákou vlevo nahoru Move_the_hat_down = Pohněte kloboučkem dolů Move_the_hat_left = Pohněte kloboučkem vlevo Move_the_hat_right = Pohněte kloboučkem vpravo Move_the_hat_up = Pohněte kloboučkem nahoru No_GrIP_devices_available = Žádná dostupná GrIP zařízení No_joysticks_found = Žádné joysticky nenalezeny No_server = Žádný server No_support_synth_type_found = Nenalezen žádný podporovaný typ syntezátoru Not_a_VGA_mode-X_resolution = Toto není VGA mode-X rozlišení Not_a_valid_VGA_resolution = Toto není VGA rozlišení Not_enough_memory = Nedostatek paměti Not_in_stereo_or_mono_mode = Není ve stereo nebo mono módu No_window = žádné okno OK = OK OPL2_synth = OPL2 syntezátor OPL3_synth = OPL3 syntezátor OPL3_synth_not_found = OPL3 syntezátor nenalezen OPL_synth_not_found = OPL syntezátor nenalezen OSS_output_driver_must_be_installed_before_input_can_be_read = OSS výstup musí být nainstalován předtím než lze číst ze vstupu Obsolete_VBE/AF_version_(need_2.0_or_greater) = Zastaralá verze VBE/AF (nutná je verze 2.0 nebo vyšší) Older_SB_version_detected = Detekována starší verze SB Pad = Pad Position = Position Position_X = Position X Position_y = Position y R = R R1 = R1 R2 = R2 R3 = R3 Red = Red Requested_mode_not_available! = Požadovaný mód není dostupný! Required_VGA_mode_not_supported = Požadovaný VGA mód není podporován Resolution_not_supported = Nepodporované rozlišení Right = Right Right_Stick = Right Stick Right_Stick_X = Right Stick X Right_Stick_Y = Right Stick Y SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibilní na portu 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = SB výstup musí být nainstalován předtím než lze číst ze vstupu SWIFT_Device_not_detected = SWIFT zařízení nedetekováno SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF nepodporuje široké virtuální obrazovky Second_OPL2_synth_not_found = Druhý OPL2 syntezátor nenalezen Select = Select Set_throttle_to_maximum = Nastavte plyn na maximum Set_throttle_to_minimum = Nastavte plyn na minimum Setting_DSP_parameters:_%s = Chyba při nastavování DSP parametrů: %s Setting_fragment_size:_%s = Chyba při nastavování velikosti fragmentu: %s Software_wavetable_synth = Softwarová wavetable syntéza Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI na portu %X Sound_Blaster_not_found = Sound Blaster nenalezen Soundscape_not_found = Soundscape nenalezen Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) na portu %X, s IRQ %d, DMA kanálem %d a waveportem %X Sound_system_not_installed = Zvukový systém není nainstalován Spinner = Spinner Square = Square Start = Start Stick = Stick Stick_X = Stick X Stick_Y = Stick Y Stick_%d = Stick %d The_sound_of_silence = Zvuky ticha This_driver_needs_local_display = Tento ovladač potřebuje lokální display This_driver_needs_root_privileges = Tento ovladač potřebuje kořenová oprávnění Throttle = Throttle Triangle = Triangle Trigger = Trigger Twist = Twist Unable_to_control_VT_switching = Nelze kontrolovat přepínání VT Unable_to_find_a_suitable_graphics_driver = Nepodařilo se najít odpovídající grafický ovladač Unable_to_find_a_usable_VT = Nelze najít použitelný VT Unable_to_map_video_memory = Nelze namapovat video paměť Unable_to_open = Nelze otevřít Unable_to_open_%s:_%s = Nelze otevřít %s: %s Unable_to_reopen_new_console = Nelze znovuotevřít novou konzoli Unsupported_color_depth = Nepodporovaná barevná hloubka Unsupported_memory_layout = Nepodporované uspořádání paměti Unsupported_sample_format = Nepodporovaný formát samplu Unsupported_screen_size = Nepodporovaná velikost obrazovky VBE/AF_Plug_and_Play_initialisation_failed = Nelze inicializacovat VBE/AF Plug and Play VBE/AF_device_not_present = VBE/AF není přítomno VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF nearptrs nejsou na této platformě podporovány VBE_%d.0_not_available = VBE %d.0 není dostupné VESA_function_0x4F02_failed = VESA funkce 0x4F02 selhala VESA_function_0x4F06_failed = VESA funkce 0x4F06 selhala VESA_mode_0x100_not_available = VESA mód 0x100 není dostupný VESA_not_available = VESA není dostupná VESA_protected_mode_interface_not_available = VESA rozhraní pro chráněný mód není dostupné VGA_only_supports_8_bit_color = VGA podporuje pouze 8-bitové barvy VT_WAITACTIVE_failure = VT_WAITACTIVE selhalo VidMode_extension_is_not_supported = VidMode rozšíření není podporováno Virtual_screen_size_too_large = Virtuální obrazovka je příliš velká Wingman_Warrior_not_connected = Wingman Warrior není připojen X = X Xtended_mode_only_supports_640x400 = Xtended mód podporuje pouze 640x400 Xtended_mode_only_supports_8_bit_color = Xtended mód podporuje pouze 8-bitové barvy Y = Y Yellow = Yellow Z = Z approx. = přibližný no_vsync = bez vertikální synchronizace %s:_%d_bits,_%s,_%d_bps,_%s = %s: %d bitů, %s, %d bps, %s %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) na portu %X, s IRQ %d a DMA kanálem %d %s_does_not_support_MIDI_input = %s nepodporuje MIDI vstup %s_does_not_support_audio_input = %s nepodporuje audio vstup %s_must_only_be_writeable_by_root = %s musí být zapisovatelný pouze rootem %s_not_found = %s nenalezen %s_on_port_%X = %s na portu %X %s:_%s = %s: %s unused = nepoužito _8_bpp_(256_color) = 8 bpp (256 barev) 15_bpp_(32K_color) = 15 bpp (32K barev) 16_bpp_(64K_color) = 16 bpp (64K barev) 24_bpp_(16M_color) = 24 bpp (16M barev) 32_bpp_(16M_color) = 32 bpp (16M barev) 4-button joystick = Čtyřtlačítkový joystick 6-button joystick = Šestitlačítkový joystick 8-button joystick = Osmitlačítkový joystick Adlib_(OPL2) = Adlib (OPL2) Adlib_(OPL3) = Adlib (OPL3) Adlib_(dual_OPL2) = Adlib (dvojitý OPL2) Agnostic = Agnostický ALSA = ALSA AWE32/EMU8000 = AWE32/EMU8000 BeOS_Keyboard = BeOS klávesnice DGA_graphics = DGA grafika DIGMID = DIGMID DirectDraw = DirectDraw DirectDraw_accel = Akcelerované DirectDraw DirectDraw_overlay = Překryvné DirectDraw DirectDraw_safe = Bezpečné DirectDraw DirectDraw_window = DirectDraw v okně DirectInput = DirectInput DirectX = DirectX DOS = DOS Dual_joysticks = Duální joystick Enlightened_Sound_Daemon = Enlightened Sound Daemon ESS_AudioDrive = ESS AudioDrive Fixed-rate_timer = Časovač s pevnou délkou intervalu Flightstick_Pro = Flightstick Pro Fullscreen = Fullscreen Fullscreen_DGA = Fullscreen DGA GamePad_Pro = GamePad Pro GDI = GDI GPM_repeater = GPM server (repeater) GrIP = GrIP GrIP_4-way = GrIP 4-way Linux_MS_mouse = Linuxová MS myš Linux_PS/2_mouse = Linuxová PS/2 myš Linux_analogue_joystick(s) = Linuxový analogový joystick(-y) Linux_console = Linuxová konzole Linux_console_keyboard = Linuxová klávesnice na konzoli Mickey_Mouse = Myšák Mickey Mode-X = Mode-X Mouse = Myš MPU-401 = MPU-401 N64pad-LPT1 = N64pad na LPT1 N64pad-LPT2 = N64pad na LPT2 N64pad-LPT3 = N64pad na LPT3 No_joystick = Bez joysticku No_mouse = Bez myši No_sound = Beze zvuku Open_Sound_System = Open Sound System PC_keyboard_(DOS) = PC klávesnice (DOS) Polling_mouse = Myš v dotazovacím módu PSXpad-LPT1 = PSXpad na LPT1 PSXpad-LPT2 = PSXpad na LPT2 PSXpad-LPT3 = PSXpad na LPT3 Safe_Fullscreen = Bezpečný fullscreen SB_MIDI_interface = SB MIDI rozhraní Sidewinder = Sidewinder SNESpad-LPT1 = SNESpad na LPT1 SNESpad-LPT2 = SNESpad na LPT2 SNESpad-LPT3 = SNESpad na LPT3 Sound_Blaster_1.0 = Sound Blaster 1.0 Sound_Blaster_1.5 = Sound Blaster 1.5 Sound_Blaster_2.0 = Sound Blaster 2.0 Sound_Blaster_Pro = Sound Blaster Pro Sound_Blaster_16 = Sound Blaster 16 Soundscape = Soundscape Standard_joystick = Standardní joystick Standard_VGA = Standardní VGA System = Systém SVGAlib = SVGAlib Timer = Časovač Unix_SIGALRM_timer = Unixový SIGALRM časovač Variable-rate_timer = Časovač s proměnnou délkou intervalu VBE/AF = VBE/AF VESA_1.x = VESA 1.x VESA_2.0_(banked) = VESA 2.0 (banked) VESA_2.0_(linear) = VESA 2.0 (linear) VESA_3.0 = VESA 3.0 Win32_joystick = Win32 joystick Win32_Multithreaded_Timer = Win32 časovač s více vlákny Win32_Singlethreaded_Timer = Win32 časovač s jedním vláknem Windows_Sound_System = Windows Sound System Wingman_Extreme = Wingman Extreme Wingman_Warrior = Wingman Warrior X-Windows = X-Windows X-Windows_graphics = X-Windows grafika X-Windows_keyboard = X-Windows klávesnice X-Windows_mouse = X-Windows myš Xtended_mode = Xtended mode fbcon = fbcon int_0x33_mouse = int 0x33 myš Button_1 = Tlačítko 1 Button_2 = Tlačítko 2 Button_3 = Tlačítko 3 Button_4 = Tlačítko 4 Button_5 = Tlačítko 5 Can_not_get_channel_setup = Nelze přečíst nastavení kanálu Can_not_open_framebuffer = Nelze otevřít framebuffer Can_not_set_channel_parameters = Nelze nastavit parametry kanálu DGA_1.0_is_required = Je vyžadováno DGA 1.0 DGA_2.0_or_newer_is_required = Je vyžadováno DGA 2.0 nebo novější IF-SEGA2/PCI:__create_linear_mapping_error = IF-SEGA2/PCI: chyba při _create_linear_mapping IF-SEGA2/PCI:__create_selector_error = IF-SEGA2/PCI: chyba při _create_selector IF-SEGA2/PCI:_device_not_found = IF-SEGA2/PCI: zařízení nenalezeno IF-SEGA2/PCI:_read_configuration_dword_error = IF-SEGA2/PCI: chyba při čtení dword hodnoty z konfigurace PCI_BIOS_not_installed = PCI BIOS není instalován Auto_fullscreen = Celoobrazovkový mód Auto_windowed = Okenní mód Can't_map_framebuffer = Nelze namapovat framebuffer Can_not_do_double_buffered_sound = Nelze použít double-bufferovaný zvuk Can_not_get_information_about_sound = Nelze zjistit informaci o zvuku Cannot_access_the_framebuffer = Nelze přistoupit k framebufferu Cannot_create_direct_context = Nelze vytvořit přímý kontext Cannot_create_offscreen_context = Nelze vytvořit mimoobrazovkový kontext Cannot_start_direct_context = Nelze spustit přímý kontext Insufficient_%s_voices_available = Nedostatečných %s hlasů je dostupných No = Ne Overlays_not_supported = Overlays nejsou podporovány Position_x = Position x SoundManager_3.0_or_later_required = Vyžadován SoundManager 3.0 nebo pozdější SoundManager_not_found = SoundManager nenalezen Unsupported_virtual_resolution = Nepodporované virtuální rozlišení VidMode_extension_requires_local_display = VidMode rozšíření vyžaduje lokální display Windowed_mode_not_supported = Okenní mód není podporován Yes = Ano colors = barev failed_on_channel_initialization = neúspěch při inicializaci kanálů open_NoteAllocator_failed = selhalo otevření NoteAllocatoru allegro-4.4.3.1/resource/language/catext.cfg0000664000175000017500000003230713437077643017670 0ustar siegesiegelanguage_name = Català [language] A = A Aim = Eix Aim_X = Eix X Aim_y = Eix y Analogue_Buttons = Butons analògics Apple_SoundManager_%d.x_%d_hz,_%d-bit,_%s_,_%d_ = Apple SoundManager %d.x %d hz, %d-bit, %s , %d approx. = aprox. Autodetect = Autodetectar Auto_fullscreen = Mode pantalla completa automàtic Auto_windowed = Mode en finestra automàtic AWE32_detection_failed_on_port_0x%04x = Detecció fallida de la AWE32 en el port 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = El controlador de la AWE32 ha tingut problemes amb les dades enllaçades AWE32_not_detected = AWE32 no detectada B1 = B1 B2 = B2 B3 = B3 B4 = B4 B5 = B5 B6 = B6 B7 = B7 B8 = B8 Back = Enrera Bad_VBE/AF_driver_ID_string = Cadena d'identificació del controlador VBE/AD invàlida Banked_framebuffer_not_available = Framebuffer per bancs no disponible B = B BLASTER_environment_variable_has_no_E_section = La variable d'entorn BLASTER no te secció E BLASTER_environment_variable_not_set = Variable d'entorn BLASTER no definida Blue = Azul Button_1 = Botón 1 Button_2 = Botón 2 Button_3 = Botón 3 Button_4 = Botón 4 Button_5 = Botón 5 Cancel = Cancel·lar Cannot_access_the_framebuffer = Impossible accedir al framebuffer Can_not_allocate_audio_buffer = Impossible reservar el buffer d'audio Cannot_create_direct_context = Impossible crear un contexte directe Cannot_create_offscreen_context = Imposible crear un contexte fora de pantalla Can_not_create_XImage = Impossible crear una XImage Can_not_do_double_buffered_sound = Impossible utilitzar un doble buffer de so Cannot_enable_linear_addressing = Impossible activar el direccionament linial Can_not_get_channel_setup = Impossible obtenir la configuració del canal Can_not_get_information_about_sound = Impossible obtenir informació del so Can_not_get_video_mode_settings = Impossible obtenir els paràmetres dels modes de video Can_not_grab_keyboard = Impossible obtenir el control del teclat Can_not_grab_mouse = Impossible obtenir el control del ratolí Can_not_init_software_mixer = Impossible iniciar el mesclador per software Can_not_install_colormap = Impossible instal·lar el mapa de colors Can_not_obtain_user_name = Impossible obtenir el nombre d'usuari Can_not_open_card/pcm_device = Impossible accedir a la tarja/controladora PCM Can_not_open_framebuffer = Impossible accedir al framebuffer Can_not_query_DirectVideo = Impossible interrogar DirectVideo Can_not_set_channel_parameters = Impossible definir els paràmetros del canal Can_not_set_video_mode = Impossible activar el modw de video Cannot_start_direct_context = Impossible iniciar el contexte directe Can_not_switch_to_DGA_mode = Impossible canviar al mode DGA Can't_find_VBEAF.DRV = Impossible trobar VBEAF.DRV Can't_make_linear_screen_bitmap = Impossible crear un bitmap linial de pantalla Can't_map_framebuffer = Impossible direccionar el framebuffer Can't_map_memory_for_VBE/AF = Impossible direccionar la memòria per VBE/AF Can't_open_framebuffer_%s = Impossible accedir al framebuffer %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Impossible usar l'interfaç MIDI y el DSP de la SB al mateix temps Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Tarjeta #%d, dispositivo #%d: %d bits, %s, %d bps, %s C = C C_Down = C Avall Centre_the_hat = Centri el hat del joystick Circle = Circle C_Left = C Esquerra colors = colors Could_not_find_GRIP.GLL = Impossible trobar GRIP.GLL Could_not_initialize_GrIP_system = Impossible iniciar el sistema GrIP C_Right = C Dreta Cross = Creu C_Up = C Adalt Device_connected_is_not_a_Wingman_Warrior = El dispositiu conectat no és un Wingman Warrior DGA_1.0_is_required = Es requireix DGA 1.0 DGA_2.0_or_newer_is_required = Es requireix DGA 2.0 o superior DGA_extension_is_not_supported = Extensió DGA no suportada Dial = Marcar Digital_input_driver_not_found = Controlador d'entrada digital no trobat Digital_sound_driver_not_found = Controlador de so digital no trobat DIGMID_patch_set_not_found = Fitxer patch per a DIGMID no trobat Direction_Pad = Pad de direcció Direction_Pad_X = Eix X del pad de direcció Direction_Pad_Y = Eix Y del pad de direcció DirectVideo_is_not_supported = DirectVideo no suportat DrawSprocket_%d_x_%d,_%dbpp,_%dhz = DrawSprocket %d x %d, %dbpp, %dhz Dual_OPL2_synths = Sintetitzador OP2 dual Error_finding_our_VT:_%s = Impossible trobar el nostre VT: %s Error_reading_.IBK_file_'%s' = Error de lectura del fitxer .IBK '%s' Error_setting_VGA_video_mode = Error activant el mode de video VGA ESS_AudioDrive_not_found = ESS AudioDrive no trobat ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) al port %X, usant el IRQ %d y el canal DMA %d failed_on_channel_initialization = error iniciant canal Failed_to_init_digital_input_driver = Error iniciant el controlador d'entrada digital Failed_to_init_digital_sound_driver = Error iniciant el controlador de sonido digital Failed_to_init_MIDI_input_driver = Error iniciant el controlador d'entrada MIDI Failed_to_init_MIDI_music_driver = Error iniciant el controlador musical MIDI Failed_to_set_VBE/AF_mode = Error activant el mode VBE/AF Fatal_error:_unable_to_activate_the_Allegro_system = Error fatal: impossible activar el sistema d'Allegro Fatal_error:_unable_to_set_GFX_SAFE = Error fatal: impossible activar el mode GFX_SAFE Framebuffer_ioctl()_failed = Fallida a l'usar ioctl() en el framebuffer Framebuffer_resolution_not_available = Resolució del framebuffer no disponible Getting_buffer_size:_%s = Obtenint el tamany del buffer: %s Graphics_Mode = Mode gràfic Green = Verd Hardware_acceleration_not_available = Acceleració per hardware no disponible Hardware_scrolling_not_supported = Scroll per hardware no disponible Hat = Hat del joystick I_Button = Botó I IF-SEGA2/PCI:__create_linear_mapping_error = IF-SEGA2/PCI: error de _create_linear_mapping IF-SEGA2/PCI:__create_selector_error = IF-SEGA2/PCI: error de _create_selector IF-SEGA2/PCI:_device_not_found = IF-SEGA2/PCI: dispositiu no trobat IF-SEGA2/PCI:_read_configuration_dword_error = IF-SEGA2/PCI: error al llegir la paraula doble de configuració II_Button = Botó II Input_is_not_supported = Entrada no suportada Insufficient_%s_voices_available = Insuficients veus (%s) disponibles Insufficient_video_memory = Memòria de video insuficient Internal_error = Error intern L1_Button = Botó L1 L1 = L1 L2 = L2 L3 = L3 Left = Esquerra Left_Stick = Palanca esquerra Left_Stick_X = Eix X de la palanca esquerra Left_Stick_Y = Eix Y de la palanca esquerra Linear_framebuffer_not_available = Framebuffer linial no disponible L = L MIDI_input_driver_not_found = Controlador d'entrada MIDI no trobat MIDI = MIDI MIDI_music_driver_not_found = Controlador musical MIDI no trobat M = M Mode-X_only_supports_8_bit_color = El Mode-X solament suporta color de 8 bits Move_stick_2_to_the_bottom_right = Mogui la palanca 2 del joystick abaix y a la dreta Move_stick_2_to_the_top_left = Mogui la palanca 2 del joystick amunt y a l'esquerra Move_stick_to_the_bottom_right = Mogui el joystick abaix y a la derecha Move_stick_to_the_top_left = Mogui el joystick amunt y a la izquierda Move_the_hat_down = Mogui el hat del joystick abaix Move_the_hat_left = Mogui el hat del joystick a l'esquerra Move_the_hat_right = Mogui el hat del joystick a la dreta Move_the_hat_up = Mogui el hat del joystick amunt MPU-401_and_%s_conflict_over_IRQ_%d = Hi ha un conflicte a l'IRQ %d entre el MPU-401 y %s MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = Interfaç MIDI MPU-401 en el port %X, utilitzant l'IRQ %d MPU-401_not_found = MPU-401 no trobat No_GrIP_devices_available = No hi ha controladors GrIP disponibles No_joysticks_found = No s'ha trobat cap joystick No = No No_server = No hi ha servidor No_support_synth_type_found = No s'ha trobat cap tipus de sintetitzador suportat Not_a_valid_VGA_resolution = No és una resolució VGA vàlida Not_a_VGA_mode-X_resolution = No és una resolució VGA Mode-X vàlida Not_enough_memory = Memòria insuficient Not_in_stereo_or_mono_mode = No es troba en mode mono ni stereo no_vsync = sense vsync No_window = Cap finestra Obsolete_VBE/AF_version_(need_2.0_or_greater) = Versió VBE/AF obsoleta (necessària 2.0 o superior) OK = Acceptar Older_SB_version_detected = Versió de SB antiga detectada open_NoteAllocator_failed = fallida en NoteAllocator obert OPL2_synth = Sintetitzador OPL2 OPL3_synth_not_found = Sintetitzador OPL3 no trobat OPL3_synth = Sintetitzador OPL3 OPL_synth_not_found = Sintetitzador OPL no trobat OSS_output_driver_must_be_installed_before_input_can_be_read = El controlador de sortida OSS s'ha d'instal·lar abans que es pugui llegir l'entrada Overlays_not_supported = Overlays no suportats Pad = Pad PCI_BIOS_not_installed = BIOS PCI no instalada Position = Posició Position_x = Posició x Position_X = Posició X Position_y = Posició y R1 = R1 R2 = R2 R3 = R3 Red = Vermell Required_VGA_mode_not_supported = Mode VGA requerit no trobat Resolution_not_supported = Resolució no suportada Right = Dreta Right_Stick = Palanca dreta Right_Stick_X = Eix X de la palanca dreta Right_Stick_Y = Eix Y de la palanca dreta R = R SB_AWE32/compatible_on_port_0x%04x = SB AWE32/compatible al port 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = El controlador de sortida SB s'ha d'instal·lar abans que es pugui llegir l'entrada %s:_can_not_open = %s: impossible obrir SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = Els controladores SciTech VBE/AF no suporten pantalles virtuals amples %s:_%d_bits,_%s,_%d_bps,_%s = %s: %d bits, %s, %d bps, %s %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) al port %X, usant l'IRQ %d y el canal DMA %d %s_does_not_support_audio_input = %s no suporta entrada d'audio %s_does_not_support_MIDI_input = %s no suporta entrada MIDI Second_OPL2_synth_not_found = Segon sintetitzador OPL2 no trobat Select = Seleccionar Set_throttle_to_maximum = Situi l'accelerador al màxim Set_throttle_to_minimum = Situi l'accelerador al mínim Setting_DSP_parameters:_%s = Configurant els paràmetres del DSP: %s Setting_fragment_size:_%s = Configurant el tamany del fragment: %s %s_must_only_be_writeable_by_root = %s solament ha de ser accessible per escriptura pel root %s_not_found = %s no trobat Software_wavetable_synth = Sintetitzador de software per tabla d'ondes %s_on_port_%X = %s al port %X Sound_Blaster_MIDI_interface_on_port_%X = Interfaç Sound Blaster MIDI al port %X Sound_Blaster_not_found = Sound Blaster no trobada SoundManager_3.0_or_later_required = Es requireix una SoundManager 3.0 o superior SoundManager_not_found = SoundManager no trobada Soundscape_not_found = Soundscape no trobada Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) al port %X, usant l'IRQ %d, el canal DMA %d y el port d'ondes %X Sound_system_not_installed = Sistema de so no instal·lat Spinner = Spinner Square = Cuadrat %s:_%s = %s: %s Start = Començar Stick_%d = Palanca %d Stick = Palanca Stick_X = Eix X de la palanca Stick_Y = Eix Y de la palanca SWIFT_Device_not_detected = Dispositiu SWIFT no detectat The_sound_of_silence = El so del silenci This_driver_needs_local_display = Aquest controlador necessita una pantalla local This_driver_needs_root_privileges = Aquest controlador necessita privilegis de root Throttle = Accelerador Triangle = Triangle Trigger = Gallet Twist = Twist Unable_to_control_VT_switching = Impossible controlar el canvi de VT Unable_to_find_a_suitable_graphics_driver = Impossible trobar un controlador gràfic adecuat Unable_to_find_a_usable_VT = Impossible trobar un VT que es pugui utilitzar Unable_to_map_video_memory = Impossible direccionar la memòria de video Unable_to_open_%s:_%s = Impossible obrir %s: %s Unable_to_open = Impossible obrir Unable_to_reopen_new_console = Impossible reobrir una nova consola Unsupported_color_depth = Profunditat de color no suportada Unsupported_memory_layout = Disposició de memòria no suportada Unsupported_sample_format = Format de sample no suportat Unsupported_screen_size = Tamany de pantalla no suportat Unsupported_virtual_resolution = Resolució de pantalla virtual no suportat unused = no utilitzat VBE/AF_device_not_present = Controlador VBE/AF absent VBE/AF_nearptrs_not_supported_on_this_platform = Els punters curts de VBE/AF no són suportats en aquesta plataforma VBE/AF_Plug_and_Play_initialisation_failed = Fallida a la inicialització de VBE/AF Plug and Play VBE_%d.0_not_available = VBE %d.0 no disponible VESA_function_0x4F02_failed = Fallida a la funció VESA 0x4F02 VESA_function_0x4F06_failed = Fallida a la funció VESA 0x4F06 VESA_mode_0x100_not_available = Mode VESA 0x100 no disponible VESA_not_available = VESA no disponible VESA_protected_mode_interface_not_available = Interfaç VESA en mode protegit no disponible VGA_only_supports_8_bit_color = VGA solament suporta color de 8 bits VidMode_extension_is_not_supported = Extensió VidMode no suportada VidMode_extension_requires_local_display = l'extensió VidMode requireix una pantalla local Virtual_screen_size_too_large = Tamany de pantalla virtual massa gran VT_WAITACTIVE_failure = Fallida de VT_WAITACTIVE Windowed_mode_not_supported = Mode en finestra no suportat Wingman_Warrior_not_connected = Wingman Warrior no conectat Xtended_mode_only_supports_640x400 = El mode Xtended solament suporta 640x400 Xtended_mode_only_supports_8_bit_color = El mode Xtended solament suporta color de 8 bits X = X Yellow = Groc Yes = Si Y = Y Z = Z allegro-4.4.3.1/resource/language/estext.cfg0000664000175000017500000003260513437077643017715 0ustar siegesiegelanguage_name = Español [language] A = A Aim = Eje Aim_X = Eje X Aim_y = Eje y Analogue_Buttons = Botones analógicos Apple_SoundManager_%d.x_%d_hz,_%d-bit,_%s_,_%d_ = Apple SoundManager %d.x %d hz, %d-bit, %s , %d approx. = aprox. Autodetect = Autodetectar Auto_fullscreen = Modo pantalla completa automático Auto_windowed = Modo en ventana automático AWE32_detection_failed_on_port_0x%04x = Detección fallida de la AWE32 en el puerto 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = El controlador de la AWE32 tuvo problemas con los datos enlazados AWE32_not_detected = AWE32 no detectada B1 = B1 B2 = B2 B3 = B3 B4 = B4 B5 = B5 B6 = B6 B7 = B7 B8 = B8 Back = Atrás Bad_VBE/AF_driver_ID_string = Cadena de identificación del controlador VBE/AD inválida Banked_framebuffer_not_available = Framebuffer por bancos no disponible B = B BLASTER_environment_variable_has_no_E_section = La variable de entorno BLASTER no tiene sección E BLASTER_environment_variable_not_set = Variable de entorno BLASTER no definida Blue = Azul Button_1 = Botón 1 Button_2 = Botón 2 Button_3 = Botón 3 Button_4 = Botón 4 Button_5 = Botón 5 Cancel = Cancelar Cannot_access_the_framebuffer = Imposible acceder al framebuffer Can_not_allocate_audio_buffer = Imposible reservar el buffer de audio Cannot_create_direct_context = Imposible crear un contexto directo Cannot_create_offscreen_context = Imposible crear un contexto fuera de pantalla Can_not_create_XImage = Imposible crear una XImage Can_not_do_double_buffered_sound = Imposible utilizar un doble buffer de sonido Cannot_enable_linear_addressing = Imposible activar el direccionamiento lineal Can_not_get_channel_setup = Imposible obtener la configuración del canal Can_not_get_information_about_sound = Imposible obtener información del sonido Can_not_get_video_mode_settings = Imposible obtener los parámetros de los modos de vídeo Can_not_grab_keyboard = Imposible obtener el control del teclado Can_not_grab_mouse = Imposible obtener el control del ratón Can_not_init_software_mixer = Imposible iniciar el mezclador por software Can_not_install_colormap = Imposible instalar el mapa de colores Can_not_obtain_user_name = Imposible obtener el nombre de usuario Can_not_open_card/pcm_device = Imposible acceder a la tarjeta/controladora PCM Can_not_open_framebuffer = Imposible acceder al framebuffer Can_not_query_DirectVideo = Imposible de interrogar DirectVideo Can_not_set_channel_parameters = Imposible definir los parámetros del canal Can_not_set_video_mode = Imposible activar el modo de vídeo Cannot_start_direct_context = Imposible iniciar el contexto directo Can_not_switch_to_DGA_mode = Imposible cambiar al modo DGA Can't_find_VBEAF.DRV = Imposible encontrar VBEAF.DRV Can't_make_linear_screen_bitmap = Imposible crear un bitmap lineal de pantalla Can't_map_framebuffer = Imposible direccionar el framebuffer Can't_map_memory_for_VBE/AF = Imposible direccionar la memoria para VBE/AF Can't_open_framebuffer_%s = Imposible acceder al framebuffer %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Imposible usar el interfaz MIDI y el DSP de la SB al mismo tiempo Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Tarjeta #%d, dispositivo #%d: %d bits, %s, %d bps, %s C = C C_Down = C Abajo Centre_the_hat = Centre el hat del joystick Circle = Círculo C_Left = C Izquierda colors = colores Could_not_find_GRIP.GLL = Imposible encontrar GRIP.GLL Could_not_initialize_GrIP_system = Imposible iniciar el sistema GrIP C_Right = C Derecha Cross = Cruz C_Up = C Arriba Device_connected_is_not_a_Wingman_Warrior = El dispositivo conectado no es un Wingman Warrior DGA_1.0_is_required = Se requiere DGA 1.0 DGA_2.0_or_newer_is_required = Se requiere DGA 2.0 o superior DGA_extension_is_not_supported = Extensión DGA no soportada Dial = Marcar Digital_input_driver_not_found = Controlador de entrada digital no encontrado Digital_sound_driver_not_found = Controlador de sonido digital no encontrado DIGMID_patch_set_not_found = Fichero de parches para DIGMID no encontrado Direction_Pad = Pad de dirección Direction_Pad_X = Eje X del pad de dirección Direction_Pad_Y = Eje Y del pad de dirección DirectVideo_is_not_supported = DirectVideo no soportado DrawSprocket_%d_x_%d,_%dbpp,_%dhz = DrawSprocket %d x %d, %dbpp, %dhz Dual_OPL2_synths = Sintetizador OP2 dual Error_finding_our_VT:_%s = Imposible encontrar nuestro VT: %s Error_reading_.IBK_file_'%s' = Error de lectura del fichero .IBK '%s' Error_setting_VGA_video_mode = Error activando el modo de vídeo VGA ESS_AudioDrive_not_found = ESS AudioDrive no encontrado ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) en el puerto %X, usando el IRQ %d y el canal DMA %d failed_on_channel_initialization = error iniciando canal Failed_to_init_digital_input_driver = Error iniciando el controlador de entrada digital Failed_to_init_digital_sound_driver = Error iniciando el controlador de sonido digital Failed_to_init_MIDI_input_driver = Error iniciando el controlador de entrada MIDI Failed_to_init_MIDI_music_driver = Error iniciando el controlador musical MIDI Failed_to_set_VBE/AF_mode = Error activando el modo VBE/AF Fatal_error:_unable_to_activate_the_Allegro_system = Error fatal: imposible activar el sistema de Allegro Fatal_error:_unable_to_set_GFX_SAFE = Error fatal: imposible activar el modo GFX_SAFE Framebuffer_ioctl()_failed = Fallo al usar ioctl() en el framebuffer Framebuffer_resolution_not_available = Resolución del framebuffer no disponible Getting_buffer_size:_%s = Obteniendo el tamaño del buffer: %s Graphics_Mode = Modo gráfico Green = Verde Hardware_acceleration_not_available = Aceleración por hardware no disponible Hardware_scrolling_not_supported = Scroll por hardware no disponible Hat = Hat del joystick I_Button = Botón I IF-SEGA2/PCI:__create_linear_mapping_error = IF-SEGA2/PCI: error de _create_linear_mapping IF-SEGA2/PCI:__create_selector_error = IF-SEGA2/PCI: error de _create_selector IF-SEGA2/PCI:_device_not_found = IF-SEGA2/PCI: dispositivo no encontrado IF-SEGA2/PCI:_read_configuration_dword_error = IF-SEGA2/PCI: error al leer palabra doble de configuración II_Button = Botón II Input_is_not_supported = Entrada no soportada Insufficient_%s_voices_available = Insuficientes voces (%s) disponibles Insufficient_video_memory = Memoria de vídeo insuficiente Internal_error = Error interno L1_Button = Botón L1 L1 = L1 L2 = L2 L3 = L3 Left = Izquierda Left_Stick = Palanca izquierda Left_Stick_X = Eje X de la palanca izquierda Left_Stick_Y = Eje Y de la palanca izquierda Linear_framebuffer_not_available = Framebuffer lineal no disponible L = L MIDI_input_driver_not_found = Controlador de entrada MIDI no encontrado MIDI = MIDI MIDI_music_driver_not_found = Controlador musical MIDI no encontrado M = M Mode-X_only_supports_8_bit_color = El Modo-X solo soporta color de 8 bits Move_stick_2_to_the_bottom_right = Mueva la palanca 2 del joystick abajo y a la derecha Move_stick_2_to_the_top_left = Mueva la palanca 2 del joystick arriba y a la izquierda Move_stick_to_the_bottom_right = Mueva el joystick abajo y a la derecha Move_stick_to_the_top_left = Mueva el joystick arriba y a la izquierda Move_the_hat_down = Mueva el hat del joystick abajo Move_the_hat_left = Mueva el hat del joystick a la izquierda Move_the_hat_right = Mueva el hat del joystick a la derecha Move_the_hat_up = Mueva el hat del joystick arriba MPU-401_and_%s_conflict_over_IRQ_%d = Hay un conflicto en el IRQ %d entre el MPU-401 y %s MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = Interfaz MIDI MPU-401 en el puerto %X, utilizando el IRQ %d MPU-401_not_found = MPU-401 no encontrado No_GrIP_devices_available = No hay controladores GrIP disponibles No_joysticks_found = No se encontró ningún joystick No = No No_server = No hay servidor No_support_synth_type_found = No se encontró ningún tipo de sintetizador soportado Not_a_valid_VGA_resolution = No es una resolución VGA válida Not_a_VGA_mode-X_resolution = No es una resolución VGA Modo-X válida Not_enough_memory = Memoria insuficiente Not_in_stereo_or_mono_mode = No se encuentra en modo mono o stereo no_vsync = sin vsync No_window = Ninguna ventana Obsolete_VBE/AF_version_(need_2.0_or_greater) = Versión VBE/AF obsoleta (necesita 2.0 o superior) OK = Aceptar Older_SB_version_detected = Versión de SB antigua detectada open_NoteAllocator_failed = fallo en NoteAllocator abierto OPL2_synth = Sintetizador OPL2 OPL3_synth_not_found = Sintetizador OPL3 no encontrado OPL3_synth = Sintetizador OPL3 OPL_synth_not_found = Sintetizador OPL no encontrado OSS_output_driver_must_be_installed_before_input_can_be_read = El controlador de salida OSS debe ser instalado antes de que se pueda leer la entrada Overlays_not_supported = Overlays no soportados Pad = Pad PCI_BIOS_not_installed = BIOS PCI no instalada Position = Posición Position_x = Posición x Position_X = Posición X Position_y = Posición y R1 = R1 R2 = R2 R3 = R3 Red = Rojo Required_VGA_mode_not_supported = Modo VGA requerido no soportado Resolution_not_supported = Resolución no soportada Right = Derecha Right_Stick = Palanca derecha Right_Stick_X = Eje X de la palanca derecha Right_Stick_Y = Eje Y de la palanca derecha R = R SB_AWE32/compatible_on_port_0x%04x = SB AWE32/compatible en el puerto 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = El controlador de salida SB debe ser instalado antes de que se pueda leer la entrada %s:_can_not_open = %s: imposible abrir SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = Los controladores SciTech VBE/AF no soportan pantallas virtuales anchas %s:_%d_bits,_%s,_%d_bps,_%s = %s: %d bits, %s, %d bps, %s %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) en el puerto %X, usando el IRQ %d y el canal DMA %d %s_does_not_support_audio_input = %s no soporta entrada de audio %s_does_not_support_MIDI_input = %s no soporta entrada MIDI Second_OPL2_synth_not_found = Segundo sintetizador OPL2 no encontrado Select = Seleccionar Set_throttle_to_maximum = Sitúe el acelerador al máximo Set_throttle_to_minimum = Sitúe el acelerador al mínimo Setting_DSP_parameters:_%s = Configurando los parámetros del DSP: %s Setting_fragment_size:_%s = Configurando el tamaño del fragmento: %s %s_must_only_be_writeable_by_root = %s solo debe ser accesible para escritura por el root %s_not_found = %s no encontrado Software_wavetable_synth = Sintetizador de software por tabla de ondas %s_on_port_%X = %s en el puerto %X Sound_Blaster_MIDI_interface_on_port_%X = Interfaz Sound Blaster MIDI en el puerto %X Sound_Blaster_not_found = Sound Blaster no encontrada SoundManager_3.0_or_later_required = Se requiere una SoundManager 3.0 o superior SoundManager_not_found = SoundManager no encontrada Soundscape_not_found = Soundscape no encontrada Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) en el puerto %X, usando el IRQ %d, el canal DMA %d y el puerto de ondas %X Sound_system_not_installed = Sistema de sonido no instalado Spinner = Spinner Square = Cuadrado %s:_%s = %s: %s Start = Comenzar Stick_%d = Palanca %d Stick = Palanca Stick_X = Eje X de la palanca Stick_Y = Eje Y de la palanca SWIFT_Device_not_detected = Dispositivo SWIFT no detectado The_sound_of_silence = El sonido del silencio This_driver_needs_local_display = Este controlador necesita una pantalla local This_driver_needs_root_privileges = Este controlador necesita privilegios de root Throttle = Acelerador Triangle = Triángulo Trigger = Gatillo Twist = Twist Unable_to_control_VT_switching = Imposible controlar el cambio de VT Unable_to_find_a_suitable_graphics_driver = Imposible encontrar un controlador gráfico adecuado Unable_to_find_a_usable_VT = Imposible encontrar un VT que se pueda utilizar Unable_to_map_video_memory = Imposible direccionar la memoria de vídeo Unable_to_open_%s:_%s = Imposible abrir %s: %s Unable_to_open = Imposible abrir Unable_to_reopen_new_console = Imposible reabrir una nueva consola Unsupported_color_depth = Profundidad de color no soportada Unsupported_memory_layout = Disposición de memoria no soportada Unsupported_sample_format = Formato de sample no soportado Unsupported_screen_size = Tamaño de pantalla no soportado Unsupported_virtual_resolution = Resolución de pantalla virtual no soportada unused = no utilizado VBE/AF_device_not_present = Controlador VBE/AF absente VBE/AF_nearptrs_not_supported_on_this_platform = Los punteros cortos de VBE/AF no son soportados en esta plataforma VBE/AF_Plug_and_Play_initialisation_failed = Fallo en la iniciación de VBE/AF Plug and Play VBE_%d.0_not_available = VBE %d.0 no disponible VESA_function_0x4F02_failed = Fallo en la función VESA 0x4F02 VESA_function_0x4F06_failed = Fallo en la función VESA 0x4F06 VESA_mode_0x100_not_available = Modo VESA 0x100 no disponible VESA_not_available = VESA no disponible VESA_protected_mode_interface_not_available = Interfaz VESA en modo protegido no disponible VGA_only_supports_8_bit_color = VGA solo soporta color de 8 bits VidMode_extension_is_not_supported = Extensión VidMode no soportada VidMode_extension_requires_local_display = la extensión VidMode requiere una pantalla local Virtual_screen_size_too_large = Tamaño de pantalla virtual demasiado grande VT_WAITACTIVE_failure = Fallo de VT_WAITACTIVE Windowed_mode_not_supported = Modo en ventana no soportado Wingman_Warrior_not_connected = Wingman Warrior no conectado Xtended_mode_only_supports_640x400 = El modo Xtended solo soporta 640x400 Xtended_mode_only_supports_8_bit_color = El modo Xtended solo soporta color de 8 bits X = X Yellow = Amarillo Yes = Sí Y = Y Z = Z allegro-4.4.3.1/resource/language/detext.cfg0000664000175000017500000001303713437077643017674 0ustar siegesiegelanguage_name = German [language] %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) an Port %X, verwendet IRQ %d und DMA-Kanal %d %s_does_not_support_audio_input = %s unterstützt keine Audio-Eingabe %s_does_not_support_MIDI_input = %s unterstützt keine MIDI-Eingabe %s_not_found = %s nicht gefunden %s_on_port_%X = %s an Port %X 4-button_joystick = 4-Tasten-Joystick 6-button_joystick = 6-Tasten-Joystick 8-button_joystick = 8-Tasten-Joystick AWE32_detection_failed_on_port_0x%04x = Automatischen Erkennung des AWE32 an Port 0x%04x fehlgeschlagen AWE32_driver:_had_trouble_with_the_embedded_data = AWE32-Treiber: Probleme mit eingebetteten Daten AWE32_not_detected = AWE32 nicht erkannt Bad_VBE/AF_driver_ID_string = Ungültiger VBE/AF-Treiber ID-String Banked_framebuffer_not_available = Banked Framebuffer nicht verfügbar BLASTER_environment_variable_has_no_E_section = BLASTER-Umgebungsvariable enthält keine E-Sektion BLASTER_environment_variable_not_set = BLASTER-Umgebungsvariable nicht gesetzt Can't_find_VBEAF.DRV = VBEAF.DRV nicht gefunden Can't_make_linear_screen_bitmap = Fehler beim Erstellen des lineares Bildschirmbitmaps Can't_map_memory_for_VBE/AF = Speicher für VBE/AF konnte nicht gemappt werden Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = SB MIDI-Interface und DSP können nicht zur selben Zeit verwendet werden Cancel = Abbruch Centre_the_hat = Zentriere den Hat digital = digital DIGMID_patch_set_not_found = DIGMID-Soundset nicht gefunden Disk_Error = Zugriffsfehler Dual_joysticks = Dual Joysticks Dual_OPL2_synths = Dual OPL2 Synths Error_reading_.IBK_file_'%s' = Fehler beim Lesen der .IBK-Datei '%s' Error_setting_video_mode = Fehler beim Setzen des Grafikmodus ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) an Port %X, verwendet IRQ %d und DMA-Kanal %d ESS_AudioDrive_not_found = ESS AudioDrive nicht gefunden Failed_to_set_VBE/AF_mode = Fehler beim Setzen des VBE/AF-Modus Flightstick_Pro = Flightstick Pro Graphics_Mode = Grafikmodus Hardware_acceleration_not_available = Hardwarebeschleunigung nicht verfügbar Hardware_scrolling_not_supported = Hardware-Scrolling nicht unterstützt Hat = Hat Insufficient_%s_voices_available = Nicht genügend %s Stimmen verfügbar Insufficient_video_memory = Nicht genügend Grafikspeicher Linear_framebuffer_not_available = Linearer Framebuffer nicht verfügbar MIDI = MIDI Mode-X_only_supports_8_bit_color = Mode-X unterstützt nur 256 Farben Move_stick_2_to_the_bottom_right = Bewege Joystick 2 in die rechte, untere Ecke Move_stick_2_to_the_top_left = Bewege Joystick 2 in die linke, obere Ecke Move_stick_to_the_bottom_right = Bewege den Joystick in die rechte, untere Ecke Move_stick_to_the_top_left = Bewege den Joystick in die linke, obere Ecke Move_the_hat_down = Bewege den Hat nach unten Move_the_hat_left = Bewege den Hat nach links Move_the_hat_right = Bewege den Hat nach rechts Move_the_hat_up = Bewege den Hat nach oben MPU-401_and_%s_conflict_over_IRQ_%d = Konflikt zwischen MPU-401 und %s auf IRQ %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI-Interface an Port %X, verwendet IRQ %d MPU-401_not_found = MPU-401 nicht gefunden Not_a_valid_VGA_resolution = Ungültige VGA-Auflösung Not_a_VGA_mode-X_resolution = Ungültige VGA Mode-X Auflösung Obsolete_VBE/AF_version_(need_2.0_or_greater) = Veraltete VBE/AF-Version (es wird v2.0 oder höher benötigt) OK = OK Older_SB_version_detected = Ältere SB-Version wurde erkannt OPL_synth_not_found = OPL-Synth nicht gefunden OPL2_synth = OPL2 Synth OPL3_synth = OPL3 Synth OPL3_synth_not_found = OPL3-Synth nicht gefunden Resolution_not_supported = Auflösung wird nicht unterstützt SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibel an Port 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = SB-Ausgabe-Treiber müssen installiert werden, bevor SB-Eingabe stattfinden kann SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF-Treiber unterstützen keine breiten, virtuellen Screens Second_OPL2_synth_not_found = Zweiter OPL2-Synth nicht gefunden Set_throttle_to_maximum = Schubkontrolle auf Maximum setzen Set_throttle_to_minimum = Schubkontrolle auf Minimum setzen Software_wavetable_synth = Software-Wavetablesynthese Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI-Interface an Port %X Sound_Blaster_not_found = Sound Blaster nicht gefunden Sound_system_not_installed = Soundsystem nicht installiert Standard_joystick = Standard-Joystick Stick = Steuerknüppel The_sound_of_silence = Der Klang der Stille Throttle = Schubkontrolle unused = unbenutzt VBE_%d.0_not_available = VBE %d.0 nicht verfügbar VBE_mode_not_available = VBE-Modus nicht verfügbar VBE/AF_device_not_present = VBE/AF-Gerät nicht verfügbar VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF-nearptrs werden auf dieser Plattform nicht unterstützt VBE/AF_Plug_and_Play_initialisation_failed = VBE/AF-Plug&Play-Initialisierung fehlgeschlagen VESA_function_0x4F02_failed = VESA-Funktion 0x4F02 fehlgeschlagen VESA_function_0x4F06_failed = VESA-Funktion 0x4F06 fehlgeschlagen VESA_mode_0x100_not_available = VESA-Modus 0x100 nicht verfügbar VESA_not_available = VESA nicht verfügbar VESA_protected_mode_interface_not_available = VESA-Protected-Mode-Interface nicht verfügbar VGA_only_supports_8_bit_color = VGA unterstützt nur 256 Farben Virtual_screen_size_too_large = Virtueller Bildschirmbereich zu groß Wingman_Extreme = Wingman Extreme Xtended_mode_only_supports_640x400 = Xtended-Modus unterstützt nur 640x400 Bildpunkte Xtended_mode_only_supports_8_bit_color = Xtended-Modus unterstützt nur 256 Farben allegro-4.4.3.1/resource/language/rutext.cfg0000664000175000017500000001660313437077643017734 0ustar siegesiegelanguage_name = Russian [language] %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) на порте %X, использует прерывание %d и канал DMA %d %s_does_not_support_audio_input = %s не поддерживает аудио-ввод %s_does_not_support_MIDI_input = %s не поддерживает ввод MIDI %s_not_found = Нет %s %s_on_port_%X = %s на порте %X 4-button_joystick = 4-х кнопочный джойстик 6-button_joystick = 6-ти кнопочный джойстик 8-button_joystick = 8-ми кнопочный джойстик AWE32_detection_failed_on_port_0x%04x = Проблемы с определением AWE32 на порте 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = Драйвер AWE32:проблемы с вложенными данными AWE32_not_detected = Не обнаружена AWE32 Bad_VBE/AF_driver_ID_string = Неверная идентификационная строка драйвера VBE/AF Banked_framebuffer_not_available = Переключаемы буфер кадра недоступен BLASTER_environment_variable_has_no_E_section = Переменная окружения BLASTER не имеет секции E BLASTER_environment_variable_not_set = Переменная окружения BLASTER не задана Can't_find_VBEAF.DRV = Невозможно найти VBEAF.DRV Can't_make_linear_screen_bitmap = Невозможно создать линейный растр экрана Can't_map_memory_for_VBE/AF = Невозможно отразить память для VBE/AF Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Невозможно одновременно использовать MIDI-интерфейс Sound Blaster'а и его DSP Cancel =Отмена Centre_the_hat = Калибровка направления джойстика digital = Цифровой DIGMID_patch_set_not_found = Недоступен Патчт-комплект к DIGMID Disk_Error = Ошибка диска Dual_joysticks = Сдвоенные джойстики Dual_OPL2_synths = Сдвоенные синтезаторы OPL2 Error_reading_.IBK_file_'%s' = Ошибка чтения .IBK-файла '%s' Error_setting_video_mode = Ошибка установки видеорежима ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) на порту %X, использует прерывание %d и канал DMA %d ESS_AudioDrive_not_found = Не найдена ESS AudioDrive Failed_to_set_VBE/AF_mode = Невозможно установить режим VBE/AF Flightstick_Pro = Flightstick Pro Graphics_Mode = Графический режим Hardware_acceleration_not_available = Аппаратное ускорение недоступно Hardware_scrolling_not_supported = Аппаратная прокрутка недоступна Hat = Joystick de direction Insufficient_%s_voices_available = Недостаточн %s голосов Insufficient_video_memory = Недостаточно видеопамяти Linear_framebuffer_not_available = Линейный буфер кадра недоступен MIDI = MIDI Mode-X_only_supports_8_bit_color = Режимы Mode-X поддерживает только 256 цветов Move_stick_2_to_the_bottom_right = Отведите джойстик 2 в нижнее-правое положение Move_stick_2_to_the_top_left = Отведите джойстик 2 к верхнее-левое положение Move_stick_to_the_bottom_right = Отведите джойстик в нижнее-правое положение Move_stick_to_the_top_left = Отведите джойстик в левое-верхнее положение Move_the_hat_down = Переместите вершину джойстики вниз Move_the_hat_left = Переместите вершину джойстика влево Move_the_hat_right = Переместите вершину джойстика вправо Move_the_hat_up = Переместите вершину джойстика вверх MPU-401_and_%s_conflict_over_IRQ_%d = Конфликт между MPU-401 и %s из-за прерывания %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = Интерфейс MIDI MPU-401 на порте %X, прерывание %d MPU-401_not_found = MPU-401 не обнаружена Not_a_valid_VGA_resolution = Не VGA-разрешение Not_a_VGA_mode-X_resolution = Не Mode-X разрешение Obsolete_VBE/AF_version_(need_2.0_or_greater) = Устаревший драйвер VBE/AF ( требуется версия 2.0 или новее) OK = Дальше Older_SB_version_detected = Обнаружена старая версия SB OPL_synth_not_found = синтезатор OPL не найден OPL2_synth = синтезатор OPL2 OPL3_synth = синтезатор OPL3 OPL3_synth_not_found = синтезатор OPL3 не найден Resolution_not_supported = Разрешение не поддерживается SB_AWE32/compatible_on_port_0x%04x = SB AWE32-совместимый на порту 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = Драйвер SB должен быть установлен до чтения SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = Драйверы VBE/AF фирмы SciTech не поддерживают широкие виртуальные экраны Second_OPL2_synth_not_found = Второй синтезатор OPL2 не найден Set_throttle_to_maximum = Установите газ на максимум Set_throttle_to_minimum = Установите газ на минимум Software_wavetable_synth = Программный волновой синтезатор Sound_Blaster_MIDI_interface_on_port_%X = MIDI-интерфейс Sound Blaster на порту %X Sound_Blaster_not_found = Sound Blaster не найден Sound_system_not_installed = Звуковая система не установлена Standard_joystick = Стандартный джойстик Stick = Джойстик The_sound_of_silence = Звук тишины Throttle = Газ unused = не занято VBE_%d.0_not_available = VBE %d.0 не доступен VBE_mode_not_available = Режим VBE не доступен VBE/AF_device_not_present = Устройство VBE/AF не найдено VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF не поддерживается на этой платформе VBE/AF_Plug_and_Play_initialisation_failed = PnP-инициализация VBE/AF провалилась VESA_function_0x4F02_failed = Функция VESA 0x4F02 провалилась VESA_function_0x4F06_failed = Функция VESA 0x4F06 провалилась VESA_mode_0x100_not_available = Режим VESA 0x100 не доступен VESA_not_available = Нет доступа к VESA VESA_protected_mode_interface_not_available = Интерфейс VESA защищенного режима недоступен VGA_only_supports_8_bit_color = VGA поддерживает только 256 цветов Virtual_screen_size_too_large = Слишком большой виртуальный экран Wingman_Extreme = Wingman Extreme Xtended_mode_only_supports_640x400 = Режим Xtended поддерживает только разрешение 640x400 Xtended_mode_only_supports_8_bit_color = Режим Xtended поддерживает только 256 цветов allegro-4.4.3.1/resource/language/entext.cfg0000664000175000017500000000004413437077643017700 0ustar siegesiegelanguage_name = English [language] allegro-4.4.3.1/resource/language/pltext.cfg0000664000175000017500000004060013437077643017713 0ustar siegesiegelanguage_name = Polish [language] 15_bpp_(32K_color) = 15 bpp (32K kolorów) 16_bpp_(64K_color) = 16 bpp (64K kolorów) 24_bpp_(16M_color) = 24 bpp (16M kolorów) 32_bpp_(16M_color) = 32 bpp (16M kolorów) 4-button joystick = 4-przyciskowy joystick 4-buttonjoystick = Joystick 4-przyciskowy 6-button joystick = 6-przyciskowy joystick 6-buttonjoystick = Joystick 6-przyciskowy _8_bpp_(256_color) = 8 bpp (256 kolorów) 8-button joystick = 8-przyciskowy joystick 8-buttonjoystick = Joystick 8-przyciskowy A = A Adlib_(dual_OPL2) = Adlib (podwójny OPL2) Adlib_(OPL2) = Adlib (OPL2) Adlib_(OPL3) = Adlib (OPL3) Agnostic = Agnostyk Aim = Wyceluj Aim_X = Wyceluj X Aim_y = Wyceluj Y ALSA = ALSA Analogue_Buttons = Przyciski analogowe Apple_SoundManager_%d.x_%d_hz,_%d-bit,_%s = Apple SoundManager %d.x %d hz, %d-bit, %s approx. = rednio Autodetect = Autodetekcja Auto_fullscreen = Autodetekcja - peny ekran Auto_windowed = Autodetekcja - okno AWE32_detection_failed_on_port_0x%04x = Nie wykryto AWE32 na porcie 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = Sterownik AWE32: problem z zaadowanie danych AWE32/EMU8000 = AWE32/EMU8000 AWE32_not_detected = Nie wykryto AWE32 B1 = B1 B2 = B2 B3 = B3 B4 = B4 B5 = B5 B6 = B6 B7 = B7 B8 = B8 Back = Powrót Bad_VBE/AF_driver_ID_string = Zy identyfikator VBE/AF Banked_framebuffer_not_available = Nie dostpny bufor ramki z przeczeniem bankow B = B BeOS_Keyboard = Klawiatura BeOS BLASTER_environment_variable_has_no_E_section = Zmienna rodowiskowa BLASTER nie ma sekcji E BLASTER_environment_variable_not_set = Zmienna rodowiskowa BLASTER nie zostaa ustawiona Blue = Niebieski Button_1 = Przycisk 1 Button_2 = Przycisk 2 Button_3 = Przycisk 3 Button_4 = Przycisk 4 Button_5 = Przycisk 5 Cancel = Anuluj Cannot_access_the_framebuffer = Brak dostpu do bufora ramki Can_not_allocate_audio_buffer = Nie można zaalokowa bufora audio Cannot_create_direct_context = Nie można utworzy bezporedniego kontekstu Cannot_create_offscreen_context = Nie można utworzy pozaekranowego kontekstu Can_not_create_XImage = Nie można stworzy XImage Can_not_do_double_buffered_sound = Nie można odtwarza podwójnie buforowanego dźwiku Cannot_enable_linear_addressing = Nie można wczy adresowania liniowego Can_not_get_channel_setup = Nie można odczyta konfiguracji kanau Can_not_get_information_about_sound = Nie można odczyta informacji o dźwiku Can_not_get_video_mode_settings = Nie można zainicjowa trybu graficznego Can_not_grab_keyboard = Nie można przechwyci klawiatury Can_not_grab_mouse = Nie można przechwyci myszy Cannot_initialise_GGI! = Nie można zainicjowa GGI! Can_not_init_software_mixer = Bd inicjowania miksera programowego Can_not_install_colormap = Bd instalowania palety kolorów Can_not_obtain_user_name = Nie można uzyska imienia użytkownika Cannot_open_card/pcm_device = Nie można otworzy karty/urzdzenia pcm Can_not_open_card/pcm_device = Nie można otworzy karty/urzdzenia PCM Cannot_open_card/pcm_device = Nie można otworzy karty/urzdzenia PCM Cannot_open_default_visual! = Nie można otworzy domylnego trybu graficznego! Can_not_open_framebuffer = Nie można otworzy bufora ramki Cannot_open_palemu/trueemu_visual! = Nie można otworzy wywietlania palemu/trueemu Can_not_query_DirectVideo = Nie można wykry DirectVideo Can_not_set_channel_parameters = Nie można ustawi parametrów kanau Cannot_set_playback_format = Nie można ustawi formatu odtwarzania Can_not_set_video_mode = Nie można ustawi trybu video Cannot_start_direct_context = Nie można wystartowa bezporedniego kontekstu Can_not_switch_to_DGA_mode = Nie można przeczy do trybu DGA Can't_find_VBEAF.DRV = Nie można znaleź VBEAF.DRV Can't_make_linear_screen_bitmap = Nie można utworzy liniowej bitmapy ekranu Can't_map_framebuffer = Nie można zamapowa bufora ramki Can't_map_framebuffer_%s = Nie można zamapowa bufora ramki %s Can't_map_memory_for_VBE/AF = Nie można zamapowa pamici na VBE/AF Can't_open_framebuffer_%s = Nie można otworzy bufora ramki %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Nie można używa SB MIDI i DSP jednoczenie Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Karta #%d, urzdzenie #%d: %d bitów, %s, %d bps, %s C = C C_Down = C Dó Centre_the_hat = Wycentruj przecznik widoków Circle = Okrg C_Left = C Lewo Could_not_find_GRIP.GLL = Brak GRIP.GLL Could_not_initialize_GrIP_system = Bd inicjowania systemu GrIP Couldn't_allocate_screen_bitmap! = Nie można zaalokowa bitmapy ekranu C_Right = C Prawo Cross = Krzyżyk C_Up = C Góra Device_connected_is_not_a_Wingman_Warrior = Podczone urzdzenie to nie Wingman Warrior DGA_1.0_is_required = Wymagane DGA 1.0 DGA_2.0_or_newer_is_required = Wymagane DGA 2.0 lub nowsze DGA_extension_is_not_supported = Rozszerzenie DGA nie jest wspierane DGA_graphics = Grafika DGA Dial = Tarcza Digital_input_driver_not_found = Nie znaleziono sterownika wejcia Digital_sound_driver_not_found = Nie znaleziono sterownika dźwiku DIGMID = DIGMID DIGMID_patch_set_not_found = Nie znaleziono danych dla DIGMID DirectDraw_accel = Akcelerowane DirectDraw DirectDraw = DirectDraw DirectDraw_overlay = Nakadka DirectDraw DirectDraw_safe = Bezpieczny tryb DirectDraw DirectDraw_window = Okienkowy tryb DirectDraw DirectInput = DirectInput Direction_Pad = Pad kierunku Direction_Pad_X = Pad kierunku X Direction_Pad_Y = Pad kierunku Y DirectVideo_is_not_supported = DirectVideo nie jest wspierane DirectX = DirectX DrawSprocket_%d_x_%d,_%dbpp,_%dhz = DrawSprocket %d x %d, %dbpp, %dhz Dual_joysticks = Podwójne joystick'i Dual_OPL2_synths = Podwójny syntezator OPL2 Error_finding_our_VT:_%s = Nie znaleziono naszego VT: %s Error_reading_.IBK_file_'%s' = Bd czytania pliku .IBK: '%s' Error_setting_VGA_video_mode = Bd ustawienia trybu VGA ESS_AudioDrive = ESS AudioDrive ESS_AudioDrive_not_found = Nie znaleziono ESS AudioDrive ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) na porcie %X, IRQ %d, DMA %d Failed_to_init_digital_input_driver = Nie można zainicjalizowa sterownika cyfrowego wejcia Failed_to_init_digital_sound_driver = Nie można zainicjalizowa sterownika cyfrowego dźwiku Failed_to_init_MIDI_input_driver = Nie można zainicjalizowa sterownika wejcia MIDI Failed_to_init_MIDI_music_driver = Nie można zainicjalizowa sterownika muzyki MIDI Failed_to_set_VBE/AF_mode = Nie można ustawi trybu VBE/AF Fatal_error:_unable_to_activate_the_Allegro_system = Fatalny bd: nie można aktywowa systemu Allegro Fatal_error:_unable_to_set_GFX_SAFE = Fatalny bd: nie można ustawi GFX_SAFE fbcon = fbcon Fixed-rate_timer = Timer o staej czstotliwoci Flightstick_Pro = Flightstick Pro Framebuffer_ioctl()_failed = Awaria bufora ramki ioctl() Framebuffer_resolution_not_available = Rozdzielczo bufora ramki niedostpna Fullscreen_DGA = Tryb penoekranowy DGA Fullscreen = Tryb penoekranowy Getting_buffer_size:_%s = Ustalanie wielkoci bufora: %s Graphics_Mode = Tryb graficzny Green = Zielony Hardware_acceleration_not_available = Brak sprztowej akceleracji Hardware_scrolling_not_supported = Sprztowego przewijanie nie jest wspierane Hat = Przecznik widoków I_Button = I Przycisk IF-SEGA2/PCI:__create_linear_mapping_error = IF-SEGA2/PCI: bd przy tworzeniu liniowego mapowania IF-SEGA2/PCI:__create_selector_error = IF-SEGA2/PCI: bd przy tworzeniu selektora IF-SEGA2/PCI:_device_not_found = IF-SEGA2/PCI: nie znaleziono urzdzenia IF-SEGA2/PCI:_read_configuration_dword_error = IF-SEGA2/PCI: bd czytania konfiguracji II_Button = II Przycisk Input_is_not_supported = Wejcie nie jest wspierane Insufficient_%s_voices_available = Mniej niż %s gosów Insufficient_video_memory = Za mao pamici video int_0x33_mouse = Mysz int 0x33 Internal_error = Bd wewntrzny L1_Button = Przycisk L1 L1 = L1 L2 = L2 L3 = L3 Left = Lewy Left_Stick = Lewy drżek Left_Stick_X = Lewy drżek X Left_Stick_Y = Lewy drżek Y Linear_framebuffer_not_available = Brak liniowego bufora ramki Linux_analogue_joystick(s) = Linux'owe joystick'i analogowe Linux_console_keyboard = Linux'owa klawiatura na konsoli Linux_console = Linux'owa konsola Linux_MS_Intellimouse = Linux'owa mysz MS Intellimouse Linux_MS_mouse = Linux'owa mysz MS Linux_PS/2_Intellimouse = Linux'owa mysz PS/2 Intellimouse Linux_PS/2_mouse = Linux'owa mysz PS/2 L = L Mickey_Mouse = Myszka Mickey MIDI_input_driver_not_found = Brak sterownika wejcia MIDI MIDI = MIDI MIDI_music_driver_not_found = Brak sterownika muzyki MIDI M = M Mode-X_only_supports_8_bit_color = Tryb-X wspiera tylko 8-bitowy kolor Mode-X = Tryb-X Mouse = Mysz Move_stick_2_to_the_bottom_right = Pochyl drżek 2 do dou, w prawo Move_stick_2_to_the_top_left = Pochyl drżek 2 do góry, w lewo Move_stick_to_the_bottom_right = Pochyl drżek do dou, w prawo Move_stick_to_the_top_left = Pochyl drżek do góry, w lewo Move_the_hat_down = Pochyl przecznik widoków do dou Move_the_hat_left = Pochyl przecznik widoków w lewo Move_the_hat_right = Pochyl przecznik widoków w prawo Move_the_hat_up = Pochyl przecznik widoków do góry MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 ma konflikt z %s na IRQ %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI na porcie %X, IRQ %d MPU-401 = MPU-401 MPU-401_not_found = Brak MPU-401 N64pad-LPT1 = N64pad na LPT1 N64pad-LPT2 = N64pad na LPT2 N64pad-LPT3 = N64pad na LPT3 No_GrIP_devices_available = Nie znaleziono żadnego urzdzenia GrIP No_joystick = Bez joystick'a No_joysticks_found = Brak joystick'a No_mouse = Bez myszy No = Nie No_server = Brak serwera No_sound = Bez dźwiku No_support_synth_type_found = Brak wsparcia dla typu syntezatora Not_a_valid_VGA_resolution = Nieprawidowa rozdzielczo VGA Not_a_VGA_mode-X_resolution = Nieprawidowa rozdzielczo VGA trybu X Not_enough_memory = Za mao pamici Not_in_stereo_or_mono_mode = Nie jest w trybie mono lub stereo no_vsync = bez synchronizacji pionowej No_window = Brak okna Obsolete_VBE/AF_version_(need_2.0_or_greater) = Nieaktualna wersja VBE/AF (wymagana 2.0 lub wyższa) OK = OK Older_SB_version_detected = Znaleziono starsz wersj SB Open_Sound_System = Open Sound System OPL2_synth = Syntezator OPL2 OPL3_synth_not_found = Brak syntezatora OPL3 OPL3_synth = Syntezator OPL3 OPL_synth_not_found = Brak syntezatora OPL OSS_output_driver_must_be_installed_before_input_can_be_read = Sterownik wyjcia OSS musi by zainstalowany przed czytaniem z wejcia Overlays_not_supported = Brak wsparcia dla nakadek Pad = Pad PCI_BIOS_not_installed = BIOS PCI nie jest zainstalowany PC_keyboard_(DOS) = Klawiatura PC (DOS) Polling_mouse = Mysz w trybie pobierania Position = Pozycja Position_x = Pozycja X Position_X = Pozycja X Position_y = Pozycja y PSXpad-LPT1 = PSXpad na LPT1 PSXpad-LPT2 = PSXpad na LPT2 PSXpad-LPT3 = PSXpad na LPT3 R1 = R1 R2 = R2 R3 = R3 Red = Czerowny Requested_mode_not_available! = Wymagany tryb jest niedostpny! Required_VGA_mode_not_supported = Wymagany tryb VGA nie jest wspierany Resolution_not_supported = Rozdzielczo nie jest wspierana Right = Prawy Right_Stick = Prawy drżek Right_Stick_X = Prawy drżek X Right_Stick_Y = Prawy drżek Y R = R Safe_Fullscreen = Bezpieczny tryb penoekranowy SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibilna na porcie 0x%04x SB_MIDI_interface = Interfejs SB MIDI SB_output_driver_must_be_installed_before_input_can_be_read = Sterownik wyjcia SB musi by zainstalowany przed czytaniem w wejcia %s:_can_not_open = Nie można otworzy: %s SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF nie wspiera szerokich ekranów wirtualnych %s:_%d_bits,_%s,_%d_bps,_%s = %s: %d bitów, %s, %d bps, %s %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) na porcie %X, IRQ %d kana DMA %d %s_does_not_support_audio_input = %s nie wspiera wejcia audio %s_does_not_support_MIDI_input = %s nie wspiera wejcia MIDI Second_OPL2_synth_not_found = Drugi syntezator OPL2 nie znaleziony Select = Wybierz Set_throttle_to_maximum = Nastaw przepustnice na maksimum Set_throttle_to_minimum = Nastaw przepustnice na minimum Setting_DSP_parameters:_%s = DSP parametr: %s Setting_fragment_size:_%s = Wielko fragmentu: %s Sidewinder = Sidewinder %s_must_only_be_writeable_by_root = %s musi by zapisane przez root'a SNESpad-LPT1 = SNESpad na LPT1 SNESpad-LPT2 = SNESpad na LPT2 SNESpad-LPT3 = SNESpad na LPT3 %s_not_found = nie znaleziono %s Software_wavetable_synth = Programowa synteza wavetable %s_on_port_%X = %s na porcie %X Sound_Blaster_1.0 = Sound Blaster 1.0 Sound_Blaster_1.5 = Sound Blaster 1.5 Sound_Blaster_16 = Sound Blaster 16 Sound_Blaster_2.0 = Sound Blaster 2.0 Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI na portu %X Sound_Blaster_not_found = Nie wykryto Sound Blastera Sound_Blaster_Pro = Sound Blaster Pro SoundManager_3.0_or_later_required = Wymagany SoundManager 3.0 lub nowszy SoundManager_not_found = SoundManager nie znaleziony Soundscape_not_found = Nie wykryto Soundscape Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) na porcie %X, IRQ %d, DMA %d, waveport %X Soundscape = Soundscape Sound_system_not_installed = Nie zainstalowano systemu dźwiku Spinner = Spinner Square = Kwadrat %s:_%s = %s: %s Standard_joystick = Standardowy joystick Standard_VGA = Standardowa VGA Start = Start Stick_%d = Drżek %d Stick = Drżek Stick_X = Drżek X Stick_Y = Drżek Y SWIFT_Device_not_detected = Nie wykryto urzdzenia SWIFT The_sound_of_silence = Odgos ciszy This_driver_needs_local_display = Ten sterownik wymaga lokalnego wywietlania This_driver_needs_root_privileges = Ten sterownik wymaga uprawnie root'a Throttle = Przepustnica Triangle = Trójkt Trigger = Spust Twist = Przekr Unable_to_control_VT_switching = Nie można kontrolowa przeczania VT Unable_to_find_a_suitable_graphics_driver = Nie można znaleź waciwego sterownika grafiki Unable_to_find_a_usable_VT = Nie można znaleź użytecznego VT Unable_to_map_video_memory = Nie można zmapowa pamici video Unable_to_open = Nie można otworzy Unable_to_open_%s:_%s = Nie można otworzy %s: %s Unable_to_reopen_new_console = Nie można ponownie otworzy nowej konsoli Unix_SIGALRM_timer = Unixowy timer SIGALRM Unsupported_color_depth = Ta gbia koloru nie jest wspierana Unsupported_memory_layout = Ten ukad pamici nie jest wspierany Unsupported_sample_format = Ten format sampla nie jest wspierany Unsupported_screen_size = Ten rozmiar ekranu nie jest wspierany Unsupported_virtual_resolution = Wirtualna rozdzielczo nie jest wspierana unused = nieużywane Variable-rate_timer = Timer o zmiennej czstotliwoci VBE/AF_device_not_present = Nie ma urzdzenia VBE/AF VBE/AF_nearptrs_not_supported_on_this_platform = Ta platforma nie wpiera VBE/AF nearptrs VBE/AF_Plug_and_Play_initialisation_failed = Nie można zainicjowa VBE/AF Plug and Play VBE/AF = VBE/AF VBE_%d.0_not_available = Brak VBE %d.0 VESA_1.x = VESA 1.x VESA_2.0_(banked) = VESA_2.0 (z przeczaniem banków) VESA_2.0_(linear) = VESA_2.0 (liniowa) VESA_3.0 = VESA 3.0 VESA_function_0x4F02_failed = Bd funkcji VESA 0x4F02 VESA_function_0x4F06_failed = Bd funkcji VESA 0x4F06 VESA_mode_0x100_not_available = Tryb VESA 0x100 nie jest dostpny VESA_not_available = Brak VESA VESA_protected_mode_interface_not_available = Interfejs VESA trybu chronionego nie jest dostpny VGA_only_supports_8_bit_color = VGA wspiera tylko 8-bitowy kolor VidMode_extension_is_not_supported = Rozszerzenie VidMode nie jest wspierane Virtual_screen_size_too_large = Rozmiar ekranu wirtualnego jest za duży VT_WAITACTIVE_failure = Awaria VT_WAITACTIVE Warning:_forcing_program_shutdown_may_lead_to_data_loss_and_unexpected_results._It_is_preferable_to_use_the_exit_command_inside_the_window._Proceed_anyway? = Uwaga: zmuszenie programu do zamknicia może prowadzi do utraty danych i niespodziewanych rezultatów. Zalecane jest użycie opcji wyjcia wewntrz programu. Kontynuowa mimo wszystko? Win32_joystick = Joystick Win32 Win32_Multithreaded_Timer = Wielowtkowy timer Win32 Win32_Singlethreaded_Timer = Jednowtkowy timer Win32 Windowed_mode_not_supported = Okienkowy tryb nie jest wspierany Windows_Sound_System = Windows Sound System Wingman_Extreme = Wingman Extreme Wingman_Warrior_not_connected = Wingman Warrior nie podczony Wingman_Warrior = Wingman Warrior Xtended_mode_only_supports_640x400 = Tryb Xtended wpiera tylko 640x400 Xtended_mode_only_supports_8_bit_color = Tryb Xtended wpiera tylko 8-bitowy kolor Xtended_mode = Tryb Xtended X-Windows_graphics = Grafika X-Windows X-Windows_keyboard = Klawiatura X-Windows X-Windows_mouse = Mysz X-Windows X-Windows = X-Windows X = X Yellow = Żóty Yes = Tak Y = Y Z = Z allegro-4.4.3.1/resource/language/dktext.cfg0000664000175000017500000001244213437077643017701 0ustar siegesiegelanguage_name = Danish [language] AWE32_detection_failed_on_port_0x%04x = AWE32 påvisning mislykkedes på port 0x%04x BLASTER_environment_variable_has_no_E_section = BLASTER miljøvariablen har ingen E sektion Error_setting_video_mode = Fejl under opsætning af skærmtilstanden Graphics_Mode = Skærmtilstand Insufficient_video_memory = Utilstrækkelig videohukommelse Hardware_acceleration_not_available = Hardwareacceleration ikke til rådighed Mode-X_only_supports_8_bit_color = Mode-X understøtter kun 8-bit farver Not_a_valid_VGA_resolution = Ikke en gyldig VGA-opløsning Not_a_VGA_mode-X_resolution = Ikke en VGA mode-X opløsning Obsolete_VBE/AF_version_(need_2.0_or_greater) = Forældet version af VBE/AF (behøver 2.0 eller nyere) Older_SB_version_detected = Ældre version af SB fundet Resolution_not_supported = Opløsning ikke understøttet Set_throttle_to_maximum = Sæt choker til maksimum Set_throttle_to_minimum = Sæt choker til minimum Standard_joystick = Standardjoystick VBE/AF_Plug_and_Play_initialisation_failed = Initialisering af VBE/AF Plug and Play mislykkedes VESA_function_0x4F02_failed = VESA-funktion 0x4F02 mislykkedes VESA_function_0x4F06_failed = VESA-funktion 0x4F06 mislykkedes VGA_only_supports_8_bit_color = VGA understøtter kun 8-bit farver Virtual_screen_size_too_large = Virtuel skærmstørrelse for stor Xtended_mode_only_supports_640x400 = Xtended mode understøtter kun 640x400 Xtended_mode_only_supports_8_bit_color = Xtended mode understøtter kun 8-bit farver %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) på port %X, benyttende IRQ %d og DMA kanal %d %s_does_not_support_audio_input = %s understøtter ikke lyd-input %s_does_not_support_MIDI_input = %s understøtter ikke MIDI-input %s_not_found = %s ikke fundet %s_on_port_%X = %s på port %X 4-button_joystick = 4-knappers joystick 6-button_joystick = 6-knappers joystick 8-button_joystick = 8-knappers joystick AWE32_driver:_had_trouble_with_the_embedded_data = AWE32 driver: havde problemer med den integrerede data AWE32_not_detected = AWE32 ikke fundet Bad_VBE/AF_driver_ID_string = Ødelagt VBE/AF-driver identifikationsstreng Banked_framebuffer_not_available = Bankopdelt framebuffer ikke til rådighed BLASTER_environment_variable_not_set = BLASTER miljøvariablen ikke sat Can't_find_VBEAF.DRV = Kan ikke finde VBEAF.DRV Can't_make_linear_screen_bitmap = Kan ikke oprette lineært skærm-bitmap Can't_map_memory_for_VBE/AF = Kan ikke kortlægge hukommelse til VBE/AF Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Kan ikke bruge SB MIDI grænsefladen og DSP på samme tid Cancel = Annullér Centre_the_hat = Centrér hatten DIGMID_patch_set_not_found = DIGMID-patch ikke fundet Disk_Error = Diskfejl Dual_joysticks = Dobbeltjoysticks Dual_OPL2_synths = Dobbelte OPL2 synthesizere Error_reading_.IBK_file_'%s' = Fejl under læsning af .IBK filen '%s' ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) på port %X, benyttende IRQ %d og DMA kanal %d ESS_AudioDrive_not_found = ESS AudioDrive ikke fundet Failed_to_set_VBE/AF_mode = Mislykkedes at sætte VBE/AF-tilstand Hardware_scrolling_not_supported = Hardwarerulning ikke understøttet Hat = Hat Insufficient_%s_voices_available = Utilstrækkelige %s stemmer til rdighed Linear_framebuffer_not_available = Lineær framebuffer ikke til rådighed Move_stick_2_to_the_bottom_right = Flyt stick 2 til nederste, højre hjørne Move_stick_2_to_the_top_left = Flyt stick 2 til øverste, venstre hjørne Move_stick_to_the_bottom_right = Flyt sticket til nederste, højre hjørne Move_stick_to_the_top_left = Flyt sticket til øverste, venstre hjørne Move_the_hat_down = Flyt hatten ned Move_the_hat_left = Flyt hatten til venstre Move_the_hat_right = Flyt hatten til højre Move_the_hat_up = Flyt hatten op MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 og %s er i konflikt ved IRQ %d MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI grænseflade på port %X, benyttende IRQ %d MPU-401_not_found = MPU-401 ikke fundet OPL_synth_not_found = OPL synthesizer ikke fundet OPL2_synth = OPL2 synthesizer OPL3_synth = OPL3 synthesizer OPL3_synth_not_found = OPL3 synthesizer ikke fundet SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibel på port 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = SB output-driver skal være installeret før input kan læses SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF-drivere undersøttter ikke brede virtuelle skærme Second_OPL2_synth_not_found = Anden OPL2 synthesizer ikke fundet Software_wavetable_synth = Software wavetable synthesizer Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI grænseflade på port %X Sound_Blaster_not_found = Sound Blaster ikke fundet Sound_system_not_installed = Lydsystem ikke installeret The_sound_of_silence = Lyden af stilhed Throttle = Choker unused = ubenyttet VBE_%d.0_not_available = VBE %d.0 ikke til rådighed VBE_mode_not_available = VBE-tilstand ikke til rådighed VBE/AF_device_not_present = VBE/AF-enhed ikke til stede VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF nearptrs ikke understøttet på denne platform VESA_mode_0x100_not_available = VESA-tilstand 0x100 ikke til rådighed VESA_not_available = VESA ikke til rådighed VESA_protected_mode_interface_not_available = VESA beskyttet-tilstands grænseflade ikke til rådighed allegro-4.4.3.1/resource/language/setext.cfg0000664000175000017500000003236013437077643017713 0ustar siegesiegelanguage_name = Svenska [language] %s:_%d_bits,_%s,_%d_bps,_%s = %s: %d bitar, %s %d bps, %s %s:_can_not_open = %s: kunde inte öppna %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) på port %X använder IRQ %d och DMA-kanal %d %s_does_not_support_MIDI_input = %s stöder inte MIDI-inspelning %s_does_not_support_audio_input = %s stöder inte ljudinspelning %s_must_only_be_writeable_by_root = %s får bara vara skrivbar med rotpriviliegier %s_not_found = Kunde inte hitta %s %s_on_port_%X = %s på port %X 4-button_joystick = 4-knappars joystick 6-button_joystick = 6-knappars joystick 8-button_joystick = 8-knappars joystick AWE32_detection_failed_on_port_0x%04x = Kunde inte hitta AWE32 på port 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = AWE32-drivrutin: problem med inbäddad data AWE32_not_detected = Kunde inte hitta AWE32 Analogue_Buttons = Analoga knappar Apple_SoundManager_%d.x_%d_hz,_%d-bit,_%s_,_%d_ = Apple SoundManager %d.x %d hz, %d-bitars, %s , %d Auto_fullscreen = Auto fullskärm Auto_windowed = Auto fönsterläge Autodetect = Känn av automatiskt BLASTER_environment_variable_has_no_E_section = Miljövariabeln BLASTER har ingen E-parameter BLASTER_environment_variable_not_set = Miljövariabeln BLASTER är inte satt Back = Tillbaka Bad_VBE/AF_driver_ID_string = Felaktig ID-text för VBE/AF-drivrutinen Banked_framebuffer_not_available = Delad skärmbuffer ej tillgänglig BeOS_joystick = BeOS-joystick BeOS_Keyboard = BeOS-tangentbord BeOS_MIDI = BeOS-MIDI BeOS_Sound = BeOS-ljud Blue = Blå Button_1 = Knapp 1 Button_2 = Knapp 2 Button_3 = Knapp 3 Button_4 = Knapp 4 Button_5 = Knapp 5 C_Down = C ner C_Left = C vänster C_Right = C höger C_Up = C upp Can't_find_VBEAF.DRV = Kunde inte hitta VBEAF.DRV Can't_make_linear_screen_bitmap = Kunde inte skapa linjär skärmbitmapp Can't_map_framebuffer = Kunde inte mappa skärmbuffer Can't_map_memory_for_VBE/AF = Kunde inte mappa minne för VBE/AF Can't_open_framebuffer_%s = Kunde inte öppna skärmbuffer %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Kunde inte använda SB MIDI-gränssnitt och DSP samtidigt Can_not_allocate_audio_buffer = Kunde inte allokera ljudbuffer Can_not_create_XImage = Kunde inte skapa XImage Can_not_do_double_buffered_sound = Dubbelbuffrat ljud stöds inte Can_not_get_information_about_sound = Kunde inte hitta information om ljud Can_not_get_video_mode_settings = Kunde inte ladda grafikkortsinställningar Can_not_grab_keyboard = Kunde inte hitta något tangentbord Can_not_grab_mouse = Kunde inte hitta någon mus Can_not_init_software_mixer = Kunde inte initiera mjukvarumixer Can_not_install_colormap = Kunde inte installera färgtabell Can_not_obtain_user_name = Kunde inte komma åt användarnamnet Can_not_open_card/pcm_device = Kunde inte öppna kort-/pcm-enhet Can_not_open_framebuffer = Kunde inte öppna skärmbuffer Can_not_query_DirectVideo = Kunde inte kommunicera med DirectVideo Can_not_set_channel_parameters = Kunde inte sätta kanal-parametrar Can_not_set_video_mode = Kunde inte sätta grafikläge Can_not_switch_to_DGA_mode = Kunde inte byta till DGA-läge Cancel = Avbryt Cannot_access_the_framebuffer = Kunde inte komma åt skärmbuffer Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Kort %d, enhet %d: %d bitar, %s, %d bps, %s Centre_the_hat = Centrera övre styrspaken Circle = Cirkel Could_not_find_GRIP.GLL = Kunde inte hitta GRIP.GLL Could_not_initialize_GrIP_system = Kunde inte initiera GrIP-systemet DGA_1.0_is_required = DGA 1.0 krävs DGA_1.0_window = DGA 1.0 fönster DGA_2.0_or_newer_is_required = DGA 2.0 eller nyare krävs DGA_2.0_soft = DGA 2.0 mjukvara DGA_extension_is_not_supported = DGA-utökning stöds inte DIGMID_patch_set_not_found = Kunde inte hitta någon DIGMID patch-uppsättning Device_connected_is_not_a_Wingman_Warrior = Den anslutna enheten är inte en Wingman Warrior Digital_input_driver_not_found = Kunde inte hitta någon drivrutin för digital ljudinmatning Digital_sound_driver_not_found = Kunde inte hitta någon drivrutin för digitalt ljud DirectDraw_accel = DirectDraw accellererad DirectDraw_safe = DirectDraw säker DirectDraw_soft = DirectDraw mjukvara DirectDraw_window = DirectDraw fönsterläge DirectInput_keyboard = DirectInput tangentbord DirectInput_mouse = DirectInput mus DirectVideo_is_not_supported = DirectVideo stöds inte Dual_OPL2_synths = Två OPL2-syntar Dual_joysticks = Två joystickar ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) på port %X, använder IRQ %d och DMA-kanal %d ESS_AudioDrive_not_found = Kunde inte hitta ESS AudioDrive Error_reading_.IBK_file_'%s' = Fel vid läsning av .IBK-filen '%s' Error_setting_VGA_video_mode = Fel uppstod när VGA-grafikläget skulle sättas Failed_to_init_MIDI_input_driver = Misslyckades med att initiera drivrutinen för MIDI-inmatning Failed_to_init_MIDI_music_driver = Misslyckades med att initiera drivrutinen för MIDI-musik Failed_to_init_digital_input_driver = Misslyckades med att initiera drivrutinen för digital ljudinmatning Failed_to_init_digital_sound_driver = Misslyckades med att initiera drivrutinen för digitalt ljud Failed_to_set_VBE/AF_mode = Kunde inte sätta VBE/AF-läge Fatal_error:_unable_to_set_GFX_SAFE = Fatalt fel: Kunde inte sätta GFX_SAFE Fixed-rate_timer = Timer med konstant hastighet Framebuffer_ioctl()_failed = Skärmbuffer ioctl() misslyckades Framebuffer_resolution_not_available = Skärmbuffer-upplösning inte tillgänglig Getting_buffer_size:_%s = Hämtar bufferstorlek: %s Graphics_Mode = Grafikläge Green = Grön Hardware_acceleration_not_available = Hårdvaruacceleration är inte tillgänglig Hardware_scrolling_not_supported = Hårdvaruskrollning stöds inte Hat = Övre styrspak IF-SEGA2/PCI:__create_linear_mapping_error = IF-SEGA2/PCI: _create_linear_mapping-fel IF-SEGA2/PCI:__create_selector_error = IF-SEGA2/PCI: _create_selector-fel IF-SEGA2/PCI:_device_not_found = IF-SEGA2/PCI: enheten kunde inte hittas Input_is_not_supported = Ljudinmatning stöds inte Insufficient_%s_voices_available = För få %s-kanaler tillgängliga Insufficient_video_memory = För lite grafikminne Int_0x33_mouse = Int 0x33-mus Internal_error = Internt fel Invalid_virtual_resolution_requested = Ogiltig virtuell upplösning efterfrågades L1_Button = L1-knapp Left = Vänster Linear_framebuffer_not_available = Linjär skärmbuffer ej tillgänglig Linux_analogue_joystick(s) = Linux analog(a) joystick(ar) Linux_console = Linuxkonsoll Linux_console_keyboard = Linuxkonsoll-tangentbord MIDI_input_driver_not_found = Kunde inte hitta någon drivrutin för MIDI-inmatning MIDI_music_driver_not_found = Kunde inte hitta någon drivrutin för MIDI-musik MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI-gränssnitt på port %X, använder IRQ %d MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 och %s krockar på IRQ %d MPU-401_not_found = Kunde inte hitta MPU-401 MacOs = Mac OS MacOs_Key = Mac OS-tangentbord MacOs_Mouse = Mac OS-mus MacOs_Timer = Mac OS-timer MacOs_X_keyboard = Mac OS X-tangentbord MacOs_X_mouse = Mac OS X-mus MacOs_X = Mac OS X Mode-X_only_supports_8_bit_color = Mode-X stöder bara 8-bitars färg Mouse = Mus Move_stick_2_to_the_bottom_right = Dra joystick 2 neråt åt höger Move_stick_2_to_the_top_left = Dra joystick 2 uppåt åt vänster Move_stick_to_the_bottom_right = Dra joystickspaken neråt åt höger Move_stick_to_the_top_left = Dra joystickspaken uppåt åt vänster Move_the_hat_down = Dra övre styrspaken neråt Move_the_hat_left = Dra övre styrspaken åt vänster Move_the_hat_right = Dra övre styrspaken åt höger Move_the_hat_up = Dra övre styrspaken uppåt No = Nej No_GrIP_devices_available = Inga GrIP-enheter tillgängliga No_joystick = Ingen joystick No_joysticks_found = Kunde inte hitta några joystickar No_mouse = Ingen mus No_server = Ingen server No_sound = Inget ljud No_supported_synth_type_found = Ingen av de synt-typer som stöds kunde hittas No_window = Inget fönster Not_a_VGA_mode-X_resolution = Inte en VGA mode-X-upplösning Not_a_valid_VGA_resolution = Ogiltig VGA-upplösning Not_enough_memory = Slut på minne Not_in_stereo_or_mono_mode = Är inte i stereo- eller monoläge OPL2_synth = OPL2-synt OPL3_synth = OPL3-synt OPL3_synth_not_found = Kunde inte hitta någon OPL3-synt OPL_synth_not_found = Kunde inte hitta någon OPL-synt OSS_output_driver_must_be_installed_before_input_can_be_read = OSS-ut-drivrutin måste installeras innan inmatning kan ske Obsolete_VBE/AF_version_(need_2.0_or_greater) = För gammal version av VBE/AF (2.0 eller högre krävs) Older_SB_version_detected = Hittade äldre SB-version PCI_BIOS_not_installed = PCI BIOS är inte installerat PC_keyboard_(DOS) = PC-tangentbord (DOS) Photon_accelerated = Photon accellererad Photon_mouse = Photon-mus Photon_safe = Photon säker Photon_soft = Photon mjukvarudrivrutin Photon_windowed = Photon fönsterläge QNX_Realtime_Platform = QNX realtidsplattform QNX_keyboard = QNX-tangentbord Red = Röd Required_VGA_mode_not_supported = VGA-läget som behövs stöds inte Resolution_not_supported = Upplösningen stöds inte Right = Höger SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibel på port 0x%04x SB_MIDI_interface = SB MIDI-gränssnitt SB_output_driver_must_be_installed_before_input_can_be_read = SB-drivrutin måste installeras innan ljudinspelning kan ske SWIFT_Device_not_detected = SWIFT-enhet kunde inte hittas SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF-drivrutinerna stöder inte breda virtuella skärmar Second_OPL2_synth_not_found = Kunde inte hitta den andra OPL2-synten Set_throttle_to_maximum = Sätt gasreglaget i maxläge Set_throttle_to_minimum = Sätt gasreglaget i minläge Setting_DSP_parameters:_%s = Sätter DSP-parametrar: %s Software_wavetable_synth = Synt med mjukvaruinstrument SoundManager_3.0_or_later_required = SoundManager 3.0 eller senare krävs SoundManager_not_found = Kunde inte hitta SoundManager Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI-gränssnitt på port %X Sound_Blaster_not_found = Kunde inte hitta Sound Blaster Sound_system_not_installed = Ljudsystemet installerades inte Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscale %s (%d hz) på port %X, använder IRQ %D, DMA-kanal %d och waveport %X Soundscape_not_found = Kunde inte hitta Soundscape Standard_joystick = Standardjoystick Stick = Joystick The_sound_of_silence = Total Tystnad This_driver_needs_local_display = Denna drivrutin kräver lokal display This_driver_needs_root_privileges = Drivrutinen kräver rootprivilegier Throttle = Gasreglage Triangle = Triangel Unable_to_find_a_suitable_graphics_driver = Kunde inte hitta någon passande drivrutin för grafik Unable_to_find_a_usable_VT = Kunde inte hitta någon användbar VT Unable_to_map_video_memory = Kunde inte mappa videominne Unable_to_open = Kunde inte öppna Unable_to_open_a_mouse_device = Kunde inte öppna musenhet Unable_to_open_%s:_%s = Kunde inte öppna %s: %s Unable_to_reopen_new_console = Kunde inte öppna ett nytt konsoll Unsupported_color_depth = Färgdjupet stöds inte Unsupported_memory_layout = Minneslayouten stöds inte Unsupported_sample_format = Ljudformatet stöds inte Unsupported_screen_size = Upplösningen stöds inte Unsupported_virtual_resolution = Den virtuella upplösningen stöds inte VBE/AF_Plug_and_Play_initialisation_failed = VBE/AF Plug and Play-initieringen misslyckades VBE/AF_device_not_present = Kunde inte hitta någon VBE/AF-enhet VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF direktpekare stöds inte på detta system VBE_%d.0_not_available = VBE %d.0 är inte tillgängligt VESA_function_0x4F02_failed = VESA-funktionen 0x4F02 misslyckades VESA_function_0x4F06_failed = VESA-funktionen 0x4F06 misslyckades VESA_mode_0x100_not_available = VESA-läge 0x100 är inte tillgängligt VESA_not_available = VESA är inte tillgängligt VESA_protected_mode_interface_not_available = Protected mode-gränssnitt för VESA är inte tillgängligt VGA_only_supports_8_bit_color = VGA stöder bara 8-bitars färg VT_WAITACTIVE_failure = VT_WAITACTIVE-fel Variable-rate_timer = Timer med variabel hastighet VidMode_extension_is_not_supported = VidMode-utökning stöds inte VidMode_extension_requires_local_display = VidMode-utökning kräver lokal display Virtual_screen_size_too_large = Virtuella skärmbredden är för stor Win32_high_performance_timer = Win32 högupplöst timer Win32_low_performance_timer = Win32 lågupplöst timer Windowed_mode_not_supported = Fönsterläge stöds inte Windows_2000_mouse = Windows 2000-mus Windows_NT_mouse = Windows NT-mus Windows_Sound_System = Windows ljudsystem Wingman_Warrior_not_connected = Wingman Warrior är inte ansluten X-Windows_keyboard = X-Windows-tangentbord X-Windows_mouse = X-Windows-mus X11_fullscreen = X11 helskärm X11_window = X11 fönsterläge Xtended_mode_only_supports_640x400 = Xtended mode stöder bara 640x400 Xtended_mode_only_supports_8_bit_color = Xtended mode stöder bara 8-bitars färg Yellow = Gul Yes = Ja allegro_window_close_message = Varning: Om du stänger programmet på detta sätt kan det orsaka förlust av data och få oväntade sidoeffekter. Det rekommenderas att använda programmets eget kommando för att avsluta. Vill du ändå stänga programmet? approx. = ungefär colors = färger failed_on_channel_initialization = Initiering av kanalen misslyckades no_vsync = ingen vsync open_NoteAllocator_failed = open NoteAllocator misslyckades unused = oanvänd allegro-4.4.3.1/resource/language/sktext.cfg0000664000175000017500000002465113437077643017725 0ustar siegesiegelanguage_name = Slovak [language] %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) na porte %X, používa IRQ %d a DMA kanál %d %s_does_not_support_MIDI_input = %s nepodporuje MIDI vstup %s_does_not_support_audio_input = %s nepodporuje audio vstup %s_must_only_be_writeable_by_root = %s musí byť zapisovateľné len rootom %s_not_found = %s nebol nájdený %s_on_port_%X = %s na porte %X %s:_%d bits,_%s,_%d bps,_%s = %s: %d bitov, %s, %d bps, %s %s:_can_not_open = %s: nedá sa otvoriť AWE32_detection_failed_on_port_0x%04x = Detekcia AWE32 zlyhala na porte 0x%04x AWE32_driver: had trouble with the embedded data = Ovládač AWE32: mal problém s vloženými údajmi AWE32_not_detected = AWE32 nedetekovaný Autodetect = Autodetekcia BLASTER_environment_variable_has_no_E_section = Premenná prostredia BLASTER nemá sekciu E BLASTER_environment_variable_not_set = Premenná prostredia BLASTER nie je nastavená Back = Späť Bad_VBE/AF_driver_ID_string = Zlý ID reťazec VBE/AF ovládača Banked_framebuffer_not_available = Banked framebuffer nie je dostupný Blue = Modrý C_Down = C Dolu C_Left = C Vľavo C_Right = C Vpravo C_Up = C Hore Can_not_allocate_audio_buffer = Nedá sa alokovať zvukový buffer Can_not_create_XImage = Nedá sa vytvoriť XImage Can_not_get_video_mode_settings = Nedajú sa zistiť nastavenia video režimu Can_not_grab_keyboard = Nedá sa grabovať klávesnica Can_not_grab_mouse = Nedá sa grabovať myš Can_not_init_software_mixer = Nedá sa inicializovať softwarový mixér Can_not_install_colormap = Nedá sa inštalovať colormap Can_not_obtain_user_name = Nedá sa zistiť meno užívateľa Can_not_query_DirectVideo = Nedá sa dotazovať DirectVideo Can_not_set_video_mode = Nedá sa nastaviť video režim Can_not_switch_to_DGA_mode = Nedá sa prepnúť do DGA režimu Can't_find_VBEAF.DRV = Nedá sa nájsť VBEAF.DRV Can't_make_linear_screen_bitmap = Nedá sa vytvoriť lineárna obrazovková bitmapa Can't_map_framebuffer_%s = Nedá sa mapovať framebuffer %s Can't_map_memory_for_VBE/AF = Nedá sa mapovať pamäť pre VBE/AF Can't_open_framebuffer_%s = Nedá sa otvoriť framebuffer %s Can't_use_SB MIDI_interface_and_DSP_at_the_same_time = SB MIDI interfejs a DSP sa nedajú používať naraz Cancel = Storno Cannot_enable_linear_addressing = Nedá sa zapnúť lineárna adresácia Cannot_open_card/pcm_device = Nedá sa otvoriť card/pcm zariadenie Cannot_open_default_visual! = Nedá sa otvoriť default visual! Cannot_open_palemu/trueemu_visual! = Nedá sa otvoriť palemu/trueemu visual! Cannot_set_playback_format = Nedá sa nastaviť formát prehrávania Card_#%d,_device_#%d:_%d_bits,_%s,_%d_bps,_%s = Karta #%d, zariadenie #%d: %d bitov, %s, %d bps, %s Centre_the_hat = Vycentruj hat Could_not_find_GRIP.GLL = Nedá sa nájsť GRIP.GLL Could_not_initialize_GrIP_system = Nepodarilo sa nájsť systém GrIP Couldn't_allocate_screen_bitmap! = Nedá sa alokovať obrazovková bitmapa! DGA_extension_is_not_supported = DGA rozšírenie nie je podporované DIGMID_patch_set_not_found = Sada DIGMID záplat nebola nájdená Device_connected_is_not_a_Wingman_Warrior = Pripojené zariadenie nie je Wingman Warrior Digital_input_driver_not_found = Ovládač digitálneho vstupu nebol nájdený Digital_sound_driver_not_found = Ovládač digitálneho zvuku nebol nájdený DirectVideo_is_not_supported = DirectVideo nie je podporované Disk_error = Chyba disku Dual_OPL2_synths = Duálny OPL2 syntezátor ES%X_(%d hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) na porte %X, používajúci IRQ %d a DMA kanál %d ESS_AudioDrive_not_found = ESS AudioDrive nebol nájdený Error_finding_our_VT: %s = Chyba pri hľadaní nášho VT: %s Error_reading_.IBK_file_'%s' = Chyba pri čítaní .IBK súboru '%s' Error_setting_VGA_video_mode = Chyba pri nastavovaní VGA video režimu Failed_to_init_MIDI_input_driver = Inicializácia ovládača MIDI vstupu zlyhala Failed_to_init_MIDI_music_driver = Inicializácia ovládača MIDI hudby zlyhala Failed_to_init_digital_input_driver = Inicializácia ovládača digitálneho vstupu zlyhala Failed_to_init_digital_sound_driver = Inicializácia ovládača digitálneho zvuku zlyhala Failed_to_set_VBE/AF_mode = Chyba pri nastavovaní VBE/AF módu Fatal_error:_unable_to_activate_the_Allegro_system = Fatálna chyba: nebolo možné aktivovať systém Allegro Fatal_error:_unable_to_set_GFX_SAFE = Fatálna chyba: nepodarilo sa nastaviť režim GFX_SAFE Framebuffer_ioctl()_failed = Framebuffer ioctl() zlyhal Framebuffer_resolution_not_available = Rozlíšenie framebuffera nie je dostupné Getting_buffer_size:_%s = Zisťujem veľkosť bufferu: %s Graphics_Mode = Grafický režim Green = Zelený Hardware_acceleration_not_available = Hardwarová akcelerácia nie je dostupná Hardware_scrolling_not_supported = Hardwarový scrolling nie je podporovaný Hat = Hat Input_is_not_supported = Vstup nie je podporovaný Insufficient_%s_voices_available = Nedostatočný počet %s hlasov Insufficient_video_memory = Nedostatok video pamäte Internal_error = Interná chyba L1 = L1 L2 = L2 Left = Vľavo Linear_framebuffer_not_available = Lineárny framebuffer nie je dostupný Linux_MS_Intellimouse = Linuxová MS Intellimouse Linux_PS/2_Intellimouse = Linuxová PS/2 Intellimouse MIDI_input_driver_not_found = Ovládač MIDI vstupu nebol nájdený MIDI_music_driver_not_found = ovládač MIDI hudby nebol nájdený MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = MPU-401 MIDI interfejs na porte %X, používajúci IRQ %d MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 a %s majú konflikt na IRQ %d MPU-401_not_found = MPU-401 nebol nájdený Mode-X_only_supports_8_bit_color = Mód X podporuje len 8-bitové farby Move_stick_2_to_the_bottom_right = Pohni druhou pákou do pravého dolného rohu Move_stick_2_to_the_top_left = Pohni druhou pákou do ľavého horného rohu Move_stick_to_the_bottom_right = Pohni pákou do pravého dolného rohu Move_stick_to_the_top_left = Pohni pákou do ľavého horného rohu Move_the_hat_down = Pohni hat dolu Move_the_hat_left = Pohni hat doľava Move_the_hat_right = Pohni hat doprava Move_the_hat_up = Pohni hat hore No_GrIP_devices_available = Nie sú dostupné žiadne GrIP zariadenia No_joysticks_found = Neboli nájdené žiadne joysticky No_server = Žiadny server No_window = Žiadne okno Not_a_VGA_mode-X_resolution = Toto nie je rozlíšenie VGA módu X Not_a_valid_VGA_resolution = Toto nie je platné VGA rozlíšenie Not_enough_memory = Nedostatok pamäti Not_in_stereo_or_mono_mode = Nie je v stereo alebo mono režime OK = OK OPL_synth_not_found = OPL syntezátor nebol nájdený OPL2_synth = OPL2 syntezátor OPL3_synth_not_found = OPL3 syntezátor nebol nájdený OPL3_synth = OPL3 syntezátor Obsolete_VBE/AF_version_(need_2.0_or_greater) = Zastaralá verzia VBE/AF (nutná verzia 2.0 a vyššia) Older_SB_version detected = Staršia verzia SB bola detekovaná Pad = kontrolér Position_X = Pozícia X Position_y = Pozícia y Position = Pozícia R1 = R1 R2 = R2 Red = Červený Requested_mode_not_available! = Požadovaný mód nie je dostupný Required_VGA_mode_not_supported = Požadovaný VGA mód nie je podporovaný Resolution_not_supported = Rozlíšenie nie je podporované Right = Vpravo SB_AWE32/compatible_on_port_0x%04x = SB AWE32/kompatibilný na porte 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = Pred tým, ako je možné čítať vstup, musí byť nainštalovaný ovládač SB výstupu SWIFT_Device_not_detected = SWIFT zariadenie nebolo detekované SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = SciTech VBE/AF ovládače nepodporujú široké virtuálne obrazovky Second_OPL2_synth_not_found = Druhý OPL2 syntezátor nebol nájdený Set_throttle_to_maximum = Nastav "plyn" na minimum Set_throttle_to_minimum = Nastav "plyn" na minimum Setting_DSP_parameters:_%s = Nastavujem parametre DSP: %s Setting_fragment_size:_%s = Nastavujem veľkosť fragmentu: %s Software_wavetable_synth = Softwarová wavetable syntéza Sound_Blaster_MIDI_interface_on_port_%X = Sound Blaster MIDI interfejs na porte %X Sound_Blaster_not_found = Sound Blaster nebol nájdený Sound_system_not_installed = Zvukový systém nie je nainštalovaný Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) na porte %X, používa IRQ %d, DMA kanál %d a waveport %X Soundscape_not_found = Soundscape nebol nájdený Start = Štart The_sound_of_silence = Zvuk ticha This_driver_needs_local_display = Tento ovládač potrebuje lokálny displej This_driver_needs_root_privileges = Tento ovládač potrebuje rootovské privilégiá Throttle = "Plyn" Unable_to_control_VT_switching = Nedá sa kontrolovať prepínanie VT Unable_to_find_a_suitable_graphics_driver = Nepodarilo sa nájsť vhodný grafický ovládač Unable_to_find_a_usable_VT = Nedá sa nájsť použiteľný VT Unable_to_map_video_memory = Nedá sa mapovať video pamäť Unable_to_open_%s:_%s = Nedá sa otvoriť %s: %s Unable_to_open = Nedá sa otvoriť Unable_to_reopen_new_console = Nedá sa znovu otvoriť nová konzola Unsupported_color_depth = Nepodporovaná farebná hĺbka Unsupported_memory_layout = Nepodporovaný layout pamäte Unsupported_sample_format = Nepodporovaný formát samplu Unsupported_screen_size = Nepodporovaná veľkosť obrazovky VBE_%d.0_not_available = VBE %d.0 nie je dostupná VBE/AF_Plug_and_Play_initialisation_failed = Inicializácia VBE/AF Plug and Play zlyhala VBE/AF_device_not_present = VBE/AF zariadenie nie je prítomné VBE/AF_nearptrs_not_supported_on_this_platform = VBE/AF nearptrs nie sú podporované na tejto platforme VESA_function_0x4F02_failed = VESA funkcia 0x4F02 zlyhala VESA_function_0x4F06_failed = VESA funkcia 0x4F06 zlyhala VESA_mode_0x100_not_available = VESA mód 0x100 nie je dostupný VESA_not_available = VESA nie je dostupná VESA_protected_mode_interface_not_available = Interfejs VESA protected režimu nie je dostupný VGA_only_supports_8_bit_color = VGA podporuje len 8-bitové farby VT_WAITACTIVE_failure = Chyba VT_WAITACTIVE VidMode_extension_is_not_supported = VidMode rozšírenie nie je podporované Virtual_screen_size_too_large = Virtuálna obrazovka je príliš veľká Wingman_Warrior_not_connected = Wingman Warrior nie je pripojený X = X Xtended_mode_only_supports_640x400 = Xtended režim podporuje len rozlíšenie 640x400 Xtended_mode_only_supports_8_bit_color = Xtended režim podporuje len 8-bitové farby Y = Y Yellow = Žltý approx. = pribl. digital = digitálnych fb_mode_%dx%d = fb mód %dx%d no_vsync = žiadna vertikálna synchronizácia unused = nepoužitý allegro-4.4.3.1/resource/language/frtext.cfg0000664000175000017500000003064613437077643017720 0ustar siegesiegelanguage_name = Français [language] AWE32_detection_failed_on_port_0x%04x = Echec de la détection de l'AWE32 sur le port 0x%04x AWE32_driver:_had_trouble_with_the_embedded_data = Pilote AWE32: problèmes avec les données résidentes AWE32_not_detected = AWE32 non détectée Aim = Pointage Aim_X = Pointage X Aim_y = Pointage y Analogue_Buttons = Boutons analogiques Autodetect = Autodétection Auto_fullscreen = Auto plein écran Auto_windowed = Auto fenêtré BLASTER_environment_variable_has_no_E_section = La variable d'environnement BLASTER n'a pas de section E BLASTER_environment_variable_not_set = Variable d'environnement BLASTER non définie Back = Arrière Bad_VBE/AF_driver_ID_string = Mauvaise chaîne d'identification du driver VBE/AF Banked_framebuffer_not_available = Tampon d'affichage à banques multiples non disponible Blue = Bleu Button_1 = Bouton 1 Button_2 = Bouton 2 Button_3 = Bouton 3 Button_4 = Bouton 4 Button_5 = Bouton 5 C_Down = C Bas C_Left = C Gauche C_Right = C Droite C_Up = C Haut Cancel = Annuler Cannot_access_the_framebuffer = Impossible d'accéder au tampon d'affichage Can_not_allocate_audio_buffer = Impossible d'allouer le tampon audio Can_not_create_XImage = Impossible de créer une XImage Cannot_create_direct_context = Impossible de créer un contexte direct Cannot_create_offscreen_context = Impossible de créer un contexte sous-jacent Can_not_do_double_buffered_sound = Impossible d'utiliser un double tampon pour le son Cannot_enable_linear_addressing = Impossible d'activer l'adressage linéaire Can_not_get_channel_setup = Impossible d'obtenir l'initialisation du canal Can_not_get_information_about_sound = Impossible d'obtenir d'information sur le son Can_not_get_video_mode_settings = Impossible d'obtenir les réglages du mode vidéo Can_not_grab_keyboard = Impossible de prendre le contrôle du clavier Can_not_grab_mouse = Impossible de prendre le contrôle de la souris Can_not_init_software_mixer = Impossible d'initialiser le mixer logiciel Can_not_install_colormap = Impossible d'installer la carte des couleurs Can_not_obtain_user_name = Impossible d'obtenir le nom de l'utilisateur Can_not_open_card/pcm_device = Impossible d'accéder à la carte ou au périphérique PCM Can_not_open_framebuffer = Impossible d'accéder au tampon d'affichage Can_not_query_DirectVideo = Impossible d'interroger DirectVideo Can_not_set_channel_parameters = Impossible de définir les paramètres du canal Can_not_set_video_mode = Impossible d'installer le mode vidéo Cannot_start_direct_context = Impossible de démarrer le context direct Can_not_switch_to_DGA_mode = Impossible de passer en mode DGA Can't_find_VBEAF.DRV = Impossible de trouver VBEAF.DRV Can't_make_linear_screen_bitmap = Impossible de créer un bitmap écran lineaire Can't_map_framebuffer = Impossible d'adresser le tampon d'affichage Can't_map_memory_for_VBE/AF = Impossible d'adresser la mémoire pour VBE/AF Can't_open_framebuffer_%s = Impossible d'accéder au tampon d'affichage %s Can't_use_SB_MIDI_interface_and_DSP_at_the_same_time = Impossible d'utiliser l'interface SB MIDI et le DSP en même temps Card__%d,_device__%d:_%d_bits,_%s,_%d_bps,_%s = Carte #%d, périphérique #%d: %d bits, %s, %d bps, %s Centre_the_hat = Centrer le joystick de direction Circle = Cercle Could_not_find_GRIP.GLL = Impossible de trouver GRIP.GLL Could_not_initialize_GrIP_system = Impossible d'initialiser le système GrIP Cross = Croix DGA_1.0_is_required = DGA 1.0 est requis DGA_2.0_or_newer_is_required = DGA 2.0 ou plus récent est requis DGA_extension_is_not_supported = L'extension DGA n'est pas supportée DIGMID_patch_set_not_found = Le fichier de patches DIGMID n'a pas été trouvé Device_connected_is_not_a_Wingman_Warrior = Le périphérique connecté n'est pas un Wingman Warrior Dial = Cadran Digital_input_driver_not_found = Pilote d'entrée digitale non trouvé Digital_sound_driver_not_found = Pilote de son digital non trouvé DirectVideo_is_not_supported = DirectVideo n'est pas supporté Direction_Pad = Manette de direction Direction_Pad_X = Manette de direction X Direction_Pad_Y = Manette de direction Y Dual_OPL2_synths = Double synthétiseur OPL2 ESS_AudioDrive_not_found = ESS AudioDrive non trouvée ES%X_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = ES%X (%d hz) sur le port %X, utilisant l'IRQ %d et le canal DMA %d Error_finding_our_VT:_%s = Impossible de trouver notre VT: %s Error_reading_.IBK_file_'%s' = Erreur de lecture du fichier .IBK '%s' Error_setting_VGA_video_mode = Erreur d'installation du mode vidéo VGA Failed_to_init_MIDI_input_driver = Echec de l'initialisation du pilote d'entrée MIDI Failed_to_init_MIDI_music_driver = Echec de l'initialisation du pilote de musique MIDI Failed_to_init_digital_input_driver = Echec de l'initialisation du pilote d'entrée digitale Failed_to_init_digital_sound_driver = Echec de l'initialisation du pilote de son digital Failed_to_set_VBE/AF_mode = Echec de l'installation du mode VBE/AF Fatal_error:_unable_to_activate_the_Allegro_system = Erreur fatale: impossible d'activer le système Allegro Fatal_error:_unable_to_set_GFX_SAFE = Erreur fatale: impossible d'installer GFX_SAFE Framebuffer_ioctl()_failed = Echec de l'appel ioctl() pour le tampon d'affichage Framebuffer_resolution_not_available = Résolution du tampon d'affichage non disponible Getting_buffer_size:_%s = Détermination de la taille du tampon: %s Graphics_Mode = Mode graphique Green = Vert Hardware_acceleration_not_available = Accélération matérielle non disponible Hardware_scrolling_not_supported = Scrolling matériel non supporté Hat = Joystick de direction I_Button = Bouton I II_Button = Bouton II Input_is_not_supported = L'entrée des données n'est pas supportée Insufficient_%s_voices_available = Insuffisamment de voix %s disponibles Insufficient_video_memory = Mémoire vidéo insuffisante Internal_error = Erreur interne L1_Button = Bouton L1 Left = Gauche Left_Stick = Manche gauche Left_Stick_X = Manche gauche X Left_Stick_Y = Manche gauche Y Linear_framebuffer_not_available = Tampon d'affichage linéaire non disponible MIDI_input_driver_not_found = Pilote d'entrée MIDI non trouvé MIDI_music_driver_not_found = Pilote de musique MIDI non trouvé MPU-401_MIDI_interface_on_port_%X,_using_IRQ_%d = Interface MPU-401 MIDI sur le port %X, utilisant l'IRQ %d MPU-401_and_%s_conflict_over_IRQ_%d = MPU-401 et %s sont en conflit sur l'IRQ %d MPU-401_not_found = MPU-401 non trouvé Mode-X_only_supports_8_bit_color = Le Mode-X ne supporte que les modes 8 bits Move_stick_2_to_the_bottom_right = Déplacez le joystick 2 en bas à droite Move_stick_2_to_the_top_left = Déplacez le joystick 2 en haut à gauche Move_stick_to_the_bottom_right = Déplacez le joystick en bas à droite Move_stick_to_the_top_left = Déplacez le joystick en haut à gauche Move_the_hat_down = Déplacez le joystick de direction vers le bas Move_the_hat_left = Déplacez le joystick de direction vers la gauche Move_the_hat_right = Déplacez le joystick de direction vers la droite Move_the_hat_up = Déplacez le joystick de direction vers le haut No = Non No_GrIP_devices_available = Pas de périphérique GrIP disponible No_joysticks_found = Aucune manette de jeux trouvée No_server = Pas de serveur No_support_synth_type_found = Impossible de trouver un type de synthétiseur supporté Not_a_VGA_mode-X_resolution = Ceci n'est pas une résolution VGA Mode-X valide Not_a_valid_VGA_resolution = Ceci n'est pas une résolution VGA valide Not_enough_memory = Pas assez de mémoire Not_in_stereo_or_mono_mode = Ni en mode stéréo ni en mode mono No_window = Pas de fenêtre OPL2_synth = synthétiseur OPL2 OPL3_synth = synthétiseur OPL3 OPL3_synth_not_found = synthétiseur OPL3 non trouvé OPL_synth_not_found = synthétiseur OPL non trouvé OSS_output_driver_must_be_installed_before_input_can_be_read = Le pilote OSS de restitution doit être installé avant que l'entrée ne soit lue Obsolete_VBE/AF_version_(need_2.0_or_greater) = Pilote VBE/AF obsolète (nécessite une version 2.0 ou plus) Older_SB_version_detected = Vieille version de SB détectée Overlays_not_supported = Overlays non supportés PCI_BIOS_not_installed = BIOS PCI non installé Pad = Manette Red = Rouge Required_VGA_mode_not_supported = Mode VGA requis non supporté Resolution_not_supported = Résolution non supportée Right = Droite Right_Stick = Manche droite Right_Stick_X = Manche droite X Right_Stick_Y = Manche droite Y SB_AWE32/compatible_on_port_0x%04x = SB AWE32/compatible sur le port 0x%04x SB_output_driver_must_be_installed_before_input_can_be_read = Le pilote SB de restitution doit être installé avant que l'entrée ne soit lue SWIFT_Device_not_detected = Périphérique SWIFT non détecté SciTech_VBE/AF_drivers_do_not_support_wide_virtual_screens = Les pilotes SciTech VBE/AF ne supportent pas les grands écrans virtuels Second_OPL2_synth_not_found = Second synthétiseur OPL2 non trouvé Select = Sélectionner Set_throttle_to_maximum = Positionnez l'accélerateur au maximum Set_throttle_to_minimum = Positionnez l'accélerateur au minimum Setting_DSP_parameters:_%s = Réglage des paramètres du DSP: %s Setting_fragment_size:_%s = Réglage de la taille des fragments: %s Software_wavetable_synth = Synthèse logicielle à partir de tables de sons Sound_Blaster_MIDI_interface_on_port_%X = Interface MIDI Sound Blaster sur le port %X Sound_Blaster_not_found = Sound Blaster non trouvé SoundManager_3.0_or_later_required = SoundManager 3.0 ou plus récent requis SoundManager_not_found = SoundManager non trouvé Soundscape_not_found = Soundscape non trouvé Soundscape_%s_(%d_hz)_on_port_%X,_using_IRQ_%d,_DMA_channel_%d_and_waveport_%X = Soundscape %s (%d hz) sur le port %X, utilisant l'IRQ %d, le canal DMA %d et le port d'ondes %X Sound_system_not_installed = système sonore non installé Square = Carré Start = Démarrage Stick = Manche Stick_X = Manche X Stick_Y = Manche Y Stick_%d = Manche %d The_sound_of_silence = Le son du silence This_driver_needs_local_display = Ce pilote nécessite un écran local This_driver_needs_root_privileges = Ce pilote nécessite les privilèges de root Throttle = Accélérateur Unable_to_control_VT_switching = Incapable de contrôler le basculement en VT Unable_to_find_a_suitable_graphics_driver = Incapable de trouver un pilote graphique adapté Unable_to_find_a_usable_VT = Incapable de trouver un VT utilisable Unable_to_map_video_memory = Incapable d'adresser la mémoire vidéo Unable_to_open = Incapable d'ouvrir Unable_to_open_%s:_%s = Incapable d'ouvrir %s: %s Unable_to_reopen_new_console = Incapable de réouvrir une nouvelle console Unsupported_color_depth = Profondeur de couleurs non supportée Unsupported_memory_layout = Disposition de mémoire non supportée Unsupported_sample_format = Format de morceau musical non supporté Unsupported_screen_size = Taille d'écran non supportée Unsupported_virtual_resolution = Résolution virtuelle non supportée VBE/AF_Plug_and_Play_initialisation_failed = Echec de l'initialisation du pilote VBE/AF Plug and Play VBE/AF_device_not_present = Pilote VBE/AF absent VBE/AF_nearptrs_not_supported_on_this_platform = Les pointeurs courts VBE/AF ne sont pas supportés sur cette plateforme VBE_%d.0_not_available = VBE %d.0 non disponible VESA_function_0x4F02_failed = Echec de la fonction VESA 0x4F02 VESA_function_0x4F06_failed = Echec de la fonction VESA 0x4F06 VESA_mode_0x100_not_available = Mode VESA 0x100 non disponible VESA_not_available = VESA non disponible VESA_protected_mode_interface_not_available = Interface VESA en mode protégé non disponible VGA_only_supports_8_bit_color = VGA supporte seulement les couleurs 8 bits VT_WAITACTIVE_failure = Echec de VT_WAITACTIVE VidMode_extension_is_not_supported = L'extension VidMode n'est pas supportée Virtual_screen_size_too_large = Ecran virtuel trop large Windowed_mode_not_supported = Mode fenêtré non supporté Wingman_Warrior_not_connected = Wingman Warrior non connecté Xtended_mode_only_supports_640x400 = Le mode Xtended supporte seulement le 640x400 Xtended_mode_only_supports_8_bit_color = Le mode Xtended supporte seulement les couleurs 8 bits Yellow = Jaune Yes = Oui no_vsync = pas de vsync %s:_can_not_open = %s: impossible d'ouvrir %s_(%d_hz)_on_port_%X,_using_IRQ_%d_and_DMA_channel_%d = %s (%d hz) sur le port %X, utilisant l'IRQ %d et le canal DMA %d %s_does_not_support_MIDI_input = %s ne supporte pas l'entrée MIDI %s_does_not_support_audio_input = %s ne supporte pas l'entrée audio %s_must_only_be_writeable_by_root = %s ne doit être modifiable que par root %s_not_found = %s non trouvé %s_on_port_%X = %s sur le port %X unused = inutilisé allegro-4.4.3.1/resource/keyboard/0000775000175000017500000000000013437077643015727 5ustar siegesiegeallegro-4.4.3.1/resource/keyboard/be.cfg0000664000175000017500000000160513437077643017000 0ustar siegesiegekeyboard_name = Belgium [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key28 = 38 key29 = 216 key30 = 34 key31 = 39 key32 = 40 key33 = 186 key35 = 33 key61 = 41 key62 = 45 key17 = 97 key23 = 122 key65 = 94 key66 = 36 key1 = 113 key68 = 109 key69 = 249 key60 = 178 key70 = 181 key26 = 119 key13 = 44 key72 = 59 key73 = 58 key74 = 61 [key_capslock] key61 = 176 key62 = 95 key17 = 65 key23 = 90 key65 = 252 key66 = 42 key1 = 81 key68 = 77 key69 = 37 key70 = 250 key26 = 87 key13 = 63 key72 = 46 key73 = 47 key74 = 43 [key_shift] key28 = 49 key29 = 50 key30 = 51 key31 = 52 key32 = 53 key33 = 54 key34 = 55 key35 = 56 key36 = 57 key27 = 48 key61 = 176 key62 = 95 key17 = 65 key23 = 90 key65 = 252 key66 = 42 key1 = 81 key68 = 77 key69 = 37 key70 = 250 key26 = 87 key13 = 63 key72 = 46 key73 = 47 key74 = 43 allegro-4.4.3.1/resource/keyboard/fr.cfg0000664000175000017500000000332113437077643017016 0ustar siegesiegekeyboard_name = France [key_escape] accent1 = 65 accent2 = 65 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 0 [key_ascii] key28 = 38 key29 = 233 key30 = 34 key31 = 39 key32 = 40 key33 = 45 key34 = 232 key35 = 95 key36 = 231 key27 = 224 key61 = 41 key17 = 97 key23 = 122 key65 = 94 key66 = 36 key1 = 113 key68 = 109 key69 = 249 key60 = 178 key70 = 42 key26 = 119 key13 = 44 key72 = 59 key73 = 58 key74 = 33 key90 = 183 key71 = 60 [key_capslock] key61 = 176 key62 = 43 key17 = 65 key23 = 90 key65 = 183 key66 = 163 key1 = 81 key68 = 77 key69 = 37 key60 = 0 key70 = 181 key26 = 87 key13 = 63 key72 = 46 key73 = 47 key74 = 167 key90 = 0 key71 = 62 [key_shift] key28 = 49 key29 = 50 key30 = 51 key31 = 52 key32 = 53 key33 = 54 key34 = 55 key35 = 56 key36 = 57 key27 = 48 key61 = 176 key64 = 0 key17 = 65 key23 = 90 key65 = 183 key66 = 163 key1 = 81 key68 = 77 key69 = 37 key60 = 0 key70 = 181 key26 = 87 key13 = 63 key72 = 46 key73 = 47 key74 = 167 key37 = 0 key90 = 0 key71 = 62 [key_control] key28 = 0 key29 = 0 key30 = 0 key31 = 0 key32 = 0 key33 = 30 key34 = 0 key35 = 28 key36 = 0 key27 = 0 key62 = 31 key64 = 0 key17 = 1 key23 = 26 key65 = 27 key66 = 29 key1 = 17 key68 = 13 key26 = 23 key13 = 0 key37 = 0 [key_altgr] key29 = 126 key30 = 35 key31 = 123 key32 = 91 key33 = 124 key34 = 96 key35 = 92 key36 = 94 key27 = 64 key61 = 93 key62 = 125 key66 = 36 key5 = 8364 [key_accent1_lower] key17 = 226 key5 = 234 key21 = 251 key9 = 238 key15 = 244 [key_accent1_upper] key17 = 194 key5 = 202 key21 = 219 key9 = 206 key15 = 212 [key_accent2_lower] key17 = 228 key5 = 235 key25 = 255 key21 = 252 key9 = 239 key15 = 246 [key_accent2_upper] key17 = 196 key5 = 203 key21 = 220 key9 = 207 key15 = 214 allegro-4.4.3.1/resource/keyboard/ru.cfg0000664000175000017500000000261013437077643017035 0ustar siegesiegekeyboard_name = Russia [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key1 = 1092 key2 = 1080 key3 = 1089 key4 = 1074 key5 = 1091 key6 = 1072 key7 = 1087 key8 = 1088 key9 = 1096 key10 = 1086 key11 = 1083 key12 = 1076 key13 = 1100 key14 = 1090 key15 = 1097 key16 = 1079 key17 = 1081 key18 = 1082 key19 = 1099 key20 = 1077 key21 = 1075 key22 = 1084 key23 = 1094 key24 = 1095 key25 = 1085 key26 = 1103 key65 = 1093 key66 = 1098 key68 = 1078 key69 = 1101 key72 = 1073 key73 = 1102 [key_capslock] key1 = 1060 key2 = 1048 key3 = 1057 key4 = 1042 key5 = 1059 key6 = 1040 key7 = 1055 key8 = 1056 key9 = 1064 key10 = 1054 key11 = 1051 key12 = 1044 key13 = 1068 key14 = 1058 key15 = 1065 key16 = 1047 key17 = 1049 key18 = 1050 key19 = 1067 key20 = 1045 key21 = 1043 key22 = 1052 key23 = 1062 key24 = 1063 key25 = 1053 key26 = 1071 key65 = 1061 key66 = 1066 key68 = 1046 key69 = 1069 key72 = 1041 key73 = 1070 [key_shift] key1 = 1060 key2 = 1048 key3 = 1057 key4 = 1042 key5 = 1059 key6 = 1040 key7 = 1055 key8 = 1056 key9 = 1064 key10 = 1054 key11 = 1051 key12 = 1044 key13 = 1068 key14 = 1058 key15 = 1065 key16 = 1047 key17 = 1049 key18 = 1050 key19 = 1067 key20 = 1045 key21 = 1043 key22 = 1052 key23 = 1062 key24 = 1063 key25 = 1053 key26 = 1071 key65 = 1061 key66 = 1066 key68 = 1046 key69 = 1069 key72 = 1041 key73 = 1070 allegro-4.4.3.1/resource/keyboard/es.cfg0000664000175000017500000000221113437077643017013 0ustar siegesiegekeyboard_name = España [key_escape] accent1 = 65 accent2 = 65 accent3 = 69 accent4 = 69 accent1_flag = 0 accent1_flag = 1 accent1_flag = 0 accent1_flag = 1 [key_ascii] key61 = 39 key62 = 161 key65 = 96 key66 = 43 key68 = 241 key69 = 180 key60 = 186 key70 = 231 key74 = 45 key71 = 60 [key_capslock] key61 = 39 key62 = 161 key65 = 96 key66 = 43 key68 = 209 key69 = 180 key60 = 186 key70 = 199 key74 = 45 key71 = 60 [key_shift] key29 = 34 key30 = 183 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 191 key65 = 94 key66 = 42 key68 = 209 key69 = 183 key60 = 170 key70 = 199 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_altgr] key28 = 124 key29 = 64 key30 = 35 key33 = 172 key65 = 91 key66 = 93 key69 = 123 key60 = 92 key70 = 125 [key_accent1_lower] key5 = 232 key21 = 249 key9 = 236 key15 = 242 key1 = 224 [key_accent2_lower] key5 = 234 key21 = 251 key9 = 238 key15 = 244 key1 = 226 [key_accent3_lower] key5 = 233 key21 = 250 key9 = 237 key15 = 243 key1 = 225 [key_accent3_upper] key5 = 201 [key_accent4_lower] key5 = 235 key21 = 252 key9 = 239 key15 = 246 key1 = 228 [key_accent4_upper] key21 = 220 key15 = 214 key1 = 196 allegro-4.4.3.1/resource/keyboard/cz.cfg0000664000175000017500000000301413437077643017022 0ustar siegesiegekeyboard_name = Czech Republic [key_escape] accent1 = 62 accent2 = 62 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 0 [key_ascii] key25 = 122 key26 = 121 key27 = 233 key28 = 43 key29 = 277 key30 = 353 key31 = 269 key32 = 345 key33 = 382 key34 = 253 key35 = 225 key36 = 237 key60 = 34 key61 = 61 key65 = 250 key66 = 41 key68 = 367 key74 = 45 [key_capslock] key25 = 90 key26 = 89 key27 = 233 key28 = 43 key29 = 277 key30 = 353 key31 = 269 key32 = 345 key33 = 382 key34 = 253 key35 = 225 key36 = 237 key60 = 34 key61 = 61 key65 = 250 key66 = 41 key68 = 367 key74 = 45 [key_shift] key25 = 90 key26 = 89 key27 = 48 key28 = 49 key29 = 50 key30 = 51 key31 = 52 key32 = 53 key33 = 54 key34 = 55 key35 = 56 key36 = 57 key60 = 59 key61 = 37 key65 = 47 key66 = 40 key68 = 34 key69 = 33 key72 = 63 key73 = 58 key74 = 95 [key_accent1_lower] key1 = 225 key5 = 233 key9 = 237 key12 = 314 key14 = 324 key15 = 243 key18 = 341 key19 = 347 key21 = 250 key26 = 253 key75 = 180 [key_accent1_upper] key1 = 193 key5 = 201 key9 = 205 key12 = 313 key14 = 323 key15 = 211 key18 = 340 key19 = 346 key21 = 218 key26 = 221 key75 = 180 [key_accent2_lower] key1 = 228 key3 = 269 key4 = 271 key5 = 277 key9 = 239 key12 = 318 key14 = 328 key15 = 246 key18 = 345 key19 = 353 key20 = 357 key21 = 252 key25 = 382 key75 = 183 key26 = 255 [key_accent2_upper] key1 = 196 key3 = 268 key4 = 270 key5 = 276 key9 = 207 key12 = 317 key14 = 327 key15 = 214 key18 = 344 key19 = 352 key20 = 356 key21 = 220 key25 = 381 key75 = 183 key26 = 376 allegro-4.4.3.1/resource/keyboard/de.cfg0000664000175000017500000000160013437077643016775 0ustar siegesiegekeyboard_name = Germany [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key61 = 223 key62 = 39 key25 = 122 key65 = 252 key66 = 43 key68 = 246 key69 = 228 key60 = 94 key70 = 35 key26 = 121 key74 = 45 key71 = 60 [key_capslock] key61 = 63 key62 = 39 key25 = 90 key65 = 154 key66 = 43 key68 = 153 key69 = 142 key60 = 248 key70 = 35 key26 = 89 key74 = 45 key71 = 60 [key_shift] key29 = 34 key30 = 167 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 96 key25 = 90 key65 = 220 key66 = 42 key68 = 214 key69 = 196 key60 = 176 key70 = 39 key26 = 89 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_control] key25 = 26 key26 = 25 [key_altgr] key29 = 178 key30 = 179 key34 = 123 key35 = 91 key36 = 93 key27 = 125 key61 = 92 key17 = 64 key66 = 126 key13 = 181 key71 = 124 key5 = 8364 allegro-4.4.3.1/resource/keyboard/dk.cfg0000664000175000017500000000272713437077643017016 0ustar siegesiegekeyboard_name = Denmark [key_escape] accent1 = 62 accent2 = 62 accent3 = 66 accent4 = 66 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 1 [key_ascii] key61 = 43 key62 = 180 key65 = 229 key66 = 168 key68 = 230 key69 = 248 key60 = 189 key70 = 39 key74 = 173 key71 = 60 key90 = 44 [key_capslock] key61 = 43 key62 = 180 key65 = 197 key66 = 168 key68 = 198 key69 = 216 key60 = 189 key70 = 39 key74 = 173 key71 = 60 [key_shift] key29 = 34 key31 = 164 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 96 key65 = 197 key66 = 94 key68 = 198 key69 = 216 key60 = 167 key70 = 42 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_altgr] key29 = 64 key30 = 163 key31 = 36 key34 = 123 key35 = 91 key36 = 93 key27 = 125 key62 = 166 key66 = 126 key71 = 92 [key_accent1_lower] key5 = 233 key25 = 253 key21 = 250 key9 = 237 key15 = 243 key1 = 225 [key_accent1_upper] key5 = 201 key25 = 221 key21 = 218 key9 = 205 key15 = 211 key1 = 193 [key_accent2_lower] key5 = 232 key21 = 249 key9 = 236 key15 = 242 key1 = 224 [key_accent2_upper] key5 = 200 key21 = 217 key9 = 204 key15 = 210 key1 = 192 [key_accent3_lower] key5 = 235 key25 = 255 key21 = 252 key9 = 239 key15 = 246 key1 = 228 [key_accent3_upper] key5 = 203 key21 = 220 key9 = 207 key15 = 214 key1 = 196 [key_accent4_lower] key5 = 234 key21 = 251 key9 = 238 key15 = 212 key1 = 226 [key_accent4_upper] key5 = 202 key21 = 219 key9 = 206 key15 = 212 key1 = 194 [key_control] key65 = 29 key68 = 27 key69 = 28 allegro-4.4.3.1/resource/keyboard/us.cfg0000664000175000017500000000024013437077643017033 0ustar siegesiegekeyboard_name = United States [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 allegro-4.4.3.1/resource/keyboard/fi.cfg0000664000175000017500000000263413437077643017013 0ustar siegesiegekeyboard_name = Finland [key_escape] accent1 = 62 accent2 = 62 accent3 = 66 accent4 = 66 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 1 [key_ascii] key61 = 43 key62 = 0 key65 = 229 key66 = 0 key68 = 246 key69 = 228 key60 = 167 key70 = 39 key74 = 45 key71 = 60 [key_capslock] key61 = 43 key62 = 0 key65 = 197 key66 = 0 key68 = 214 key69 = 196 key70 = 39 key74 = 45 key71 = 60 [key_shift] key29 = 34 key31 = 164 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 0 key65 = 197 key66 = 0 key68 = 214 key69 = 196 key60 = 189 key70 = 42 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_altgr] key29 = 64 key30 = 163 key31 = 36 key34 = 123 key35 = 91 key36 = 93 key27 = 125 key61 = 92 key66 = 126 key71 = 166 [key_accent1_lower] key5 = 233 key25 = 253 key21 = 250 key9 = 237 key15 = 243 key1 = 225 [key_accent1_upper] key5 = 201 key25 = 221 key21 = 218 key9 = 205 key15 = 211 key1 = 193 [key_accent2_lower] key5 = 232 key25 = 253 key21 = 249 key9 = 236 key15 = 242 key1 = 224 [key_accent2_upper] key5 = 200 key25 = 221 key21 = 217 key9 = 204 key15 = 210 key1 = 192 [key_accent3_lower] key5 = 235 key25 = 255 key21 = 252 key9 = 239 key15 = 246 key1 = 228 [key_accent3_upper] key5 = 203 key21 = 220 key9 = 207 key15 = 214 key1 = 196 [key_accent4_lower] key5 = 234 key21 = 251 key9 = 238 key15 = 244 key1 = 226 [key_accent4_upper] key5 = 202 key21 = 219 key9 = 206 key15 = 212 key1 = 194 allegro-4.4.3.1/resource/keyboard/se.cfg0000664000175000017500000000276313437077643017027 0ustar siegesiegekeyboard_name = Sverige [key_escape] accent1 = 62 accent2 = 62 accent3 = 66 accent4 = 66 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 1 [key_ascii] key61 = 43 key62 = 43 key65 = 229 key66 = 0 key68 = 246 key69 = 228 key60 = 167 key70 = 39 key74 = 45 key71 = 60 [key_capslock] key68 = 214 key69 = 196 key60 = 167 key70 = 39 [key_shift] key29 = 34 key31 = 164 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key65 = 197 key66 = 0 key68 = 214 key69 = 196 key60 = 189 key70 = 42 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_altgr] key29 = 64 key30 = 163 key31 = 36 key34 = 123 key35 = 91 key36 = 93 key27 = 125 key61 = 92 key66 = 126 key3 = 231 key14 = 241 key71 = 124 [key_accent1_lower] key5 = 233 key25 = 253 key21 = 250 key9 = 237 key15 = 211 key1 = 225 key3 = 231 key14 = 241 key75 = 180 [key_accent1_upper] key5 = 201 key25 = 221 key21 = 218 key9 = 205 key15 = 211 key1 = 193 key3 = 199 key14 = 209 key75 = 180 [key_accent2_lower] key5 = 232 key21 = 217 key9 = 236 key15 = 242 key1 = 224 key75 = 96 [key_accent2_upper] key5 = 200 key21 = 217 key9 = 204 key15 = 210 key1 = 192 key75 = 96 [key_accent3_lower] key5 = 235 key25 = 255 key21 = 252 key9 = 239 key15 = 246 key1 = 228 key75 = 168 [key_accent3_upper] key5 = 203 key25 = 255 key21 = 220 key9 = 207 key15 = 214 key1 = 196 key75 = 168 [key_accent4_lower] key5 = 234 key21 = 251 key9 = 238 key15 = 212 key1 = 226 key75 = 94 [key_accent4_upper] key5 = 202 key21 = 219 key9 = 206 key15 = 212 key1 = 194 key75 = 94 allegro-4.4.3.1/resource/keyboard/sk.cfg0000664000175000017500000000336513437077643017034 0ustar siegesiegekeyboard_name = Slovakia [key_escape] accent1 = 62 accent2 = 62 accent3 = 60 accent4 = 61 accent1_flag = 0 accent2_flag = 1 accent3_flag = 1 accent4_flag = 4 [key_ascii] key25 = 122 key26 = 121 key27 = 233 key28 = 43 key29 = 318 key30 = 353 key31 = 269 key32 = 357 key33 = 382 key34 = 253 key35 = 225 key36 = 237 key60 = 59 key61 = 61 key65 = 250 key66 = 228 key68 = 244 key74 = 45 key69 = 167 key70 = 328 key71 = 38 key90 = 44 [key_capslock] key25 = 90 key26 = 89 key27 = 233 key28 = 43 key29 = 318 key30 = 353 key31 = 269 key32 = 357 key33 = 382 key34 = 253 key35 = 225 key36 = 237 key60 = 59 key61 = 61 key65 = 250 key66 = 228 key68 = 244 key74 = 45 key69 = 167 key70 = 328 key71 = 38 [key_shift] key25 = 90 key26 = 89 key27 = 48 key28 = 49 key29 = 50 key30 = 51 key31 = 52 key32 = 53 key33 = 54 key34 = 55 key35 = 56 key36 = 57 key60 = 176 key61 = 37 key65 = 47 key66 = 40 key68 = 34 key69 = 33 key72 = 63 key73 = 58 key74 = 95 key70 = 41 key71 = 42 key75 = 32 [key_accent1_lower] key1 = 225 key5 = 233 key9 = 237 key12 = 314 key14 = 324 key15 = 243 key18 = 341 key19 = 347 key21 = 250 key26 = 253 key75 = 180 key3 = 263 key25 = 378 [key_accent1_upper] key1 = 193 key5 = 201 key9 = 205 key12 = 313 key14 = 323 key15 = 211 key18 = 340 key19 = 346 key21 = 218 key26 = 221 key75 = 180 key3 = 262 key25 = 377 [key_accent2_lower] key3 = 269 key4 = 271 key5 = 277 key12 = 318 key14 = 328 key18 = 345 key19 = 353 key20 = 357 key25 = 382 key75 = 183 [key_accent2_upper] key3 = 268 key4 = 270 key5 = 276 key12 = 317 key14 = 327 key18 = 344 key19 = 352 key20 = 356 key25 = 381 key26 = 256 key75 = 183 [key_accent3_lower] key21 = 367 [key_accent3_upper] key21 = 366 [key_accent4_lower] key1 = 228 key15 = 246 key21 = 252 [key_accent4_upper] key1 = 196 key15 = 214 key21 = 220 allegro-4.4.3.1/resource/keyboard/ch.cfg0000664000175000017500000000275513437077643017013 0ustar siegesiegekeyboard_name = Switzerland [key_escape] accent1 = 62 accent2 = 62 accent3 = 63 accent4 = 63 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 1 [key_ascii] key61 = 39 key62 = 94 key25 = 122 key65 = 232 key66 = 168 key68 = 233 key69 = 224 key60 = 167 key70 = 36 key26 = 121 key74 = 45 key90 = 46 key71 = 60 [key_capslock] key61 = 39 key62 = 94 key65 = 200 key66 = 168 key68 = 201 key69 = 192 key60 = 163 key70 = 181 key26 = 89 key74 = 45 key90 = 46 key71 = 60 key25 = 90 [key_shift] key28 = 43 key29 = 34 key30 = 42 key31 = 231 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key64 = 0 key65 = 252 key66 = 33 key68 = 246 key69 = 228 key60 = 163 key70 = 181 key26 = 89 key72 = 59 key73 = 58 key74 = 95 key37 = 0 key90 = 46 key71 = 62 key62 = 96 key25 = 90 [key_control] key28 = 0 key29 = 0 key30 = 0 key31 = 0 key32 = 0 key33 = 30 key34 = 0 key35 = 28 key36 = 0 key27 = 0 key62 = 31 key64 = 0 key17 = 1 key23 = 26 key65 = 27 key66 = 29 key1 = 17 key68 = 13 key26 = 23 key13 = 0 key37 = 0 [key_altgr] key29 = 64 key30 = 35 key33 = 172 key34 = 166 key35 = 231 key61 = 180 key62 = 126 key66 = 93 key28 = 161 key65 = 91 key69 = 123 key60 = 125 key71 = 92 [key_accent1_lower] key5 = 234 key21 = 251 key9 = 238 key15 = 244 key1 = 226 [key_accent1_upper] key17 = 194 key5 = 202 key21 = 219 key9 = 206 key15 = 212 [key_accent2_lower] key17 = 228 key5 = 235 key25 = 255 key21 = 252 key9 = 239 key15 = 246 [key_accent2_upper] key17 = 196 key5 = 203 key21 = 220 key9 = 207 key15 = 214 allegro-4.4.3.1/resource/keyboard/uk.cfg0000664000175000017500000000044713437077643017034 0ustar siegesiegekeyboard_name = United Kingdom [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key70 = 35 [key_capslock] key70 = 35 [key_shift] key29 = 34 key30 = 163 key69 = 64 key60 = 172 key70 = 126 key71 = 124 allegro-4.4.3.1/resource/keyboard/pt.cfg0000664000175000017500000000225013437077643017032 0ustar siegesiegekeyboard_name = Portugal [key_escape] accent1 = 66 accent2 = 66 accent3 = 70 accent4 = 70 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 1 [key_ascii] key61 = 39 key62 = 171 key65 = 43 key66 = 39 key68 = 231 key69 = 186 key60 = 92 key70 = 126 key74 = 45 key71 = 60 [key_capslock] key68 = 199 key74 = 173 key71 = 60 [key_shift] key29 = 34 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 187 key65 = 42 key66 = 96 key68 = 199 key69 = 170 key60 = 124 key70 = 94 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_altgr] key29 = 64 key30 = 163 key31 = 167 key34 = 123 key35 = 91 key36 = 93 key27 = 125 key65 = 254 [key_accent1_lower] key5 = 233 key21 = 250 key9 = 237 key15 = 243 key1 = 225 [key_accent1_upper] key5 = 201 key21 = 218 key9 = 205 key15 = 211 key1 = 193 [key_accent2_lower] key5 = 232 key21 = 249 key9 = 236 key15 = 242 key1 = 224 [key_accent2_upper] key5 = 200 key21 = 217 key9 = 204 key15 = 210 key1 = 192 [key_accent3_lower] key15 = 245 key1 = 227 key14 = 164 [key_accent3_upper] key15 = 213 key1 = 195 key14 = 165 [key_accent4_lower] key5 = 234 key15 = 244 key1 = 226 [key_accent4_upper] key5 = 202 key15 = 212 key1 = 194 allegro-4.4.3.1/resource/keyboard/cf.cfg0000664000175000017500000000234013437077643016777 0ustar siegesiegekeyboard_name = Canada (Français) [key_escape] accent1 = 65 accent2 = 66 accent3 = 69 accent4 = 66 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 0 [key_ascii] key60 = 35 key65 = 128 key66 = 168 key70 = 60 key71 = 171 key74 = 233 [key_capslock] key60 = 35 key70 = 60 key74 = 201 key71 = 171 [key_shift] key29 = 34 key30 = 47 key33 = 63 key60 = 124 key65 = 128 key66 = 168 key69 = 96 key70 = 62 key71 = 187 key72 = 39 key73 = 34 key74 = 201 [key_altgr] key27 = 188 key28 = 177 key29 = 64 key30 = 163 key31 = 162 key32 = 164 key33 = 172 key34 = 124 key35 = 178 key36 = 179 key60 = 92 key61 = 189 key62 = 190 key65 = 91 key66 = 93 key68 = 126 key69 = 123 key70 = 125 key71 = 176 key72 = 175 key73 = 173 key74 = 180 [key_accent1_lower] key1 = 226 key5 = 234 key9 = 238 key15 = 244 key21 = 251 [key_accent1_upper] key1 = 194 key5 = 202 key15 = 212 key21 = 219 [key_accent2_lower] key1 = 228 key5 = 235 key9 = 239 key15 = 246 key21 = 252 key25 = 255 [key_accent2_upper] key1 = 196 key5 = 203 key15 = 214 key21 = 220 [key_accent3_lower] key1 = 224 key5 = 232 key15 = 242 key21 = 249 [key_accent3_upper] key1 = 192 key5 = 200 key9 = 204 key15 = 210 key21 = 217 [key_accent4_lower] key3 = 231 [key_accent4_upper] key3 = 199 allegro-4.4.3.1/resource/keyboard/no.cfg0000664000175000017500000000147113437077643017027 0ustar siegesiegekeyboard_name = Norway [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key61 = 43 key62 = 92 key65 = 229 key66 = 168 key68 = 248 key69 = 230 key60 = 124 key70 = 39 key74 = 45 key71 = 60 [key_capslock] key61 = 43 key62 = 92 key65 = 197 key66 = 168 key68 = 216 key69 = 198 key60 = 39 key70 = 39 key74 = 45 key71 = 60 [key_shift] key29 = 34 key31 = 164 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 96 key65 = 197 key66 = 94 key68 = 216 key69 = 198 key60 = 167 key70 = 42 key72 = 59 key73 = 58 key74 = 95 key71 = 62 [key_control] key35 = 27 key36 = 29 key62 = 28 key66 = 30 key74 = 31 [key_altgr] key29 = 64 key30 = 163 key31 = 36 key34 = 123 key35 = 91 key36 = 93 key27 = 125 key62 = 180 key66 = 126 allegro-4.4.3.1/resource/keyboard/br.cfg0000664000175000017500000000226413437077643017017 0ustar siegesiegekeyboard_name = Brazil [key_escape] accent1 = 65 accent2 = 65 accent3 = 69 accent4 = 69 accent1_flag = 0 accent2_flag = 1 accent3_flag = 0 accent4_flag = 1 [key_ascii] key60 = 39 key65 = 39 key66 = 91 key68 = 231 key69 = 126 key70 = 93 key74 = 59 key94 = 47 [key_capslock] key60 = 39 key65 = 39 key66 = 91 key68 = 199 key69 = 126 key70 = 93 key74 = 59 key94 = 47 [key_shift] key33 = 168 key60 = 34 key65 = 96 key66 = 123 key68 = 199 key69 = 94 key70 = 125 key74 = 58 key94 = 63 [key_altgr] key28 = 185 key29 = 178 key30 = 179 key31 = 163 key32 = 162 key33 = 172 key62 = 167 key66 = 170 key70 = 186 key94 = 176 [key_accent1_lower] key1 = 225 key5 = 233 key9 = 237 key15 = 243 key21 = 250 key3 = 231 [key_accent1_upper] key1 = 193 key5 = 201 key9 = 205 key15 = 211 key21 = 218 key3 = 199 [key_accent2_lower] key1 = 224 key5 = 232 key9 = 236 key15 = 242 key21 = 249 key3 = 199 [key_accent2_upper] key1 = 192 key5 = 200 key9 = 204 key15 = 210 key21 = 217 [key_accent3_lower] key1 = 227 key15 = 245 [key_accent3_upper] key1 = 195 key15 = 213 [key_accent4_lower] key1 = 226 key5 = 234 key9 = 238 key15 = 244 key21 = 251 [key_accent4_upper] key1 = 194 key5 = 202 key9 = 206 key15 = 212 key21 = 219 allegro-4.4.3.1/resource/keyboard/pl.cfg0000664000175000017500000000121713437077643017024 0ustar siegesiegekeyboard_name = Poland [key_escape] accent1 = 60 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 1 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_altgr_lower] key1 = 261 key3 = 263 key5 = 281 key12 = 322 key14 = 324 key15 = 243 key19 = 347 key24 = 378 key26 = 380 [key_altgr_upper] key1 = 260 key3 = 262 key5 = 280 key12 = 321 key14 = 323 key15 = 211 key19 = 346 key24 = 377 key26 = 379 [key_accent1_lower] key1 = 261 key3 = 263 key5 = 281 key12 = 322 key14 = 324 key15 = 243 key19 = 347 key24 = 378 key26 = 380 [key_accent1_upper] key1 = 260 key3 = 262 key5 = 280 key12 = 321 key14 = 323 key15 = 211 key19 = 346 key24 = 377 key26 = 379 allegro-4.4.3.1/resource/keyboard/dvorak.cfg0000664000175000017500000000237013437077643017700 0ustar siegesiegekeyboard_name = Dvorak [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key61 = 91 key62 = 93 key17 = 39 key23 = 44 key5 = 46 key18 = 112 key20 = 121 key25 = 102 key21 = 103 key9 = 99 key15 = 114 key16 = 108 key65 = 47 key66 = 61 key19 = 111 key4 = 101 key6 = 117 key7 = 105 key8 = 100 key10 = 104 key11 = 116 key12 = 110 key68 = 115 key69 = 45 key26 = 59 key24 = 113 key3 = 106 key22 = 107 key2 = 120 key14 = 98 key72 = 119 key73 = 118 key74 = 122 [key_capslock] key61 = 91 key62 = 93 key17 = 39 key23 = 44 key5 = 46 key18 = 80 key20 = 89 key25 = 70 key21 = 71 key9 = 67 key15 = 82 key16 = 76 key65 = 47 key66 = 61 key19 = 79 key4 = 69 key6 = 85 key7 = 73 key8 = 68 key10 = 72 key11 = 84 key12 = 78 key68 = 83 key69 = 45 key26 = 59 key24 = 81 key3 = 74 key22 = 75 key2 = 88 key14 = 66 key72 = 87 key73 = 86 key74 = 90 [key_shift] key17 = 34 key23 = 60 key5 = 62 key18 = 80 key20 = 89 key25 = 70 key21 = 71 key9 = 67 key15 = 82 key16 = 76 key65 = 63 key66 = 43 key19 = 79 key4 = 69 key6 = 85 key7 = 73 key8 = 68 key10 = 72 key11 = 84 key12 = 78 key68 = 83 key69 = 95 key26 = 58 key24 = 81 key3 = 74 key22 = 75 key2 = 88 key14 = 66 key72 = 87 key73 = 86 key74 = 90 key71 = 124 allegro-4.4.3.1/resource/keyboard/it.cfg0000664000175000017500000000134213437077643017024 0ustar siegesiegekeyboard_name = Italy [key_escape] accent1 = 0 accent2 = 0 accent3 = 0 accent4 = 0 accent1_flag = 0 accent2_flag = 0 accent3_flag = 0 accent4_flag = 0 [key_ascii] key61 = 39 key62 = 236 key65 = 232 key66 = 43 key68 = 210 key69 = 224 key60 = 92 key70 = 249 key74 = 45 key90 = 0 key71 = 60 [key_capslock] key65 = 232 key66 = 43 key68 = 242 key69 = 224 key60 = 92 key70 = 249 key74 = 45 key71 = 60 [key_shift] key29 = 34 key30 = 163 key33 = 38 key34 = 47 key35 = 40 key36 = 41 key27 = 61 key61 = 63 key62 = 94 key63 = 8 key64 = 9 key65 = 233 key66 = 42 key68 = 199 key69 = 176 key60 = 124 key70 = 167 key72 = 59 key73 = 58 key74 = 95 key90 = 1 key71 = 62 [key_control] key63 = 8 [key_altgr] key65 = 91 key66 = 93 key68 = 64 key69 = 35 allegro-4.4.3.1/tests/0000775000175000017500000000000013437077643013442 5ustar siegesiegeallegro-4.4.3.1/tests/win/0000775000175000017500000000000013437077643014237 5ustar siegesiegeallegro-4.4.3.1/tests/win/dxwindow.rc0000664000175000017500000000243113437077643016430 0ustar siegesiege// Windows resource file for the dxwindow example #include #include "dxwindow.rh" MYACCEL ACCELERATORS BEGIN VK_F1, CMD_FILE_RUN, VIRTKEY VK_F2, CMD_FILE_STOP, VIRTKEY VK_ADD, CMD_SET_SPEED_UP, CONTROL, VIRTKEY VK_SUBTRACT, CMD_SET_SPEED_DOWN, CONTROL, VIRTKEY END MYMENU MENU BEGIN POPUP "&File" BEGIN MENUITEM "&Run\tF1", CMD_FILE_RUN MENUITEM "&Stop\tF2", CMD_FILE_STOP MENUITEM SEPARATOR MENUITEM "E&xit", CMD_FILE_EXIT END POPUP "&Settings" BEGIN MENUITEM "Speed up\tCtrl +", CMD_SET_SPEED_UP MENUITEM "Speed down\tCtrl -", CMD_SET_SPEED_DOWN MENUITEM "Default Speed", CMD_SET_SPEED_DEFAULT END POPUP "&Help", HELP BEGIN MENUITEM "&About", CMD_HELP_ABOUT END END ABOUTDLG DIALOG 25, 0, 150, 100 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "About" FONT 8, "MS Shell Dlg" BEGIN CONTROL "&OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 50, 80, 50, 15 CONTROL "", -1, "button", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 140, 65 CONTROL "An example program showing how to use Allegro's DirectX windowed driver with a native window.", -1, "static", SS_CENTER | WS_CHILD | WS_VISIBLE, 25, 25, 100, 35 END allegro-4.4.3.1/tests/win/dibhello.c0000664000175000017500000001277413437077643016200 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Example program showing how Allegro graphics can be used in * Windows alongside the GDI. This method is slower than using * DirectX, but good for when you want to use some of the Allegro * drawing routines in a GUI program. * * By Marian Dvorsky. * * See readme.txt for copyright information. */ #include "allegro.h" #include "winalleg.h" HBITMAP hbmp; BITMAP *a, *b; PALETTE pal; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam) { RECT rect, updaterect; PAINTSTRUCT ps; HBITMAP oldbmp; HDC hdc, dc; switch (message) { case WM_QUERYNEWPALETTE: InvalidateRect(hwnd, NULL, 1); return 1; case WM_PALETTECHANGED: if ((HWND)wParam != hwnd) { hdc = GetDC(hwnd); InvalidateRect(hwnd, NULL, 1); ReleaseDC(hwnd, hdc); } return 1; case WM_PAINT: if (GetUpdateRect(hwnd, &updaterect, FALSE)) { hdc = BeginPaint(hwnd, &ps); /* we will blit our nice bitmap first. We didn't covert it * to HBITMAP so we will draw it this way: */ set_palette_to_hdc(hdc, pal); draw_to_hdc(hdc, b, 0, 0); /* 24 bit image we have in HBITMAP as DDB. To draw such * image, use this code: */ dc = CreateCompatibleDC(hdc); oldbmp = SelectObject(dc, hbmp); BitBlt(hdc, b->w, 0, a->w, a->h, dc, 0, 0, SRCCOPY); SelectObject(dc, oldbmp); DeleteDC(dc); /* you can also use GDI functions as well */ rect.left = 640; rect.top = 0; rect.right = updaterect.right; rect.bottom = 200; FillRect(hdc, &rect, GetStockObject(WHITE_BRUSH)); rect.left = 0; rect.top = 200; rect.right = updaterect.right; rect.bottom = updaterect.bottom; FillRect(hdc, &rect, GetStockObject(WHITE_BRUSH)); TextOut(hdc, 20, 205, "This is 8-bit allegro.pcx", 25); TextOut(hdc, 360, 205, "This is 24-bit Allegro memory bitmap", 36); EndPaint(hwnd, &ps); } return 0; case WM_DESTROY: DeleteObject(hbmp); destroy_bitmap(a); destroy_bitmap(b); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { static char szAppName[] = "Hello"; WNDCLASS wndclass; HWND hwnd; MSG msg; int x; if (!hPrevInstance) { wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; RegisterClass(&wndclass); } hwnd = CreateWindow(szAppName, /* window class name */ "HELLO Program", /* window caption */ WS_OVERLAPPEDWINDOW, /* window style */ CW_USEDEFAULT, /* initial x position */ CW_USEDEFAULT, /* initial y position */ CW_USEDEFAULT, /* initial x size */ CW_USEDEFAULT, /* initial y size */ NULL, /* parent window handle */ NULL, /* window menu handle */ hInstance, /* program instance handle */ NULL); /* creation parameters */ /* we have to install platform independent driver */ if (install_allegro(SYSTEM_NONE, &errno, atexit) != 0) exit(0); set_color_conversion(COLORCONV_NONE); /* we can optionally set GDI color format (makes things faster) */ set_gdi_color_format(); /* let's try create 24 bit bitmap */ a = create_bitmap_ex(24, 320, 200); /* we could load some 8 bit bitmap */ b = load_bitmap("..\\..\\examples\\allegro.pcx", pal); if (!b) { /* the CMake MSVC workspace puts the executable one directory deeper */ b = load_bitmap("..\\..\\..\\examples\\allegro.pcx", pal); if (!b) { MessageBox(NULL, "Can't load ..\\..\\examples\\allegro.pcx!", "Error", MB_OK); exit(0); } } /* draw something into a */ clear_bitmap(a); textout_centre_ex(a, font, "Hello world", 160, 100, makecol24(255, 0, 0), 0); textout_centre_ex(a, font, "This was created using Allegro", 160, 120, makecol24(0, 255, 0), 0); for (x=0; x<255; x++) { vline(a, x+20, 10, 20, makecol24(x, 0, 0)); vline(a, x+20, 30, 40, makecol24(0, x, 0)); vline(a, x+20, 50, 60, makecol24(0, 0, x)); } /* we will blit 24 bit bitmap as DDB */ /* as far as we will use palette for 8 bit picture 'b', we will * create this bitmap with color conversion table for palette pal * (which will be active when we're in 8-bit mode) */ select_palette(pal); hbmp = convert_bitmap_to_hbitmap(a); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } allegro-4.4.3.1/tests/win/dibsound.rh0000664000175000017500000000112613437077643016401 0ustar siegesiege// Windows resource header file for the dibsound example #define CMD_FILE_OPEN 100 #define CMD_FILE_PLAY 101 #define CMD_FILE_STOP 102 #define CMD_FILE_EXIT 103 #define CMD_SET_VOLUME_UP 110 #define CMD_SET_VOLUME_DOWN 111 #define CMD_SET_VOLUME_DEFAULT 112 #define CMD_SET_PAN_LEFT 113 #define CMD_SET_PAN_RIGHT 114 #define CMD_SET_PAN_CENTER 115 #define CMD_SET_SPEED_UP 116 #define CMD_SET_SPEED_DOWN 117 #define CMD_SET_SPEED_NORMAL 118 #define CMD_SET_LOOP_MODE 119 #define CMD_HELP_ABOUT 130 allegro-4.4.3.1/tests/win/dibsound.c0000664000175000017500000002043013437077643016211 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Example program showing how to use Allegro as a sound * library under Windows. * * By Eric Botcazou. * * Original idea and improvements by Javier Gonzalez. * * See readme.txt for copyright information. */ #include "allegro.h" #include "winalleg.h" #include "dibsound.rh" HINSTANCE hInst = NULL; PALETTE pal; BITMAP *bmp = NULL; BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: EndDialog(hwnd, IDOK); return TRUE; case IDCANCEL: EndDialog(hwnd, IDCANCEL); return TRUE; } break; } return FALSE; } int OpenNewSample(SAMPLE **sample, HWND hwnd) { OPENFILENAME openfilename; SAMPLE *new_sample; char filename[512]; memset(&openfilename, 0, sizeof(OPENFILENAME)); openfilename.lStructSize = sizeof(OPENFILENAME); openfilename.hwndOwner = hwnd; openfilename.lpstrFilter = "Sounds (*.wav;*.voc)\0*.wav;*.voc\0"; openfilename.lpstrFile = filename; openfilename.nMaxFile = sizeof(filename); openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; filename[0] = 0; if (GetOpenFileName(&openfilename)) { new_sample = load_sample(openfilename.lpstrFile); if (!new_sample) { MessageBox(hwnd, "This is not a standard sound file.", "Error!", MB_ICONERROR | MB_OK); return -1; } /* make room for next samples */ if (*sample) destroy_sample(*sample); *sample = new_sample; return 0; } return -1; } LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { static SAMPLE *sample = NULL; static int volume = 128; static int pan = 128; static int speed = 1000; static int loop = FALSE; HDC hdc; RECT updaterect; PAINTSTRUCT ps; switch(Message) { case WM_COMMAND: switch(LOWORD(wParam)) { case CMD_FILE_OPEN: OpenNewSample(&sample, hwnd); break; case CMD_FILE_PLAY: if (!sample) { if (OpenNewSample(&sample, hwnd) != 0) break; } /* play it !! */ play_sample(sample, volume, pan, speed, loop); break; case CMD_FILE_STOP: if (sample) stop_sample(sample); break; case CMD_FILE_EXIT: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case CMD_SET_VOLUME_UP: volume = MIN(volume+32, 255); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_VOLUME_DOWN: volume = MAX(volume-32, 0); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_VOLUME_DEFAULT: volume = 128; if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_PAN_LEFT: pan = MAX(pan-32, 0); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_PAN_RIGHT: pan = MIN(pan+32, 255); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_PAN_CENTER: pan = 128; if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_SPEED_UP: speed = MIN(speed*2, 8000); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_SPEED_DOWN: speed = MAX(speed/2, 125); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_SPEED_NORMAL: speed = 1000; if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_SET_LOOP_MODE: loop = !loop; CheckMenuItem(GetMenu(hwnd), CMD_SET_LOOP_MODE, loop ? MF_CHECKED : MF_UNCHECKED); if (sample) adjust_sample(sample, volume, pan, speed, loop); break; case CMD_HELP_ABOUT: DialogBox(hInst, "ABOUTDLG", hwnd, AboutDlgProc); break; } return 0; case WM_QUERYNEWPALETTE: InvalidateRect(hwnd, NULL, TRUE); return TRUE; case WM_PALETTECHANGED: if ((HWND)wParam != hwnd) { hdc = GetDC(hwnd); InvalidateRect(hwnd, NULL, TRUE); ReleaseDC(hwnd, hdc); } return TRUE; case WM_PAINT: if (GetUpdateRect(hwnd, &updaterect, FALSE)) { hdc = BeginPaint(hwnd, &ps); set_palette_to_hdc(hdc, pal); draw_to_hdc(hdc, bmp, 0, 0); EndPaint(hwnd, &ps); } return 0; case WM_CLOSE: destroy_sample(sample); DestroyWindow(hwnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, Message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { static char szAppName[] = "Sound Player"; WNDCLASS wndClass; HWND hwnd; HACCEL haccel; MSG msg; hInst = hInstance; if (!hPrevInstance) { wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInst; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wndClass.lpszMenuName = "MYMENU"; wndClass.lpszClassName = szAppName; RegisterClass(&wndClass); } hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 320, 240, NULL, NULL, hInst, NULL); if (!hwnd) { MessageBox(0, "Window Creation Failed.", "Error!", MB_ICONERROR | MB_OK | MB_SYSTEMMODAL); return 0; } /* register our window BEFORE calling allegro_init() */ win_set_window(hwnd); /* initialize the library */ if (allegro_init() != 0) return 0; /* install the digital sound module */ install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL); /* allow Allegro to keep playing samples in the background */ set_display_switch_mode(SWITCH_BACKGROUND); /* load some 8 bit bitmap */ set_color_conversion(COLORCONV_NONE); bmp = load_bitmap("..\\..\\examples\\allegro.pcx", pal); if (!bmp) { /* the CMake MSVC workspace puts the executable one directory deeper */ bmp = load_bitmap("..\\..\\..\\examples\\allegro.pcx", pal); if (!bmp) { MessageBox(hwnd, "Can't load ..\\..\\examples\\allegro.pcx", "Error!", MB_ICONERROR | MB_OK); return 0; } } /* display the window */ haccel = LoadAccelerators(hInst, "MYACCEL"); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); /* process messages */ while(GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, haccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } allegro-4.4.3.1/tests/win/scrsave.rc0000664000175000017500000000140513437077643016233 0ustar siegesiege// Windows resource file for the Allegro screensaver example #include #include "scrsave.rh" STRINGTABLE DISCARDABLE BEGIN 1 "Allegro Screensaver" END ID_CONFIG_DLG DIALOG DISCARDABLE 6, 18, 164, 86 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Allegro Screensaver Setup" FONT 8, "MS Shell Dlg" BEGIN DEFPUSHBUTTON "OK", IDOK, 28, 62, 50, 14 PUSHBUTTON "Cancel", IDCANCEL, 84, 62, 50, 14 EDITTEXT IDC_EDIT_MESSAGE, 24, 36, 124, 12, ES_AUTOHSCROLL CONTROL "Display Blue Cross", IDC_CHECK_BLUECROSS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 12, 8, 72, 8 CONTROL "Display the following mesasage:", IDC_CHECK_SHOWMESSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 12, 26, 116, 8 END allegro-4.4.3.1/tests/win/scrsave.rh0000664000175000017500000000031113437077643016233 0ustar siegesiege// Windows resource header file for the Allegro screensaver example #define IDC_EDIT_MESSAGE 100 #define IDC_CHECK_BLUECROSS 101 #define IDC_CHECK_SHOWMESSAGE 102 allegro-4.4.3.1/tests/win/dibsound.rc0000664000175000017500000000377213437077643016405 0ustar siegesiege// Windows resource file for the dibsound example #include #include "dibsound.rh" MYACCEL ACCELERATORS BEGIN VK_F1, CMD_FILE_OPEN, VIRTKEY VK_F2, CMD_FILE_PLAY, VIRTKEY VK_F3, CMD_FILE_STOP, VIRTKEY VK_ADD, CMD_SET_VOLUME_UP, CONTROL, VIRTKEY VK_SUBTRACT, CMD_SET_VOLUME_DOWN, CONTROL, VIRTKEY "L", CMD_SET_PAN_LEFT, CONTROL, VIRTKEY "R", CMD_SET_PAN_RIGHT, CONTROL, VIRTKEY "F", CMD_SET_SPEED_UP, CONTROL, VIRTKEY "S", CMD_SET_SPEED_DOWN, CONTROL, VIRTKEY "O", CMD_SET_LOOP_MODE, CONTROL, VIRTKEY END MYMENU MENU BEGIN POPUP "&File" BEGIN MENUITEM "&Open...\tF1", CMD_FILE_OPEN MENUITEM "&Play\tF2", CMD_FILE_PLAY MENUITEM "&Stop\tF3", CMD_FILE_STOP MENUITEM SEPARATOR MENUITEM "E&xit", CMD_FILE_EXIT END POPUP "&Settings" BEGIN MENUITEM "Volume up\tCtrl +", CMD_SET_VOLUME_UP MENUITEM "Volume down\tCtrl -", CMD_SET_VOLUME_DOWN MENUITEM "Default Volume", CMD_SET_VOLUME_DEFAULT MENUITEM SEPARATOR MENUITEM "Pan left\tCtrl L", CMD_SET_PAN_LEFT MENUITEM "Pan right\tCtrl R", CMD_SET_PAN_RIGHT MENUITEM "Center Pan", CMD_SET_PAN_CENTER MENUITEM SEPARATOR MENUITEM "Speed up\tCtrl F", CMD_SET_SPEED_UP MENUITEM "Speed down\tCtrl S", CMD_SET_SPEED_DOWN MENUITEM "Normal Speed", CMD_SET_SPEED_NORMAL MENUITEM SEPARATOR MENUITEM "Loop mode\tCtrl O", CMD_SET_LOOP_MODE END POPUP "&Help", HELP BEGIN MENUITEM "&About", CMD_HELP_ABOUT END END ABOUTDLG DIALOG 25, 0, 150, 100 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "About" FONT 8, "MS Shell Dlg" BEGIN CONTROL "&OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 50, 80, 50, 15 CONTROL "", -1, "button", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 140, 65 CONTROL "An example program showing how to use Allegro as a sound library under Windows.", -1, "static", SS_CENTER | WS_CHILD | WS_VISIBLE, 25, 25, 100, 30 END allegro-4.4.3.1/tests/win/dxwindow.c0000664000175000017500000003076513437077643016261 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Example program showing how to use Allegro's DirectX * windowed driver with a native window. * * By Eric Botcazou. * * Modified by V. Karthik Kumar to not use keyboard routines. * * See readme.txt for copyright information. */ #include "allegro.h" #include "winalleg.h" #include "dxwindow.rh" #include "examples/running.h" #define WINDOW_WIDTH 478 #define WINDOW_HEIGHT 358 #define RADIUS 50 #define STEP 4 #define TIMER_SPEED_MAX 150 #define TIMER_SPEED_MIN 20 #define TIMER_SPEED_DEFAULT 80 #define TIMER_STEP 10 #define TIMER_SPEED_BOOST 10 #define BOOST_DURATION 1500 struct point { int x, y; fixed theta; int branch; }; HINSTANCE hInst = NULL; DATAFILE *dat; int timer_speed; volatile int tick = 0; int tick_boost = -1; int running; struct point p[8]; int radius; fixed scaled_radius; /* to keep the radial speed constant */ fixed inv_scaled_radius; void tick_counter(void) { tick++; if (tick_boost > 0) { if (tick >= tick_boost + BOOST_DURATION/TIMER_SPEED_BOOST) tick_boost = 0; } } void init_trajectory(int w, int h, int bw, int bh, int r) { p[0].x = bw + r; p[0].y = h - bh; p[0].theta = itofix(0); p[0].branch = 0; p[1].x = w - p[0].x; p[1].y = p[0].y; p[1].theta = p[0].theta; p[1].branch = 1; p[2].x = w - bw; p[2].y = h - (bh + r); p[2].theta = itofix(-64); p[2].branch = 2; p[3].x = p[2].x; p[3].y = h - p[2].y; p[3].theta = p[2].theta; p[3].branch = 3; p[4].x = p[1].x; p[4].y = bh; p[4].theta = itofix(-128); p[4].branch = 4; p[5].x = p[0].x; p[5].y = bh; p[5].theta = p[4].theta; p[5].branch = 5; p[6].x = bw; p[6].y = p[3].y; p[6].theta = itofix(-192); p[6].branch = 6; p[7].x = p[6].x; p[7].y = p[2].y; p[7].theta = p[6].theta; p[7].branch = 7; radius = r; scaled_radius = (r + bh) * fixtorad_r; /* fixed = int*fixed */ inv_scaled_radius = fixdiv(itofix(1), scaled_radius); } void calculate_position(struct point *pos, int delta_s) { int diff; fixed theta_diff; switch (pos->branch) { case 0: pos->x += delta_s; if (pos->x > p[1].x) { diff = pos->x - p[1].x; *pos = p[1]; calculate_position(pos, diff); } break; case 1: pos->theta -= inv_scaled_radius * delta_s; if (pos->theta < p[2].theta) { theta_diff = p[2].theta - pos->theta; *pos = p[2]; calculate_position(pos, fixtoi(fixmul(theta_diff, scaled_radius))); } else { pos->x = p[1].x - fixtoi(fixsin(pos->theta) * radius); pos->y = p[1].y - radius + fixtoi(fixcos(pos->theta) * radius); } break; case 2: pos->y -= delta_s; if (pos->y < p[3].y) { diff = p[3].y - pos->y; *pos = p[3]; calculate_position(pos, diff); } break; case 3: pos->theta -= inv_scaled_radius * delta_s; if (pos->theta < p[4].theta) { theta_diff = p[4].theta - pos->theta; *pos = p[4]; calculate_position(pos, fixtoi(fixmul(theta_diff, scaled_radius))); } else { pos->x = p[3].x - radius - fixtoi(fixsin(pos->theta) * radius); pos->y = p[3].y + fixtoi(fixcos(pos->theta) * radius); } break; case 4: pos->x -= delta_s; if (pos->x < p[5].x) { diff = p[5].x - pos->x; *pos = p[5]; calculate_position(pos, diff); } break; case 5: pos->theta -= inv_scaled_radius * delta_s; if (pos->theta < p[6].theta) { theta_diff = p[6].theta - pos->theta; *pos = p[6]; calculate_position(pos, fixtoi(fixmul(theta_diff, scaled_radius))); } else { pos->x = p[5].x - fixtoi(fixsin(pos->theta) * radius); pos->y = p[5].y + radius + fixtoi(fixcos(pos->theta) * radius); } break; case 6: pos->y += delta_s; if (pos->y > p[7].y) { diff = pos->y - p[7].y; *pos = p[7]; calculate_position(pos, diff); } break; case 7: pos->theta -= inv_scaled_radius * delta_s; if (pos->theta < itofix(-256)) { /* not p[0].theta */ theta_diff = itofix(-256) - pos->theta; /* not p[0].theta */ *pos = p[0]; calculate_position(pos, fixtoi(fixmul(theta_diff, scaled_radius))); } else { pos->x = p[7].x + radius - fixtoi(fixsin(pos->theta) * radius); pos->y = p[7].y + fixtoi(fixcos(pos->theta) * radius); } break; } } void boost(void) { tick_boost = tick; install_int(tick_counter, TIMER_SPEED_BOOST); play_sample((SAMPLE *)dat[SOUND_01].dat, 128, 128, 1000, FALSE); } BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: EndDialog(hwnd, IDOK); return TRUE; case IDCANCEL: EndDialog(hwnd, IDCANCEL); return TRUE; } break; } return FALSE; } LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_COMMAND: switch(LOWORD(wParam)) { case CMD_FILE_RUN: if (!running) { install_int(tick_counter, timer_speed); running = TRUE; } break; case CMD_FILE_STOP: if (running) { remove_int(tick_counter); running = FALSE; } break; case CMD_FILE_EXIT: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case CMD_SET_SPEED_UP: timer_speed -= TIMER_STEP; if (timer_speed < TIMER_SPEED_MIN) timer_speed = TIMER_SPEED_MIN; install_int(tick_counter, timer_speed); tick_boost = -1; break; case CMD_SET_SPEED_DOWN: timer_speed += TIMER_STEP; if (timer_speed > TIMER_SPEED_MAX) timer_speed = TIMER_SPEED_MAX; install_int(tick_counter, timer_speed); tick_boost = -1; break; case CMD_SET_SPEED_DEFAULT: timer_speed = TIMER_SPEED_DEFAULT; install_int(tick_counter, timer_speed); tick_boost = -1; break; case CMD_HELP_ABOUT: DialogBox(hInst, "ABOUTDLG", hwnd, AboutDlgProc); break; } return 0; case WM_LBUTTONDOWN: if (getpixel(screen, lParam&0xFFFF, lParam>>16) != 0) boost(); return 0; case WM_CLOSE: DestroyWindow(hwnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, Message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { static char szAppName[] = "Running Pac-Man"; WNDCLASS wndClass; RECT win_rect; HWND hwnd; HACCEL haccel; MSG msg; BITMAP *video_page[2]; int screen_w, screen_h, sprite_w, sprite_h; int last_tick, next_page; struct point pos; hInst = hInstance; if (!hPrevInstance) { wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInst; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = CreateSolidBrush(0); wndClass.lpszMenuName = "MYMENU"; wndClass.lpszClassName = szAppName; RegisterClass(&wndClass); } hwnd = CreateWindow(szAppName, szAppName, WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInst, NULL); if (!hwnd) { MessageBox(0, "Unable to create the window.", "Error!", MB_ICONERROR | MB_OK | MB_SYSTEMMODAL); return 0; } /* get the dimensions of the client area of the window */ GetClientRect(hwnd, &win_rect); screen_w = win_rect.right - win_rect.left; screen_h = win_rect.bottom - win_rect.top; /* the DirectX windowed driver requires the width to be a multiple of 4 */ screen_w &= ~3; /* register our window BEFORE calling allegro_init() */ win_set_window(hwnd); /* initialize the library */ if (allegro_init() != 0) return 0; install_timer(); install_keyboard(); install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL); /* install the DirectX windowed driver */ if (set_gfx_mode(GFX_DIRECTX_WIN, screen_w, screen_h, 0, 0) != 0) { MessageBox(hwnd, "Unable the set the graphics mode.", "Error!", MB_ICONERROR | MB_OK); return 0; } /* allow Allegro to keep running in the background */ set_display_switch_mode(SWITCH_BACKGROUND); /* load the data */ dat = load_datafile("../../examples/running.dat"); if (!dat) { /* the CMake MSVC workspace puts the executable one directory deeper */ dat = load_datafile("../../../examples/running.dat"); if (!dat) { MessageBox(hwnd, "Unable to load ../../examples/running.dat!", "Error!", MB_ICONERROR | MB_OK); return 0; } } sprite_w = ((BITMAP *)dat[FRAME_01].dat)->w; sprite_h = ((BITMAP *)dat[FRAME_01].dat)->h; /* initialize the trajectory parameters */ init_trajectory(screen_w, screen_h, sprite_w/2, sprite_h/2, RADIUS); /* set the 8-bit palette */ set_palette((RGB *)dat[PALETTE_001].dat); /* create two pages of video memory */ video_page[0] = create_video_bitmap(screen_w, screen_h); video_page[1] = create_video_bitmap(screen_w, screen_h); /* display the window */ haccel = LoadAccelerators(hInst, "MYACCEL"); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); /* set initial conditions */ pos = p[0]; next_page = 1; running = TRUE; timer_speed = TIMER_SPEED_DEFAULT; install_int(tick_counter, timer_speed); last_tick = tick; /* main loop */ while (TRUE) { /* process the keys */ while (keypressed()) { if ((readkey() >> 8) == KEY_B) boost(); } /* animate the screen */ clear_bitmap(video_page[next_page]); if (!running) textout_ex(video_page[next_page], font, "Paused", 10, 10, 96, -1); /* update the position if it has ticked */ if (tick != last_tick) { calculate_position(&pos, STEP); last_tick = tick; } /* handle end of boost */ if (tick_boost == 0) { install_int(tick_counter, timer_speed); tick_boost = -1; } /* draw sprite onto the backbuffer */ rotate_sprite(video_page[next_page], (BITMAP *)dat[last_tick%10].dat, pos.x - sprite_w/2, pos.y - sprite_h/2, pos.theta); /* flip the two pages of video memory */ show_video_bitmap(video_page[next_page]); next_page = 1 - next_page; /* process the Win32 messages */ while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, haccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else goto End; } } End: /* clean up ourselves */ destroy_bitmap(video_page[0]); destroy_bitmap(video_page[1]); unload_datafile(dat); return msg.wParam; } allegro-4.4.3.1/tests/win/scrsave.c0000664000175000017500000002776713437077643016074 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Example program showing how to write a Windows screensaver. This * uses a fullscreen DirectX mode when activated normally, or the * GDI interface functions when it is running in preview mode from * inside the Windows screensaver selection dialog. When in * configuration mode, it just uses a standard Windows API dialog. * This also demonstrates how to load, save, and modify the * configuration options. * * Compile this like a normal executable, but rename the output * program to have a .scr extension, and then copy it into your * 'windows/system' directory (or 'winnt/system32' directory under * Windows NT/2000/XP). * * By Shawn Hargreaves. * * Modified by Andrei Ellman to demonstrate loading, saving and * modifying of configuration settings. * * See readme.txt for copyright information. */ #include #include "allegro.h" #include "winalleg.h" #include "scrsave.rh" #define INISETTINGNAME_SHOWBLUECROSS "showbluecross" #define INISETTINGDEFAULT_SHOWBLUECROSS 1 #define INISETTINGNAME_SHOWEXTRATEXT "showextratext" #define INISETTINGDEFAULT_SHOWEXTRATEXT 1 #define INISETTINGNAME_MESSAGE "message" #define INISETTINGDEFAULT_MESSAGE "This message may be changed" #define MAX_MESSAGE_LENGTH 40 int setting_show_blue_cross, setting_show_extra_text; char saver_message[MAX_MESSAGE_LENGTH+1]; BITMAP *buf; int xline; int yline; typedef struct BOUNCER { float x, y; float dx, dy; } BOUNCER; #define NUM_BOUNCERS 3 BOUNCER bouncer[NUM_BOUNCERS]; void set_saver_config(void) { /* Because of the different ways screensavers are invoked from the shell, * we must make absolutely sure we set the INI file to be in the same * directory as the SCR file. set_config_file() is not sufficient in these * circumstances, so we have to set the ABSOLUTE path of the INI file. */ char szPath[512], szINIFile[512]; /* As we are using SYSTEM_NONE as the system driver, we cannot use Allegro's * get_executable_name(). Thankfully, this is a Windows specific program, so * we can get away with the equivalent Windows code below. */ if(GetModuleFileName(NULL, szPath, sizeof(szPath))==0) szPath[0]=0; replace_filename(szINIFile, szPath, "scrsave.ini", 512); set_config_file(szINIFile); } void load_config(void) { set_saver_config(); setting_show_blue_cross = get_config_int(NULL, INISETTINGNAME_SHOWBLUECROSS, INISETTINGDEFAULT_SHOWBLUECROSS); setting_show_extra_text = get_config_int(NULL, INISETTINGNAME_SHOWEXTRATEXT, INISETTINGDEFAULT_SHOWEXTRATEXT); ustrzcpy(saver_message, MAX_MESSAGE_LENGTH+1, get_config_string(NULL, INISETTINGNAME_MESSAGE, INISETTINGDEFAULT_MESSAGE)); } void save_config(void) { set_saver_config(); set_config_int(NULL, INISETTINGNAME_SHOWBLUECROSS, setting_show_blue_cross); set_config_int(NULL, INISETTINGNAME_SHOWEXTRATEXT, setting_show_extra_text); set_config_string(NULL, INISETTINGNAME_MESSAGE, saver_message); } /* initialises our graphical effect */ void ss_init(void) { int i; load_config(); xline = 0; yline = 0; srand(time(NULL)); for (i=0; iw; bouncer[i].y = rand() % buf->h; bouncer[i].dx = 0.5 + (rand() & 255) / 256.0; bouncer[i].dy = 0.5 + (rand() & 255) / 256.0; if ((rand() & 255) < 128) bouncer[i].dx *= -1; if ((rand() & 255) < 128) bouncer[i].dy *= -1; } } /* animates the graphical effect */ void ss_update(void) { int i; xline++; if (xline > buf->w) xline = 0; yline++; if (yline > buf->h) yline = 0; for (i=0; i buf->w)) bouncer[i].dx *= -1; if ((bouncer[i].y < 0) || (bouncer[i].y > buf->h)) bouncer[i].dy *= -1; } } /* draws the graphical effect */ void ss_draw(void) { clear_bitmap(buf); if (setting_show_blue_cross) { line(buf, 0, 0, buf->w, buf->h, makecol(0, 0, 255)); line(buf, buf->w, 0, 0, buf->h, makecol(0, 0, 255)); } vline(buf, xline, 0, buf->h, makecol(255, 0, 0)); hline(buf, 0, yline, buf->w, makecol(0, 255, 0)); textout_centre_ex(buf, font, "Allegro", bouncer[0].x, bouncer[0].y, makecol(0, 128, 255), -1); textout_centre_ex(buf, font, "Screensaver", bouncer[1].x, bouncer[1].y, makecol(255, 128, 0), -1); if (setting_show_extra_text) textout_centre_ex(buf, font, saver_message, bouncer[2].x, bouncer[2].y, makecol(255, 255, 255), -1); } /* shuts down the graphical effect */ void ss_exit(void) { } /* dialog procedure for the settings dialog */ BOOL CALLBACK settings_dlg_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: /* Set up the values for the controls, and grey them out if appropriate. */ SendMessage(GetDlgItem(hwndDlg, IDC_CHECK_BLUECROSS), BM_SETCHECK, (setting_show_blue_cross?BST_CHECKED:BST_UNCHECKED), 0); SendMessage(GetDlgItem(hwndDlg, IDC_CHECK_SHOWMESSAGE), BM_SETCHECK, (setting_show_extra_text?BST_CHECKED:BST_UNCHECKED), 0); SendMessage(GetDlgItem(hwndDlg, IDC_EDIT_MESSAGE), WM_SETTEXT, 0, (LPARAM) ((LPCTSTR) saver_message)); SendMessage(GetDlgItem(hwndDlg, IDC_EDIT_MESSAGE), EM_LIMITTEXT, MAX_MESSAGE_LENGTH, 0); EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_MESSAGE), setting_show_extra_text); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CHECK_SHOWMESSAGE: /* If this checkbox is changed, then we will grey-out the edit-box accordingly. */ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_MESSAGE), (SendMessage(GetDlgItem(hwndDlg, IDC_CHECK_SHOWMESSAGE), BM_GETCHECK, 0, 0)==BST_CHECKED)); return 1; case IDOK: /* Read in the settings from the dialog. */ setting_show_blue_cross = (SendMessage(GetDlgItem(hwndDlg, IDC_CHECK_BLUECROSS), BM_GETCHECK, 0, 0)==BST_CHECKED?1:0); setting_show_extra_text = (SendMessage(GetDlgItem(hwndDlg, IDC_CHECK_SHOWMESSAGE), BM_GETCHECK, 0, 0)==BST_CHECKED?1:0); SendMessage(GetDlgItem(hwndDlg, IDC_EDIT_MESSAGE), WM_GETTEXT, (WPARAM)(MAX_MESSAGE_LENGTH+1), (LPARAM) ((LPCTSTR) saver_message)); /* And now save these settings to the INI file. */ save_config(); EndDialog(hwndDlg, 1); return 1; case IDCANCEL: EndDialog(hwndDlg, 0); return 1; } break; } return 0; } /* the settings dialog function */ int do_settings(HANDLE hInstance, HANDLE hPrevInstance, HWND hParentWnd) { if (install_allegro(SYSTEM_NONE, &errno, atexit) != 0) exit(0); load_config(); DialogBox(hInstance, "ID_CONFIG_DLG", hParentWnd, settings_dlg_proc); return 0; } /* the password dialog function */ int do_password(HANDLE hInstance, HANDLE hPrevInstance, HWND hParentWnd) { /* Load the password change DLL */ HINSTANCE mpr = LoadLibrary(TEXT("MPR.DLL")); if (mpr) { /* Grab the password change function from it */ typedef DWORD (PASCAL *PWCHGPROC)(LPCSTR, HWND, DWORD, LPVOID); PWCHGPROC pwd = (PWCHGPROC)GetProcAddress(mpr, "PwdChangePasswordA"); /* Do the password change */ if ( pwd != NULL ) pwd("SCRSAVE", hParentWnd, 0, NULL); /* Free the library */ FreeLibrary(mpr); mpr=NULL; } return 0; } /* window procedure for the screensaver preview */ LRESULT CALLBACK preview_wnd_proc(HWND hwnd, UINT message, UINT wParam, LONG lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: SetTimer(hwnd, 1, 15, NULL); return 0; case WM_TIMER: ss_update(); InvalidateRect(hwnd, NULL, FALSE); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); ss_draw(); set_palette_to_hdc(hdc, _current_palette); draw_to_hdc(hdc, buf, 0, 0); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: KillTimer(hwnd, 1); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } /* the screensaver preview function */ int do_preview(HANDLE hInstance, HANDLE hPrevInstance, HWND hParentWnd) { WNDCLASS wndclass; HWND hwnd; MSG msg; RECT rc; if (!hPrevInstance) { wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = preview_wnd_proc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "sspreview"; RegisterClass(&wndclass); } if (hParentWnd) GetClientRect(hParentWnd, &rc); else rc.right = rc.bottom = 256; if (install_allegro(SYSTEM_NONE, &errno, atexit) != 0) exit(0); set_palette(default_palette); set_gdi_color_format(); buf = create_bitmap(rc.right, rc.bottom); ss_init(); ss_update(); hwnd = CreateWindow("sspreview", NULL, WS_CHILD, 0, 0, rc.right, rc.bottom, hParentWnd, NULL, hInstance, NULL); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } ss_exit(); destroy_bitmap(buf); return msg.wParam; } /* display switch callback */ static int foreground = TRUE; static void dispsw_callback(void) { foreground = FALSE; } /* run the saver normally, in fullscreen mode */ int do_saver(HANDLE hInstance, HANDLE hPrevInstance, HWND hParentWnd) { HANDLE scrsaver_mutex; int mx, my, t; /* prevent multiple instances from running */ scrsaver_mutex = CreateMutex(NULL, TRUE, "Allegro screensaver"); if (!scrsaver_mutex || (GetLastError() == ERROR_ALREADY_EXISTS)) return -1; if (allegro_init() != 0) return -1; install_keyboard(); install_mouse(); install_timer(); /* try to set a fullscreen mode */ if (set_gfx_mode(GFX_DIRECTX_ACCEL, 640, 480, 0, 0) != 0) if (set_gfx_mode(GFX_DIRECTX_SOFT, 640, 480, 0, 0) != 0) if (set_gfx_mode(GFX_DIRECTX_SAFE, 640, 480, 0, 0) != 0) { ReleaseMutex(scrsaver_mutex); return -1; } set_display_switch_mode(SWITCH_BACKAMNESIA); /* not SWITCH_AMNESIA */ set_display_switch_callback(SWITCH_OUT, dispsw_callback); buf = create_bitmap(SCREEN_W, SCREEN_H); ss_init(); ss_update(); mx = mouse_x; my = mouse_y; t = retrace_count; while (foreground && (!keypressed()) && (!mouse_b) && (mouse_x == mx) && (mouse_y == my)) { while (t < retrace_count) { ss_update(); t++; } ss_draw(); blit(buf, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); poll_mouse(); } ss_exit(); destroy_bitmap(buf); ReleaseMutex(scrsaver_mutex); return 0; } /* the main program body */ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { HWND hwnd; char *args; args = lpszCmdParam; if ((args[0] == '-') || (args[0] == '/')) args++; if ((args[0]) && ((args[1] == ' ') || (args[1] == ':'))) hwnd = (HWND)atoi(args+2); else hwnd = GetActiveWindow(); switch (utolower(args[0])) { case 'c': return do_settings(hInstance, hPrevInstance, hwnd); case 'a': return do_password(hInstance, hPrevInstance, hwnd); case 'p': return do_preview(hInstance, hPrevInstance, hwnd); case 's': return do_saver(hInstance, hPrevInstance, hwnd); } return 0; } allegro-4.4.3.1/tests/win/dxwindow.rh0000664000175000017500000000046613437077643016443 0ustar siegesiege// Windows resource header file for the dxwindow example #define CMD_FILE_RUN 100 #define CMD_FILE_STOP 101 #define CMD_FILE_EXIT 102 #define CMD_SET_SPEED_UP 103 #define CMD_SET_SPEED_DOWN 104 #define CMD_SET_SPEED_DEFAULT 105 #define CMD_HELP_ABOUT 106 allegro-4.4.3.1/tests/win/dibgrab.c0000664000175000017500000001047713437077643016006 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Example program showing how to read and write Allegro format * bitmaps from a GDI device context. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include "allegro.h" #include "winalleg.h" #define GRAB_W 64 #define GRAB_H 64 BITMAP *grab_region = NULL; int captured = FALSE; POINT location; PALETTE pal; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam) { HWND dwnd; HDC hdc, ddc; PAINTSTRUCT ps; RECT rc, sz; OPENFILENAME fn; char filename[256]; switch (message) { case WM_PAINT: if (GetUpdateRect(hwnd, &rc, FALSE)) { hdc = BeginPaint(hwnd, &ps); set_palette_to_hdc(hdc, default_palette); if (captured) { dwnd = GetDesktopWindow(); ddc = GetDC(dwnd); GetWindowRect(dwnd, &sz); location.x = MIN(location.x, sz.right-GRAB_W); location.y = MIN(location.y, sz.bottom-GRAB_W); blit_from_hdc(ddc, grab_region, location.x, location.y, 0, 0, GRAB_W, GRAB_H); ReleaseDC(dwnd, ddc); GetClientRect(hwnd, &sz); stretch_blit_to_hdc(grab_region, hdc, 0, 0, GRAB_W, GRAB_H, 0, 0, sz.right, sz.bottom); } else { FillRect(hdc, &rc, GetStockObject(WHITE_BRUSH)); TextOut(hdc, 8, 8, "Click here, then drag over desktop", 34); } EndPaint(hwnd, &ps); } return 0; case WM_LBUTTONDOWN: if (!captured) { SetCapture(hwnd); captured = TRUE; location.x = (short)(lParam & 0xFFFF); location.y = (short)(lParam >> 16); ClientToScreen(hwnd, &location); InvalidateRect(hwnd, NULL, FALSE); } return 0; case WM_LBUTTONUP: if (captured) { ReleaseCapture(); captured = FALSE; InvalidateRect(hwnd, NULL, FALSE); memset(&fn, 0, sizeof(fn)); fn.lStructSize = sizeof(fn); fn.hwndOwner = hwnd; fn.lpstrFilter = "Bitmap Files (*.bmp;*.pcx;*.tga)\0*.bmp;*.pcx;*.tga\0All Files (*.*)\0*.*\0"; fn.lpstrFile = filename; fn.nMaxFile = sizeof(filename); fn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; filename[0] = 0; if (GetSaveFileName(&fn)) { if (save_bitmap(filename, grab_region, pal) != 0) MessageBox(hwnd, "Error saving bitmap file", NULL, MB_OK); } } return 0; case WM_MOUSEMOVE: if (captured) { location.x = (short)(lParam & 0xFFFF); location.y = (short)(lParam >> 16); ClientToScreen(hwnd, &location); InvalidateRect(hwnd, NULL, FALSE); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { static char szAppName[] = "Magnificator"; WNDCLASS wndclass; HWND hwnd; MSG msg; if (!hPrevInstance) { wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; RegisterClass(&wndclass); } hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 256, 256, NULL, NULL, hInstance, NULL); if (install_allegro(SYSTEM_NONE, &errno, atexit) != 0) exit(0); set_gdi_color_format(); grab_region = create_bitmap_ex(32, GRAB_W, GRAB_H); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } destroy_bitmap(grab_region); return msg.wParam; } allegro-4.4.3.1/tests/test.c0000664000175000017500000033311413437077643014572 0ustar siegesiege/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Main test program for the Allegro library. * * By Shawn Hargreaves. * * See readme.txt for copyright information. */ #include #include #include #include #include "allegro.h" int gfx_card = GFX_AUTODETECT; int gfx_w = 640; int gfx_h = 480; int gfx_bpp = 8; int gfx_rate = 0; int mode = DRAW_MODE_SOLID; char mode_string[80]; #define CHECK_TRANS_BLENDER() \ if (bitmap_color_depth(screen) > 8) \ set_trans_blender(0, 0, 0, 0x40); #define TIME_SPEED 2 BITMAP *global_sprite = NULL; RLE_SPRITE *global_rle_sprite = NULL; COMPILED_SPRITE *global_compiled_sprite = NULL; BITMAP *realscreen = NULL; PALETTE mypal; #define NUM_PATTERNS 8 BITMAP *pattern[NUM_PATTERNS]; int cpu_has_capabilities = 0; int type3d = POLYTYPE_FLAT; char allegro_version_str[120]; char internal_version_str[80]; char gfx_specs[80]; char gfx_specs2[80]; char gfx_specs3[80]; char mouse_specs[80]; char cpu_specs[120]; char buf[160]; int xoff, yoff; long tm = 0; /* counter, incremented once a second */ volatile int _tm = 0; /* volatile so we can try to sync to the timer */ long ct; #define SHOW_TIME_MACRO() \ if (ct >= 0) { \ if (tm >= TIME_SPEED) { \ if (profile) \ return; \ show_time(ct, screen, 16); \ /* sync to timer */ \ _tm = 0; \ while (_tm < 2) ; \ ct = 0; \ tm = 0; \ _tm = 0; \ } \ else \ ct++; \ } int profile = FALSE; COLOR_MAP *trans_map = NULL; COLOR_MAP *light_map = NULL; void tm_tick(void) { if (++_tm >= 100) { _tm = 0; tm++; if (realscreen) blit(screen, realscreen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); } } END_OF_FUNCTION(tm_tick) void show_time(long t, BITMAP *bmp, int y) { int s, x1, y1, x2, y2; get_clip_rect(bmp, &x1, &y1, &x2, &y2); s = get_clip_state(bmp); sprintf(buf, " %ld per second ", t / TIME_SPEED); set_clip_rect(bmp, 0, 0, SCREEN_W-1, SCREEN_H-1); set_clip_state(bmp, TRUE); textout_centre_ex(bmp, font, buf, SCREEN_W/2, y, palette_color[15], palette_color[0]); set_clip_rect(bmp, x1, y1, x2, y2); set_clip_state(bmp, s); } void message(char *s) { textout_centre_ex(screen, font, s, SCREEN_W/2, 6, palette_color[15], palette_color[0]); if (!profile) textout_centre_ex(screen, font, "Press a key or mouse button", SCREEN_W/2, SCREEN_H-10, palette_color[15], palette_color[0]); } int next(void) { if (keypressed()) { clear_keybuf(); return TRUE; } poll_mouse(); if (mouse_b) { do { poll_mouse(); } while (mouse_b); return TRUE; } return FALSE; } BITMAP *make_sprite(void) { BITMAP *b; solid_mode(); b = create_bitmap(32, 32); clear_to_color(b, bitmap_mask_color(b)); circlefill(b, 16, 16, 8, palette_color[2]); circle(b, 16, 16, 8, palette_color[1]); line(b, 0, 0, 31, 31, palette_color[3]); line(b, 31, 0, 0, 31, palette_color[3]); textout_ex(b, font, "Test", 1, 12, palette_color[15], -1); return b; } int check_tables(void) { if (bitmap_color_depth(screen) > 8) { set_trans_blender(0, 0, 0, 128); } else if ((!rgb_map) || (!trans_map) || (!light_map)) { if (!rgb_map) { rgb_map = malloc(sizeof(RGB_MAP)); create_rgb_table(rgb_map, mypal, NULL); } if (!trans_map) { trans_map = malloc(sizeof(COLOR_MAP)); create_trans_table(trans_map, mypal, 96, 96, 96, NULL); } if (!light_map) { light_map = malloc(sizeof(COLOR_MAP)); create_light_table(light_map, mypal, 0, 0, 0, NULL); } color_map = trans_map; return D_REDRAW; } return D_O_K; } void make_patterns(void) { int c; pattern[0] = create_bitmap(2, 2); clear_to_color(pattern[0], bitmap_mask_color(pattern[0])); putpixel(pattern[0], 0, 0, palette_color[255]); pattern[1] = create_bitmap(2, 2); clear_to_color(pattern[1], bitmap_mask_color(pattern[1])); putpixel(pattern[1], 0, 0, palette_color[255]); putpixel(pattern[1], 1, 1, palette_color[255]); pattern[2] = create_bitmap(4, 4); clear_to_color(pattern[2], bitmap_mask_color(pattern[2])); vline(pattern[2], 0, 0, 4, palette_color[255]); hline(pattern[2], 0, 0, 4, palette_color[255]); pattern[3] = create_bitmap(4, 4); clear_to_color(pattern[3], bitmap_mask_color(pattern[3])); line(pattern[3], 0, 3, 3, 0, palette_color[255]); pattern[4] = create_bitmap(8, 8); clear_to_color(pattern[4], bitmap_mask_color(pattern[4])); for (c=0; c<16; c+=2) circle(pattern[4], 4, 4, c, palette_color[c]); pattern[5] = create_bitmap(8, 8); clear_to_color(pattern[5], bitmap_mask_color(pattern[5])); for (c=0; c<8; c++) hline(pattern[5], 0, c, 8, palette_color[c]); pattern[6] = create_bitmap(8, 8); clear_to_color(pattern[6], bitmap_mask_color(pattern[6])); circle(pattern[6], 0, 4, 3, palette_color[2]); circle(pattern[6], 8, 4, 3, palette_color[2]); circle(pattern[6], 4, 0, 3, palette_color[1]); circle(pattern[6], 4, 8, 3, palette_color[1]); pattern[7] = create_bitmap(64, 8); clear_to_color(pattern[7], bitmap_mask_color(pattern[7])); textout_ex(pattern[7], font, "PATTERN!", 0, 0, palette_color[255], bitmap_mask_color(pattern[7])); } void getpix_demo(void) { int c, ox, oy; scare_mouse(); acquire_screen(); clear_to_color(screen, palette_color[0]); message("getpixel test"); for (c=0; c<16; c++) rectfill(screen, xoff+100+((c&3)<<5), yoff+50+((c>>2)<<5), xoff+120+((c&3)<<5), yoff+70+((c>>2)<<5), palette_color[c]); release_screen(); unscare_mouse(); ox = -1; oy = -1; while (!next()) { rest(1); poll_mouse(); if ((mouse_x != ox) || (mouse_y != oy)) { ox = mouse_x; oy = mouse_y; scare_mouse(); acquire_screen(); c = getpixel(screen, ox-2, oy-2); sprintf(buf, " %X ", c); textout_centre_ex(screen, font, buf, SCREEN_W/2, yoff+24, palette_color[15], palette_color[0]); release_screen(); unscare_mouse(); } } } void putpix_test(int xpos, int ypos) { int c, x, y; for (c=0; c<16; c++) for (x=0; x<16; x+=2) for (y=0; y<16; y+=2) putpixel(screen, xpos+((c&3)<<4)+x, ypos+((c>>2)<<4)+y, palette_color[c]); } void hline_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) hline(screen, xpos+48-c*3, ypos+c*3, xpos+48+c*3, palette_color[c]); } void vline_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) vline(screen, xpos+c*4, ypos+36-c*3, ypos+36+c*3, palette_color[c]); } void line_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) { line(screen, xpos+32, ypos+32, xpos+32+((c-8)<<2), ypos, palette_color[c%15+1]); line(screen, xpos+32, ypos+32, xpos+32-((c-8)<<2), ypos+64, palette_color[c%15+1]); line(screen, xpos+32, ypos+32, xpos, ypos+32-((c-8)<<2), palette_color[c%15+1]); line(screen, xpos+32, ypos+32, xpos+64, ypos+32+((c-8)<<2), palette_color[c%15+1]); } } void rectfill_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) rectfill(screen, xpos+((c&3)*17), ypos+((c>>2)*17), xpos+15+((c&3)*17), ypos+15+((c>>2)*17), palette_color[c]); } void triangle_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) triangle(screen, xpos+22+((c&3)<<4), ypos+15+((c>>2)<<4), xpos+13+((c&3)<<3), ypos+7+((c>>2)<<4), xpos+7+((c&3)<<4), ypos+27+((c>>2)<<3), palette_color[c]); } void circle_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) circle(screen, xpos+32, ypos+32, c*2, palette_color[c%15+1]); } void circlefill_test(int xpos, int ypos) { int c; for (c=15; c>=0; c--) circlefill(screen, xpos+8+((c&3)<<4), ypos+8+((c>>2)<<4), c, palette_color[c%15+1]); } void ellipse_test(int xpos, int ypos) { int c; for (c=15; c>=0; c--) ellipse(screen, xpos+8+((c&3)<<4), ypos+8+((c>>2)<<4), (16-c)*2, (c+1)*2, palette_color[c%15+1]); } void ellipsefill_test(int xpos, int ypos) { int c; for (c=15; c>=0; c--) ellipsefill(screen, xpos+8+((c&3)<<4), ypos+8+((c>>2)<<4), (16-c)*2, (c+1)*2, palette_color[c%15+1]); } void arc_test(int xpos, int ypos) { int c; for (c=0; c<16; c++) arc(screen, xpos+32, ypos+32, itofix(c*12), itofix(64+c*16), c*2, palette_color[c%15+1]); } void textout_test(int xpos, int ypos) { textout_ex(screen, font,"This is a", xpos-8, ypos, palette_color[1], palette_color[0]); textout_ex(screen, font,"test of the", xpos+3, ypos+10, palette_color[1], palette_color[0]); textout_ex(screen, font,"textout", xpos+14, ypos+20, palette_color[1], palette_color[0]); textout_ex(screen, font,"function.", xpos+25, ypos+30, palette_color[1], palette_color[0]); textout_ex(screen, font,"solid background", xpos, ypos+48, palette_color[2], palette_color[0]); textout_ex(screen, font,"solid background", xpos+4, ypos+52, palette_color[4], palette_color[0]); textout_ex(screen, font,"transparent background", xpos, ypos+68, palette_color[2], -1); textout_ex(screen, font,"transparent background", xpos+4, ypos+72, palette_color[4], -1); } void sprite_test(int xpos, int ypos) { int x,y; for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) for (y=6; y<64; y+=global_sprite->w+6) draw_sprite(screen, global_sprite, xpos+x, ypos+y); } void xlu_sprite_test(int xpos, int ypos) { int x,y; solid_mode(); for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) { for (y=6; y<64; y+=global_sprite->w+6) { set_trans_blender(0, 0, 0, x+y*3); draw_trans_sprite(screen, global_sprite, xpos+x, ypos+y); } } } void lit_sprite_test(int xpos, int ypos) { int x,y; solid_mode(); for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) { for (y=6; y<64; y+=global_sprite->w+6) { set_trans_blender(x*4, (x+y)*2, y*4, 0); draw_lit_sprite(screen, global_sprite, xpos+x, ypos+y, ((x*2+y)*5)&0xFF); } } } void rle_xlu_sprite_test(int xpos, int ypos) { int x,y; solid_mode(); for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) { for (y=6; y<64; y+=global_sprite->w+6) { set_trans_blender(0, 0, 0, x+y*3); draw_trans_rle_sprite(screen, global_rle_sprite, xpos+x, ypos+y); } } } void rle_lit_sprite_test(int xpos, int ypos) { int x,y; solid_mode(); for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) { for (y=6; y<64; y+=global_sprite->w+6) { set_trans_blender(x*4, (x+y)*2, y*4, 0); draw_lit_rle_sprite(screen, global_rle_sprite, xpos+x, ypos+y, ((x*2+y)*5)&0xFF); } } } void rle_sprite_test(int xpos, int ypos) { int x,y; for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) for (y=6; y<64; y+=global_sprite->w+6) draw_rle_sprite(screen, global_rle_sprite, xpos+x, ypos+y); } void compiled_sprite_test(int xpos, int ypos) { int x,y; for (y=0;y<82;y++) for (x=0;x<82;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); for (x=6; x<64; x+=global_sprite->w+6) for (y=6; y<64; y+=global_sprite->w+6) draw_compiled_sprite(screen, global_compiled_sprite, xpos+x, ypos+y); } void flipped_sprite_test(int xpos, int ypos) { int x, y; for (y=0;y<88;y++) for (x=0;x<88;x+=2) putpixel(screen, xpos+x+(y&1), ypos+y, palette_color[8]); draw_sprite(screen, global_sprite, xpos+8, ypos+8); draw_sprite_h_flip(screen, global_sprite, xpos+48, ypos+8); draw_sprite_v_flip(screen, global_sprite, xpos+8, ypos+48); draw_sprite_vh_flip(screen, global_sprite, xpos+48, ypos+48); } void putpix_demo(void) { int c = 0; int x, y; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 255) + 32; y = (AL_RAND() & 127) + 40; putpixel(screen, xoff+x, yoff+y, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void hline_demo(void) { int c = 0; int x1, x2, y; tm = 0; _tm = 0; ct = 0; while (!next()) { x1 = (AL_RAND() & 255) + 32; x2 = (AL_RAND() & 255) + 32; y = (AL_RAND() & 127) + 40; hline(screen, xoff+x1, yoff+y, xoff+x2, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void vline_demo(void) { int c = 0; int x, y1, y2; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 255) + 32; y1 = (AL_RAND() & 127) + 40; y2 = (AL_RAND() & 127) + 40; vline(screen, xoff+x, yoff+y1, yoff+y2, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void line_demo(void) { int c = 0; int x1, y1, x2, y2; tm = 0; _tm = 0; ct = 0; while (!next()) { x1 = (AL_RAND() & 255) + 32; x2 = (AL_RAND() & 255) + 32; y1 = (AL_RAND() & 127) + 40; y2 = (AL_RAND() & 127) + 40; line(screen, xoff+x1, yoff+y1, xoff+x2, yoff+y2, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void rectfill_demo(void) { int c = 0; int x1, y1, x2, y2; tm = 0; _tm = 0; ct = 0; while (!next()) { x1 = (AL_RAND() & 255) + 32; y1 = (AL_RAND() & 127) + 40; x2 = (AL_RAND() & 255) + 32; y2 = (AL_RAND() & 127) + 40; rectfill(screen, xoff+x1, yoff+y1, xoff+x2, yoff+y2, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void triangle_demo(void) { int c = 0; int x1, y1, x2, y2, x3, y3; tm = 0; _tm = 0; ct = 0; while (!next()) { x1 = (AL_RAND() & 255) + 32; x2 = (AL_RAND() & 255) + 32; x3 = (AL_RAND() & 255) + 32; y1 = (AL_RAND() & 127) + 40; y2 = (AL_RAND() & 127) + 40; y3 = (AL_RAND() & 127) + 40; triangle(screen, xoff+x1, yoff+y1, xoff+x2, yoff+y2, xoff+x3, yoff+y3, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void triangle3d_demo(void) { V3D v1, v2, v3; int x0 = xoff+32; int y0 = yoff+40; v1.u = 0; v1.v = 0; v2.u = itofix(32); v2.v = 0; v3.u = 0; v3.v = itofix(32); tm = _tm = 0; ct = 0; while (!next()) { v1.x = itofix((AL_RAND() & 255) + x0); v2.x = itofix((AL_RAND() & 255) + x0); v3.x = itofix((AL_RAND() & 255) + x0); v1.y = itofix((AL_RAND() & 127) + y0); v2.y = itofix((AL_RAND() & 127) + y0); v3.y = itofix((AL_RAND() & 127) + y0); v1.z = itofix((AL_RAND() & 127) + 400); v2.z = itofix((AL_RAND() & 127) + 400); v3.z = itofix((AL_RAND() & 127) + 400); if ((type3d == POLYTYPE_ATEX_LIT) || (type3d == POLYTYPE_PTEX_LIT) || (type3d == POLYTYPE_ATEX_MASK_LIT) || (type3d == POLYTYPE_PTEX_MASK_LIT)) { v1.c = AL_RAND() & 255; v2.c = AL_RAND() & 255; v3.c = AL_RAND() & 255; } else { v1.c = palette_color[AL_RAND() & 255]; v2.c = palette_color[AL_RAND() & 255]; v3.c = palette_color[AL_RAND() & 255]; } triangle3d(screen, type3d, pattern[AL_RAND()%NUM_PATTERNS], &v1, &v2, &v3); SHOW_TIME_MACRO(); } ct = -1; } void circle_demo(void) { int c = 0; int x, y, r; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 127) + 92; y = (AL_RAND() & 63) + 76; r = (AL_RAND() & 31) + 16; circle(screen, xoff+x, yoff+y, r, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void circlefill_demo(void) { int c = 0; int x, y, r; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 127) + 92; y = (AL_RAND() & 63) + 76; r = (AL_RAND() & 31) + 16; circlefill(screen, xoff+x, yoff+y, r, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void ellipse_demo(void) { int c = 0; int x, y, rx, ry; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 127) + 92; y = (AL_RAND() & 63) + 76; rx = (AL_RAND() & 31) + 16; ry = (AL_RAND() & 31) + 16; ellipse(screen, xoff+x, yoff+y, rx, ry, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void ellipsefill_demo(void) { int c = 0; int x, y, rx, ry; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 127) + 92; y = (AL_RAND() & 63) + 76; rx = (AL_RAND() & 31) + 16; ry = (AL_RAND() & 31) + 16; ellipsefill(screen, xoff+x, yoff+y, rx, ry, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void arc_demo(void) { int c = 0; int x, y, r; fixed a1, a2; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 127) + 92; y = (AL_RAND() & 63) + 76; r = (AL_RAND() & 31) + 16; a1 = (AL_RAND() & 0xFF) << 16; a2 = (AL_RAND() & 0xFF) << 16; arc(screen, xoff+x, yoff+y, a1, a2, r, palette_color[c]); if (mode >= DRAW_MODE_COPY_PATTERN) drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void textout_demo(void) { int c = 0; int x, y; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & 127) + 40; y = (AL_RAND() & 127) + 40; textout_ex(screen, font, "textout test", xoff+x, yoff+y, palette_color[c], palette_color[0]); if (++c >= 16) c = 0; SHOW_TIME_MACRO(); } ct = -1; } void sprite_demo(void) { int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; draw_sprite(screen, global_sprite, xoff+x, yoff+y); SHOW_TIME_MACRO(); } ct = -1; } void xlu_sprite_demo(void) { int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; if (bitmap_color_depth(screen) > 8) set_trans_blender(0, 0, 0, AL_RAND()&0x7F); draw_trans_sprite(screen, global_sprite, xoff+x, yoff+y); SHOW_TIME_MACRO(); } ct = -1; } void lit_sprite_demo(void) { int c = 1; int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; if (bitmap_color_depth(screen) > 8) set_trans_blender(AL_RAND()&0xFF, AL_RAND()&0xFF, AL_RAND()&0xFF, 0); draw_lit_sprite(screen, global_sprite, xoff+x, yoff+y, c); c = (c+13) & 0xFF; SHOW_TIME_MACRO(); } ct = -1; } void rle_xlu_sprite_demo(void) { int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; if (bitmap_color_depth(screen) > 8) set_trans_blender(0, 0, 0, AL_RAND()&0x7F); draw_trans_rle_sprite(screen, global_rle_sprite, xoff+x, yoff+y); SHOW_TIME_MACRO(); } ct = -1; } void rle_lit_sprite_demo(void) { int c = 1; int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; if (bitmap_color_depth(screen) > 8) set_trans_blender(AL_RAND()&0xFF, AL_RAND()&0xFF, AL_RAND()&0xFF, 0); draw_lit_rle_sprite(screen, global_rle_sprite, xoff+x, yoff+y, c); c = (c+13) & 0xFF; SHOW_TIME_MACRO(); } ct = -1; } void rle_sprite_demo(void) { int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; draw_rle_sprite(screen, global_rle_sprite, xoff+x, yoff+y); SHOW_TIME_MACRO(); } ct = -1; } void compiled_sprite_demo(void) { int x, y; int xand = (SCREEN_W >= 320) ? 255 : 127; int xadd = (SCREEN_W >= 320) ? 16 : 80; tm = 0; _tm = 0; ct = 0; while (!next()) { x = (AL_RAND() & xand) + xadd; y = (AL_RAND() & 127) + 30; draw_compiled_sprite(screen, global_compiled_sprite, xoff+x, yoff+y); SHOW_TIME_MACRO(); } ct = -1; } int blit_from_screen = FALSE; int blit_align = FALSE; int blit_mask = FALSE; void blit_demo(void) { int x, y; int sx, sy; BITMAP *b; solid_mode(); b = create_bitmap(64, 32); if (!b) { clear_to_color(screen, palette_color[0]); textout_ex(screen, font, "Out of memory!", 50, 50, palette_color[15], palette_color[0]); destroy_bitmap(b); while (!next()) ; return; } clear_to_color(b, (blit_mask ? bitmap_mask_color(b) : palette_color[0])); circlefill(b, 32, 16, 16, palette_color[4]); circlefill(b, 32, 16, 10, palette_color[2]); circlefill(b, 32, 16, 6, palette_color[1]); line(b, 0, 0, 63, 31, palette_color[3]); line(b, 0, 31, 63, 0, palette_color[3]); rect(b, 8, 4, 56, 28, palette_color[3]); rect(b, 0, 0, 63, 31, palette_color[15]); tm = 0; _tm = 0; ct = 0; sx = ((SCREEN_W-64) / 2) & 0xFFFC; sy = yoff + 32; if (blit_from_screen) blit(b, screen, 0, 0, sx, sy, 64, 32); while (!next()) { x = (AL_RAND() & 127) + 60; y = (AL_RAND() & 63) + 50; if (blit_align) x &= 0xFFFC; if (blit_from_screen) { if (blit_mask) masked_blit(screen, screen, sx, sy, xoff+x, yoff+y+24, 64, 32); else blit(screen, screen, sx, sy, xoff+x, yoff+y+24, 64, 32); } else { if (blit_mask) masked_blit(b, screen, 0, 0, xoff+x, yoff+y, 64, 32); else blit(b, screen, 0, 0, xoff+x, yoff+y, 64, 32); } SHOW_TIME_MACRO(); } destroy_bitmap(b); ct = -1; } void misc(void) { BITMAP *p; volatile fixed x, y, z; volatile float fx, fy, fz; clear_to_color(screen, palette_color[0]); textout_ex(screen,font,"Timing some other routines...", xoff+44, 6, palette_color[15], palette_color[0]); p = create_bitmap(320, 200); if (!p) textout_ex(screen,font,"Out of memory!", 16, 50, palette_color[15], palette_color[0]); else { tm = 0; _tm = 0; ct = 0; do { clear_bitmap(p); ct++; if (next()) return; } while (tm < TIME_SPEED); destroy_bitmap(p); sprintf(buf,"clear_bitmap(320x200): %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+15, palette_color[15], palette_color[0]); } x = y = z = 0; tm = 0; _tm = 0; ct = 0; do { z += fixmul(x,y); x += 1317; y += 7143; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixmul(): %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+25, palette_color[15], palette_color[0]); fx = fy = fz = 0; tm = 0; _tm = 0; ct = 0; do { fz += fx * fy; fx += 1317; fy += 7143; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "float *: %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+35, palette_color[15], palette_color[0]); x = y = 0; tm = 0; _tm = 0; ct = 0; do { z += fixdiv(x,y); x += 1317; y += 7143; if (y==0) y++; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixdiv(): %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+45, palette_color[15], palette_color[0]); fx = fy = 1; tm = 0; _tm = 0; ct = 0; do { fz += fx / fy; fx += 1317; fy += 7143; if (fy==0) fy++; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "float /: %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+55, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixsqrt(x); x += 7361; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixsqrt(): %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+65, palette_color[15], palette_color[0]); fx = 1; tm = 0; _tm = 0; ct = 0; do { fy += sqrt(fx); fx += 7361; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "libc sqrtf(): %ld per second", ct/TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+75, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixsin(x); x += 4283; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixsin(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+85, palette_color[15], palette_color[0]); fx = 1; tm = 0; _tm = 0; ct = 0; do { fy += sin(fx); fx += 4283; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "libc sin(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+95, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixcos(x); x += 4283; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixcos(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+105, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixtan(x); x += 8372; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixtan(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+115, palette_color[15], palette_color[0]); fx = 1; tm = 0; _tm = 0; ct = 0; do { fy += tan(fx); fx += 8372; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "libc tan(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+125, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixasin(x); x += 5621; x &= 0xffff; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixasin(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+135, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixacos(x); x += 5621; x &= 0xffff; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf,"fixacos(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+145, palette_color[15], palette_color[0]); x = 1; tm = 0; _tm = 0; ct = 0; do { y += fixatan(x); x += 7358; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixatan(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+155, palette_color[15], palette_color[0]); fx = 1; tm = 0; _tm = 0; ct = 0; do { fy += atan(fx); fx += 7358; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "libc atan(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+165, palette_color[15], palette_color[0]); x = 1, y = 2; tm = 0; _tm = 0; ct = 0; do { z += fixatan2(x, y); x += 5621; y += 7335; ct++; if (next()) return; } while (tm < TIME_SPEED); sprintf(buf, "fixatan2(): %ld per second", ct / TIME_SPEED); textout_ex(screen, font, buf, xoff+16, yoff+175, palette_color[15], palette_color[0]); textout_ex(screen, font, "Press a key or mouse button", xoff+52, SCREEN_H-10, palette_color[15], palette_color[0]); while (!next()) ; } void rainbow(void) { char buf[80]; int x, y; int r, g, b; float h, s, v, c; acquire_screen(); clear_to_color(screen, palette_color[0]); sprintf(buf, "%d bit color...", bitmap_color_depth(screen)); textout_centre_ex(screen, font, buf, SCREEN_W/2, 6, palette_color[15], palette_color[0]); for (h=0; h<360; h+=0.25) { for (c=0; c<1; c+=0.005) { s = 1.0-ABS(1.0-c*2); v = MIN(c*2, 1.0); x = cos(h*3.14159/180.0)*c*128.0; y = sin(h*3.14159/180.0)*c*128.0; hsv_to_rgb(h, s, v, &r, &g, &b); putpixel(screen, SCREEN_W/2+x, SCREEN_H/2+y, makecol(r, g, b)); } } textout_ex(screen, font, "Press a key or mouse button", xoff+52, SCREEN_H-10, palette_color[15], palette_color[0]); release_screen(); while (!next()) ; } static void caps(void) { static char *s[] = { "(scroll)", "(triple buffer)", "(hardware cursor)", "solid hline:", "xor hline:", "solid/masked pattern hline:", "copy pattern hline:", "solid fill:", "xor fill:", "solid/masked pattern fill:", "copy pattern fill:", "solid line:", "xor line:", "solid triangle:", "xor triangle:", "mono text:", "vram->vram blit:", "masked vram->vram blit:", "mem->screen blit:", "masked mem->screen blit:", "system->screen blit:", "masked system->screen blit:", "Mouse pointer:", "stretch vram->vram blit:", "masked stretch vram->vram blit:", "stretch system->vram blit:", "masked stretch system->vram blit:", NULL }; int c; acquire_screen(); clear_to_color(screen, palette_color[0]); textout_ex(screen,font,"Hardware accelerated features", xoff+44, 6, palette_color[15], palette_color[0]); for (c=3; s[c]; c++) { textout_ex(screen, font, s[c], SCREEN_W/2+64-text_length(font, s[c]), SCREEN_H/2-184+c*16, palette_color[15], palette_color[0]); textout_ex(screen, font, (gfx_capabilities & (1<= 16) int_c1 = 0; } END_OF_FUNCTION(int1) void int2(void) { if (++int_c2 >= 16) int_c2 = 0; } END_OF_FUNCTION(int2) void int3(void) { if (++int_c3 >= 16) int_c3 = 0; } END_OF_FUNCTION(int3) void interrupt_test(void) { clear_to_color(screen, palette_color[0]); message("Timer interrupt test"); textout_ex(screen,font,"1/4", xoff+108, yoff+78, palette_color[15], palette_color[0]); textout_ex(screen,font,"1", xoff+156, yoff+78, palette_color[15], palette_color[0]); textout_ex(screen,font,"5", xoff+196, yoff+78, palette_color[15], palette_color[0]); LOCK_VARIABLE(int_c1); LOCK_VARIABLE(int_c2); LOCK_VARIABLE(int_c3); LOCK_FUNCTION(int1); LOCK_FUNCTION(int2); LOCK_FUNCTION(int3); install_int(int1, 250); install_int(int2, 1000); install_int(int3, 5000); while (!next()) { rectfill(screen, xoff+110, yoff+90, xoff+130, yoff+110, palette_color[int_c1]); rectfill(screen, xoff+150, yoff+90, xoff+170, yoff+110, palette_color[int_c2]); rectfill(screen, xoff+190, yoff+90, xoff+210, yoff+110, palette_color[int_c3]); rest(1); } remove_int(int1); remove_int(int2); remove_int(int3); } int fade_color = 63; void fade(void) { RGB rgb; rgb.r = rgb.g = rgb.b = (fade_color < 64) ? fade_color : 127 - fade_color; rgb.filler = 0; _set_color(0, &rgb); fade_color++; if (fade_color >= 128) fade_color = 0; } END_OF_FUNCTION(fade) void rotate_test(void) { fixed c = 0; BITMAP *b; BITMAP *new_sprite; solid_mode(); new_sprite = create_bitmap(33, 33); clear_to_color(new_sprite, bitmap_mask_color(new_sprite)); circlefill(new_sprite, 16, 16, 9, palette_color[2]); circle(new_sprite, 16, 16, 9, palette_color[1]); line(new_sprite, 0, 0, 32, 32, palette_color[3]); line(new_sprite, 32, 0, 0, 32, palette_color[3]); textout_ex(new_sprite, font, "Test", 1, 12, palette_color[15], -1); set_clip_rect(screen, 0, 0, VIRTUAL_W-1, VIRTUAL_H-1); clear_to_color(screen, palette_color[0]); message("Bitmap rotation test"); b = create_bitmap(33, 33); draw_sprite(screen, new_sprite, SCREEN_W/2-16-33, SCREEN_H/2-16-33); draw_sprite(screen, new_sprite, SCREEN_W/2-16-66, SCREEN_H/2-16-66); draw_sprite_v_flip(screen, new_sprite, SCREEN_W/2-16-33, SCREEN_H/2-16+33); draw_sprite_v_flip(screen, new_sprite, SCREEN_W/2-16-66, SCREEN_H/2-16+66); draw_sprite_h_flip(screen, new_sprite, SCREEN_W/2-16+33, SCREEN_H/2-16-33); draw_sprite_h_flip(screen, new_sprite, SCREEN_W/2-16+66, SCREEN_H/2-16-66); draw_sprite_vh_flip(screen, new_sprite, SCREEN_W/2-16+33, SCREEN_H/2-16+33); draw_sprite_vh_flip(screen, new_sprite, SCREEN_W/2-16+66, SCREEN_H/2-16+66); tm = 0; _tm = 0; ct = 0; while (!next()) { clear_to_color(b, palette_color[0]); rotate_sprite(b, new_sprite, 0, 0, c); blit(b, screen, 0, 0, SCREEN_W/2-16, SCREEN_H/2-16, b->w, b->h); c += itofix(1) / 16; SHOW_TIME_MACRO(); } destroy_bitmap(new_sprite); destroy_bitmap(b); } void stretch_test(void) { BITMAP *b; int c; set_clip_rect(screen, 0, 0, VIRTUAL_W-1, VIRTUAL_H-1); clear_to_color(screen, palette_color[0]); message("Bitmap scaling test"); tm = 0; _tm = 0; ct = 0; c = 1; rect(screen, SCREEN_W/2-128, SCREEN_H/2-64, SCREEN_W/2+128, SCREEN_H/2+64, palette_color[15]); set_clip_rect(screen, SCREEN_W/2-127, SCREEN_H/2-63, SCREEN_W/2+127, SCREEN_H/2+63); solid_mode(); b = create_bitmap(32, 32); clear_to_color(b, palette_color[0]); circlefill(b, 16, 16, 8, palette_color[2]); circle(b, 16, 16, 8, palette_color[1]); line(b, 0, 0, 31, 31, palette_color[3]); line(b, 31, 0, 0, 31, palette_color[3]); textout_ex(b, font, "Test", 1, 12, palette_color[15], -1); while (!next()) { stretch_blit(b, screen, 0, 0, 32, 32, SCREEN_W/2-c, SCREEN_H/2-(256-c), c*2, (256-c)*2); if (c >= 255) { c = 1; rectfill(screen, SCREEN_W/2-127, SCREEN_H/2-63, SCREEN_W/2+127, SCREEN_H/2+63, palette_color[0]); } else c++; SHOW_TIME_MACRO(); } destroy_bitmap(b); } void hscroll_test(void) { int x, y; int done = FALSE; int ox = mouse_x; int oy = mouse_y; set_clip_rect(screen, 0, 0, VIRTUAL_W-1, VIRTUAL_H-1); clear_to_color(screen, palette_color[0]); rect(screen, 0, 0, VIRTUAL_W-1, VIRTUAL_H-1, palette_color[15]); for (x=1; x<16; x++) { vline(screen, VIRTUAL_W*x/16, 1, VIRTUAL_H-2, palette_color[x]); hline(screen, 1, VIRTUAL_H*x/16, VIRTUAL_W-2, palette_color[x]); sprintf(buf, "%x", x); textout_ex(screen, font, buf, 2, VIRTUAL_H*x/16-4, palette_color[15], -1); textout_ex(screen, font, buf, VIRTUAL_W-9, VIRTUAL_H*x/16-4, palette_color[15], -1); textout_ex(screen, font, buf, VIRTUAL_W*x/16-4, 2, palette_color[15], -1); textout_ex(screen, font, buf, VIRTUAL_W*x/16-4, VIRTUAL_H-9, palette_color[15], -1); } sprintf(buf, "Graphics driver: %s", gfx_driver->name); textout_ex(screen, font, buf, 32, 32, palette_color[15], -1); sprintf(buf, "Description: %s", gfx_driver->desc); textout_ex(screen, font, buf, 32, 48, palette_color[15], -1); sprintf(buf, "Specs: %s", gfx_specs); textout_ex(screen, font, buf, 32, 64, palette_color[15], -1); sprintf(buf, "Color depth: %s", gfx_specs2); textout_ex(screen, font, buf, 32, 80, palette_color[15], -1); textout_ex(screen, font, gfx_specs3, 32, 96, palette_color[15], -1); if (gfx_driver->scroll == NULL) textout_ex(screen, font, "Hardware scrolling not supported", 32, 112, palette_color[15], -1); x = y = 0; position_mouse(32, 32); while ((!done) && (!mouse_b)) { poll_mouse(); if ((mouse_x != 32) || (mouse_y != 32)) { x += mouse_x - 32; y += mouse_y - 32; position_mouse(32, 32); } if (keypressed()) { switch (readkey() >> 8) { case KEY_LEFT: x--; break; case KEY_RIGHT: x++; break; case KEY_UP: y--; break; case KEY_DOWN: y++; break; default: done = TRUE; break; } } if (x < 0) x = 0; else if (x > (VIRTUAL_W - SCREEN_W)) x = VIRTUAL_W - SCREEN_W; if (y < 0) y = 0; else if (y > VIRTUAL_H) y = VIRTUAL_H; scroll_screen(x, y); rest(1); } do { poll_mouse(); } while (mouse_b); position_mouse(ox, oy); clear_keybuf(); scroll_screen(0, 0); } void test_it(char *msg, void (*func)(int, int)) { int x = 0; int y = 0; int c = 0; int pat = AL_RAND()%NUM_PATTERNS; do { acquire_screen(); set_clip_rect(screen, 0, 0, SCREEN_W-1, SCREEN_H-1); clear_to_color(screen, palette_color[0]); message(msg); textout_centre_ex(screen, font, "(arrow keys to slide)", SCREEN_W/2, 28, palette_color[15], palette_color[0]); textout_ex(screen, font, "unclipped:", xoff+48, yoff+50, palette_color[15], palette_color[0]); textout_ex(screen, font, "clipped:", xoff+180, yoff+62, palette_color[15], palette_color[0]); rect(screen, xoff+191, yoff+83, xoff+240, yoff+114, palette_color[15]); set_clip_rect(screen, xoff+192, yoff+84, xoff+239, yoff+113); drawing_mode(mode, pattern[pat], 0, 0); set_clip_state(screen, FALSE); (*func)(xoff+x+60, yoff+y+70); set_clip_state(screen, TRUE); (*func)(xoff+x+180, yoff+y+70); solid_mode(); release_screen(); do { poll_mouse(); if (mouse_b) { do { poll_mouse(); } while (mouse_b); c = KEY_ESC<<8; break; } if (keypressed()) c = readkey(); } while (!c); if ((c>>8) == KEY_LEFT) { if (x > -32) x--; c = 0; } else if ((c>>8) == KEY_RIGHT) { if (x < 32) x++; c = 0; } else if ((c>>8) == KEY_UP) { if (y > -32) y--; c = 0; } else if ((c>>8) == KEY_DOWN) { if (y < 32) y++; c = 0; } } while (!c); } void do_it(char *msg, int clip_flag, void (*func)(void)) { int x1, y1, x2, y2; set_clip_rect(screen, 0, 0, SCREEN_W-1, SCREEN_H-1); clear_to_color(screen, palette_color[0]); message(msg); if (clip_flag) { do { x1 = (AL_RAND() & 255) + 32; x2 = (AL_RAND() & 255) + 32; } while (x2-x1 < 30); do { y1 = (AL_RAND() & 127) + 40; y2 = (AL_RAND() & 127) + 40; } while (y2-y1 < 20); set_clip_rect(screen, xoff+x1, yoff+y1, xoff+x2, yoff+y2); } else set_clip_state(screen, FALSE); drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); (*func)(); solid_mode(); if (!clip_flag) set_clip_state(screen, TRUE); } void circler(BITMAP *b, int x, int y, int c) { circlefill(b, x, y, 4, palette_color[c]); } int floodfill_proc(void) { int ox, oy, nx, ny; int c; scare_mouse(); clear_to_color(screen, palette_color[0]); textout_centre_ex(screen, font, "floodfill test", SCREEN_W/2, 6, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "Press a mouse button to draw,", SCREEN_W/2, 64, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "a key 0-9 to floodfill,", SCREEN_W/2, 80, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "and ESC to finish", SCREEN_W/2, 96, palette_color[15], palette_color[0]); unscare_mouse(); ox = -1; oy = -1; do { poll_mouse(); c = mouse_b; if (c) { nx = mouse_x; ny = mouse_y; if ((ox >= 0) && (oy >= 0)) { scare_mouse(); if (c&1) { line(screen, ox, oy, nx, ny, palette_color[255]); } else { acquire_screen(); do_line(screen, ox, oy, nx, ny, 255, circler); release_screen(); } unscare_mouse(); } ox = nx; oy = ny; } else ox = oy = -1; if (keypressed()) { c = readkey() & 0xff; if ((c >= '0') && (c <= '9')) { scare_mouse(); drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); floodfill(screen, mouse_x, mouse_y, palette_color[c-'0']); solid_mode(); unscare_mouse(); } } rest(1); } while (c != 27); return D_REDRAW; } void draw_spline(int points[8]) { int i, c1, c2; if (bitmap_color_depth(screen) == 8) { c1 = 255; c2 = 1; } else { c1 = makecol(255, 255, 255); c2 = makecol(0, 255, 255); } spline(screen, points, c1); for (i=0; i<4; i++) rect(screen, points[i*2]-6, points[i*2+1]-6, points[i*2]+5, points[i*2+1]+5, c2); } int spline_proc(void) { int points[8]; int nx, ny, ox, oy; int sel, os; int c; scare_mouse(); acquire_screen(); clear_to_color(screen, palette_color[0]); textout_centre_ex(screen, font, "spline test", SCREEN_W/2, 6, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "Drag boxes to change guide points,", SCREEN_W/2, 64, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "and press ESC to finish", SCREEN_W/2, 80, palette_color[15], palette_color[0]); for (c=0; c<4; c++) { points[c*2] = SCREEN_W/2 + c*64 - 96; points[c*2+1] = SCREEN_H/2 + ((c&1) ? 32 : -32); } xor_mode(TRUE); ox = mouse_x; oy = mouse_x; sel = -1; draw_spline(points); release_screen(); unscare_mouse(); for (;;) { poll_mouse(); nx = mouse_x; ny = mouse_y; os = sel; if (mouse_b) { if (sel < 0) { for (sel=3; sel>=0; sel--) { if ((nx >= points[sel*2]-6) && (nx < points[sel*2]+6) && (ny >= points[sel*2+1]-6) && (ny < points[sel*2+1]+6)) break; } } if ((sel >= 0) && ((ox != nx) || (oy != ny) || (os != sel))) { scare_mouse(); acquire_screen(); draw_spline(points); points[sel*2] = nx; points[sel*2+1] = ny; draw_spline(points); release_screen(); unscare_mouse(); } } else sel = -1; if (keypressed()) { c = readkey(); if ((c&0xFF) == 27) break; } ox = nx; oy = ny; rest(1); } xor_mode(FALSE); return D_REDRAW; } int polygon_proc(void) { #define MAX_POINTS 256 int k = 0; int num_points = 0; int points[MAX_POINTS*2]; CHECK_TRANS_BLENDER(); scare_mouse(); clear_to_color(screen, palette_color[0]); textout_centre_ex(screen, font, "polygon test", SCREEN_W/2, 6, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "Press left mouse button to add a", SCREEN_W/2, 64, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "point, right mouse button to draw,", SCREEN_W/2, 80, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "and ESC to finish", SCREEN_W/2, 96, palette_color[15], palette_color[0]); unscare_mouse(); do { poll_mouse(); rest(1); } while (mouse_b); do { poll_mouse(); if ((mouse_b & 1) && (num_points < MAX_POINTS)) { points[num_points*2] = mouse_x; points[num_points*2+1] = mouse_y; scare_mouse(); if (num_points > 0) line(screen, points[(num_points-1)*2], points[(num_points-1)*2+1], points[num_points*2], points[num_points*2+1], palette_color[255]); circlefill(screen, points[num_points*2], points[num_points*2+1], 2, palette_color[255]); num_points++; unscare_mouse(); do { poll_mouse(); } while (mouse_b); } if ((mouse_b & 2) && (num_points > 2)) { scare_mouse(); line(screen, points[(num_points-1)*2], points[(num_points-1)*2+1], points[0], points[1], palette_color[255]); drawing_mode(mode, pattern[AL_RAND()%NUM_PATTERNS], 0, 0); polygon(screen, num_points, points, palette_color[1]); solid_mode(); num_points = 0; unscare_mouse(); do { poll_mouse(); } while (mouse_b); } if (keypressed()) k = readkey() & 0xff; rest(1); } while (k != 27); return D_REDRAW; } int putpixel_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("putpixel test", putpix_test); do_it("timing putpixel", FALSE, putpix_demo); do_it("timing putpixel [clipped]", TRUE, putpix_demo); unscare_mouse(); return D_REDRAW; } int getpixel_proc(void) { getpix_demo(); return D_REDRAW; } int hline_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("hline test", hline_test); do_it("timing hline", FALSE, hline_demo); do_it("timing hline [clipped]", TRUE, hline_demo); unscare_mouse(); return D_REDRAW; } int vline_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("vline test", vline_test); do_it("timing vline", FALSE, vline_demo); do_it("timing vline [clipped]", TRUE, vline_demo); unscare_mouse(); return D_REDRAW; } int line_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("line test", line_test); do_it("timing line", FALSE, line_demo); do_it("timing line [clipped]", TRUE, line_demo); unscare_mouse(); return D_REDRAW; } int rectfill_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("rectfill test", rectfill_test); do_it("timing rectfill", FALSE, rectfill_demo); do_it("timing rectfill [clipped]", TRUE, rectfill_demo); unscare_mouse(); return D_REDRAW; } int triangle_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("triangle test", triangle_test); do_it("timing triangle", FALSE, triangle_demo); do_it("timing triangle [clipped]", TRUE, triangle_demo); unscare_mouse(); return D_REDRAW; } int triangle3d_proc(void) { check_tables(); scare_mouse(); type3d = POLYTYPE_FLAT; do_it("timing triangle 3D [flat]", FALSE, triangle3d_demo); type3d = POLYTYPE_GCOL; do_it("timing triangle 3D [gcol]", FALSE, triangle3d_demo); type3d = POLYTYPE_GRGB; do_it("timing triangle 3D [grgb]", FALSE, triangle3d_demo); type3d = POLYTYPE_ATEX; do_it("timing triangle 3D [atex]", FALSE, triangle3d_demo); type3d = POLYTYPE_PTEX; do_it("timing triangle 3D [ptex]", FALSE, triangle3d_demo); type3d = POLYTYPE_ATEX_MASK; do_it("timing triangle 3D [atex mask]", FALSE, triangle3d_demo); type3d = POLYTYPE_PTEX_MASK; do_it("timing triangle 3D [ptex mask]", FALSE, triangle3d_demo); type3d = POLYTYPE_ATEX_LIT; do_it("timing triangle 3D [atex lit]", FALSE, triangle3d_demo); type3d = POLYTYPE_PTEX_LIT; do_it("timing triangle 3D [ptex lit]", FALSE, triangle3d_demo); type3d = POLYTYPE_ATEX_MASK_LIT; do_it("timing triangle 3D [atex mask lit]", FALSE, triangle3d_demo); type3d = POLYTYPE_PTEX_MASK_LIT; do_it("timing triangle 3D [ptex mask lit]", FALSE, triangle3d_demo); unscare_mouse(); return D_REDRAW; } int circle_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("circle test", circle_test); do_it("timing circle", FALSE, circle_demo); do_it("timing circle [clipped]", TRUE, circle_demo); unscare_mouse(); return D_REDRAW; } int circlefill_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("circlefill test", circlefill_test); do_it("timing circlefill", FALSE, circlefill_demo); do_it("timing circlefill [clipped]", TRUE, circlefill_demo); unscare_mouse(); return D_REDRAW; } int ellipse_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("ellipse test", ellipse_test); do_it("timing ellipse", FALSE, ellipse_demo); do_it("timing ellipse [clipped]", TRUE, ellipse_demo); unscare_mouse(); return D_REDRAW; } int ellipsefill_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("ellipsefill test", ellipsefill_test); do_it("timing ellipsefill", FALSE, ellipsefill_demo); do_it("timing ellipsefill [clipped]", TRUE, ellipsefill_demo); unscare_mouse(); return D_REDRAW; } int arc_proc(void) { CHECK_TRANS_BLENDER(); scare_mouse(); test_it("arc test", arc_test); do_it("timing arc", FALSE, arc_demo); do_it("timing arc [clipped]", TRUE, arc_demo); unscare_mouse(); return D_REDRAW; } int textout_proc(void) { scare_mouse(); test_it("textout test", textout_test); do_it("timing textout", FALSE, textout_demo); do_it("timing textout [clipped]", TRUE, textout_demo); unscare_mouse(); return D_REDRAW; } /* Some helpers for blit_proc */ int pause_mode = FALSE; int blit_pause_proc(void) { static int pause_count = 0; int ch; /* Don't go too fast. We want to be able to see if it's working the way it * was intended to and without this all you see are colors zipping arround. */ pause_count++; if (pause_count >= 2) { pause_count = 0; rest(5); } if (!pause_mode) { if (mouse_needs_poll()) poll_mouse(); if (mouse_b) return TRUE; if (keypressed()) { if (((ch = readkey()) & 0xff) == 'f') { pause_mode = TRUE; return FALSE; } return TRUE; } } else { while (!keypressed()) { if (mouse_needs_poll()) poll_mouse(); if (mouse_b) return FALSE; rest(2); } if (((ch = readkey()) & 0xff) == 'f') { pause_mode = FALSE; return FALSE; } if (((ch & 0xff) == 27) || ((ch & 0xff) == 'q')) return TRUE; } return FALSE; } int blit_proc(void) { int i, c, y, tpat_size=64; int done = FALSE; scare_mouse(); acquire_screen(); set_clip_rect(screen, 0, 0, SCREEN_W-1, SCREEN_H-1); clear_to_color(screen, palette_color[0]); textout_centre_ex(screen, font, "Blit to self test. Options: ", SCREEN_W/2, 4, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, " Press 'f' to toggle frame mode. ", SCREEN_W/2, 12, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, " Press any other key to do next test. ", SCREEN_W/2, 20, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "Frame mode options: ", SCREEN_W/2, 40, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, " Press any key to draw next frame. ", SCREEN_W/2, 48, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, " Press 'f' to toggle frame mode. ", SCREEN_W/2, 56, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, " Press 'q' to continue with next test.", SCREEN_W/2, 64, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "Press a key or mouse button to start.", SCREEN_W/2, 80, palette_color[15], palette_color[0]); release_screen(); unscare_mouse(); while ((!keypressed()) && (!mouse_b)) { if (mouse_needs_poll()) poll_mouse(); rest(2); } pause_mode = FALSE; if (keypressed()) { if ((readkey() & 0xff) == 'f') pause_mode = TRUE; } else { while (mouse_b) { if (mouse_needs_poll()) poll_mouse(); } } scare_mouse(); acquire_screen(); /* Find a good size for the test pattern. If its too small its difficult * to see and if its too big then the test can run too slow. */ if ((SCREEN_W < 256) || (SCREEN_H < 256)) tpat_size = 32; else if ((SCREEN_W < 640) || (SCREEN_H < 480)) tpat_size = 64; else tpat_size = 96; /* Draw test pattern */ for (y=0; y < tpat_size; y+=(tpat_size/8)) { for (c=0; c < 8; c++) rectfill(screen, c*(tpat_size/8), y, (c*(tpat_size/8))+(tpat_size/8)-1, y+(tpat_size/8)-1, palette_color[(c+(y/8))&31]); } vline(screen, 5, 0, tpat_size-1, palette_color[15]); vline(screen, tpat_size-6, 0, tpat_size-1, palette_color[15]); vline(screen, 4, 0, tpat_size-1, palette_color[0]); vline(screen, tpat_size-5, 0, tpat_size-1, palette_color[0]); vline(screen, 3, 0, tpat_size-1, palette_color[15]); vline(screen, tpat_size-4, 0, tpat_size-1, palette_color[15]); hline(screen, 0, 5, tpat_size-1, palette_color[15]); hline(screen, 0, tpat_size-6, tpat_size-1, palette_color[15]); hline(screen, 0, 4, tpat_size-1, palette_color[0]); hline(screen, 0, tpat_size-5, tpat_size-1, palette_color[0]); hline(screen, 0, 3, tpat_size-1, palette_color[15]); hline(screen, 0, tpat_size-4, tpat_size-1, palette_color[15]); release_screen(); #define B2S_CHECK_X \ rest(20); \ if (done) \ break; /* Blit to self test */ for (i = 0; i < 2; i++) { /* down+right */ for (c = y = 0; (c < SCREEN_W-tpat_size) && (y < SCREEN_H-tpat_size); c++, y++) { blit(screen, screen, c, y, c+1, y+1, tpat_size, tpat_size); vline(screen, c, y, y+tpat_size-1, palette_color[0]); hline(screen, c, y, c+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* up+left */ for ( ; (c > 0) && (y > 0); c--, y--) { blit(screen, screen, c, y, c-1, y-1, tpat_size, tpat_size); vline(screen, c+tpat_size-1, y, y+tpat_size-1, palette_color[0]); hline(screen, c, y+tpat_size-1, c+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* right */ for ( ; c < SCREEN_W-tpat_size; c++) { blit(screen, screen, c, y, c+1, y, tpat_size, tpat_size); vline(screen, c, y, y+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* down+left */ for ( ; (c > 0) && (y < SCREEN_H-tpat_size); c--, y++) { blit(screen, screen, c, y, c-1, y+1, tpat_size, tpat_size); vline(screen, c+tpat_size-1, y, y+tpat_size-1, palette_color[0]); hline(screen, c, y, c+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* up+right */ for ( ; (c < SCREEN_W-tpat_size) && (y > 0); c++, y--) { blit(screen, screen, c, y, c+1, y-1, tpat_size, tpat_size); vline(screen, c, y, y+tpat_size-1, palette_color[0]); hline(screen, c, y+tpat_size-1, c+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* down */ for ( ; y < SCREEN_H-tpat_size; y++) { blit(screen, screen, c, y, c, y+1, tpat_size, tpat_size); hline(screen, c, y, c+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* left */ for ( ; c > 0; c--) { blit(screen, screen, c, y, c-1, y, tpat_size, tpat_size); vline(screen, c+tpat_size-1, y, y+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X /* up */ for ( ; y > 0; y--) { blit(screen, screen, c, y, c, y-1, tpat_size, tpat_size); hline(screen, c, y+tpat_size-1, c+tpat_size-1, palette_color[0]); if ((done = blit_pause_proc())) break; } B2S_CHECK_X } if (keypressed()) readkey(); blit_from_screen = TRUE; do_it("timing blit screen->screen", FALSE, blit_demo); blit_align = TRUE; do_it("timing blit screen->screen (aligned)", FALSE, blit_demo); blit_align = FALSE; blit_from_screen = FALSE; do_it("timing blit memory->screen", FALSE, blit_demo); blit_align = TRUE; do_it("timing blit memory->screen (aligned)", FALSE, blit_demo); blit_align = FALSE; blit_mask = TRUE; if (gfx_capabilities & GFX_HW_VRAM_BLIT_MASKED) { blit_from_screen = TRUE; do_it("timing masked blit screen->screen", FALSE, blit_demo); blit_from_screen = FALSE; } do_it("timing masked blit memory->screen", FALSE, blit_demo); blit_mask = FALSE; do_it("timing blit [clipped]", TRUE, blit_demo); unscare_mouse(); return D_REDRAW; } int sprite_proc(void) { scare_mouse(); test_it("sprite test", sprite_test); do_it("timing draw_sprite", FALSE, sprite_demo); do_it("timing draw_sprite [clipped]", TRUE, sprite_demo); test_it("RLE sprite test", rle_sprite_test); do_it("timing draw_rle_sprite", FALSE, rle_sprite_demo); do_it("timing draw_rle_sprite [clipped]", TRUE, rle_sprite_demo); global_compiled_sprite = get_compiled_sprite(global_sprite, is_planar_bitmap(screen)); test_it("compiled sprite test", compiled_sprite_test); do_it("timing draw_compiled_sprite", FALSE, compiled_sprite_demo); destroy_compiled_sprite(global_compiled_sprite); unscare_mouse(); return D_REDRAW; } int xlu_sprite_proc(void) { check_tables(); scare_mouse(); test_it("translucent sprite test", xlu_sprite_test); do_it("timing draw_trans_sprite", FALSE, xlu_sprite_demo); do_it("timing draw_trans_sprite [clipped]", TRUE, xlu_sprite_demo); test_it("translucent RLE sprite test", rle_xlu_sprite_test); do_it("timing draw_trans_rle_sprite", FALSE, rle_xlu_sprite_demo); do_it("timing draw_trans_rle_sprite [clipped]", TRUE, rle_xlu_sprite_demo); unscare_mouse(); return D_REDRAW; } int lit_sprite_proc(void) { check_tables(); color_map = light_map; scare_mouse(); test_it("tinted sprite test", lit_sprite_test); do_it("timing draw_lit_sprite", FALSE, lit_sprite_demo); do_it("timing draw_lit_sprite [clipped]", TRUE, lit_sprite_demo); test_it("tinted RLE sprite test", rle_lit_sprite_test); do_it("timing draw_lit_rle_sprite", FALSE, rle_lit_sprite_demo); do_it("timing draw_lit_rle_sprite [clipped]", TRUE, rle_lit_sprite_demo); color_map = trans_map; unscare_mouse(); return D_REDRAW; } int rotate_proc(void) { scare_mouse(); test_it("Flipped sprite test", flipped_sprite_test); rotate_test(); unscare_mouse(); return D_REDRAW; } int polygon3d_proc(void) { #define NUM_POINTS 8+6 #define NUM_FACES 6 #define BUFFER_SIZE 128 #define NUM_MODES 15 /* a 3d x,y,z position */ typedef struct POINT { float x, y, z; } POINT; /* four vertices plus a normal make up a quad */ typedef struct QUAD { int v1, v2, v3, v4; int normal; int visible; } QUAD; /* vertices of the cube */ static POINT point[NUM_POINTS] = { /* regular vertices */ { -32, -32, -32 }, { -32, 32, -32 }, { 32, 32, -32 }, { 32, -32, -32 }, { -32, -32, 32 }, { -32, 32, 32 }, { 32, 32, 32 }, { 32, -32, 32 }, /* normals */ { -32, -32, -33 }, { -32, -32, 33 }, { -33, 32, -32 }, { 33, 32, -32 }, { 32, -33, 32 }, { 32, 33, 32 } }; /* output vertex list */ static V3D_f vtx[NUM_POINTS] = { /* x y z u v c */ { 0, 0, 0, 0, 0, 0x30 }, { 0, 0, 0, 0, 32, 0x99 }, { 0, 0, 0, 32, 32, 0x55 }, { 0, 0, 0, 32, 0, 0xDD }, { 0, 0, 0, 32, 0, 0x40 }, { 0, 0, 0, 32, 32, 0xBB }, { 0, 0, 0, 0, 32, 0x77 }, { 0, 0, 0, 0, 0, 0xF0 } }; /* six faces makes up a cube */ QUAD face[NUM_FACES] = { /* v1 v2 v3 v4 nrm v */ { 0, 3, 2, 1, 8, 0 }, { 4, 5, 6, 7, 9, 0 }, { 1, 5, 4, 0, 10, 0 }, { 2, 3, 7, 6, 11, 0 }, { 7, 3, 0, 4, 12, 0 }, { 6, 5, 1, 2, 13, 0 } }; /* descriptions of the render modes */ static char *mode_desc[NUM_MODES] = { "POLYTYPE_FLAT", "POLYTYPE_GCOL", "POLYTYPE_GRGB", "POLYTYPE_ATEX", "POLYTYPE_PTEX", "POLYTYPE_ATEX_MASK", "POLYTYPE_PTEX_MASK", "POLYTYPE_ATEX_LIT", "POLYTYPE_PTEX_LIT", "POLYTYPE_ATEX_MASK_LIT", "POLYTYPE_PTEX_MASK_LIT", "POLYTYPE_ATEX_TRANS", "POLYTYPE_PTEX_TRANS", "POLYTYPE_ATEX_MASK_TRANS", "POLYTYPE_PTEX_MASK_TRANS" }; int c; int key; int mode = POLYTYPE_FLAT; int tile = 1; float xr = -16; float yr = 24; float zr = 0; float dist = 128; float vx, vy, vz; float nx, ny, nz; int redraw_mode = TRUE; MATRIX_f transform, camera; V3D_f *vertex, *normal; BITMAP *buffer, *texture; buffer = create_bitmap(BUFFER_SIZE, BUFFER_SIZE); texture = create_bitmap(32, 32); check_tables(); blit(global_sprite, texture, 0, 0, 0, 0, 32, 32); rect(texture, 0, 0, 31, 31, palette_color[1]); scare_mouse(); acquire_screen(); clear_to_color(screen, palette_color[0]); textout_centre_ex(screen, font, "3d polygon test", SCREEN_W/2, 6, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "Use the arrow keys to rotate the", SCREEN_W/2, 64, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "cube, + and - to zoom, space to", SCREEN_W/2, 80, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "change drawing mode, enter to tile", SCREEN_W/2, 96, palette_color[15], palette_color[0]); textout_centre_ex(screen, font, "the texture, and ESC to finish", SCREEN_W/2, 112, palette_color[15], palette_color[0]); release_screen(); /* set projection parameters */ set_projection_viewport(0, 0, BUFFER_SIZE, BUFFER_SIZE); get_camera_matrix_f(&camera, 0, 0, 0, /* eye position */ 0, 0, 1, /* front vector */ 0, -1, 0, /* up vector */ 32, /* field of view */ 1); /* aspect ratio */ for (;;) { if (redraw_mode) { rectfill(screen, 0, 24, SCREEN_W, 32, palette_color[0]); textout_centre_ex(screen, font, mode_desc[mode], SCREEN_W/2, 24, palette_color[255], palette_color[0]); redraw_mode = FALSE; } clear_to_color(buffer, 8); /* build a transformation matrix */ get_transformation_matrix_f(&transform, 1, xr, yr, zr, 0, 0, dist); /* transform vertices into view space */ for (c=0; c