diff --git a/AUTHORS b/AUTHORS index c7f4622..eb365e5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,5 +7,6 @@ Ulf Wohlers Tommy Frössman Dean Beeler Sebastian Strohhäcker +Ralf Grillenberger nick_without_<> @ users.sourceforge.net diff --git a/ChangeLog b/ChangeLog index 270019f..3e912f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,67 +1,80 @@ 0.74 - Several small game specific fixes/hacks/support. (Offensive, Roadhog, GTA installer, Kingdom O' Magic soundcard detection, - Pirate booter, armored fist installer) - - Add the S3-specific 640x480 256 color mode. Fixes regression in "Wooden - Ships and Iron Men" and "I Have No Mouth And I Must Scream". + Pirate booter, Armored Fist installer) + - Add the S3-specific 640x480 256 color mode. (fixes regression in "Wooden + Ships and Iron Men" and "I Have No Mouth And I Must Scream") - Fix a stack overflow that could crash DOSBox. - - Add fake microphone input. (Fixes Talking Parrot) + - Add fake microphone input. (fixes Talking Parrot) - Modify adlib turn off code, so that it doesn't turn off in cases where the same sound is repeated over and over again. - Several small fixes to the CDROM audio code. (HOMM2, Redneck Rampage and others) - Several improvements to the CDROM emulation code. (fixes Alpha Storm and GT Racing 97) - - Some small cpu fixes that might fix something. - - Handle opcode 0xff subcode 7 as invalid instruction, fixes dif-2 & others. - - Some hercules fixes (Testdrive) + - Some small CPU fixes that might fix something. + - Handle opcode 0xff subcode 7 as invalid instruction. (fixes dif-2 & others) + - Some hercules fixes. (Testdrive) - Improve support for blanked parts that wrap around to the start of - the screen. (Fixes Magic Circle demo and Sid&Al) - - Remove old opl cores as the new ones seem work very nice. + the screen. (fixes Magic Circle demo and Sid&Al) + - Remove old OPL cores as the new ones seem to work very nicely. - Modify movie recording code so that the movies aren't corrupt when you exit dosbox without stopping the movie. - Change RGB3x scaler to look more pretty. - Improve initial register values compatility of the GUS. - - Change render preferences a bit to be more compatible with windows 7. - - Add DOS fixes to terminate program. (Fixes fortune teller) - - Add FFREEP. (Fixes trucks) - - Improve FPU ST80 in C mode when writing zero. (Fixes antigok) - - Add special int10 scanline function. (Fixes mz700 and probably lots + - Added autodetection for Gameblaster. (games can find it now) + - Change render preferences a bit to be more compatible with Windows 7. + - Add DOS fixes to terminate program. (fixes Fortune Teller) + - Add FFREEP. (fixes Trucks) + - Improve FPU ST80 in C mode when writing zero. (fixes Antigok) + - Add special int10 scanline function. (fixes mz700 and probably lots of games that mess with them) - - Fix scrolling in rarely used video modes. (Fixes Orphee) + - Fix scrolling in rarely used video modes. (fixes Orphee) - Modify game specific hacks a bit so that Kick off 3 works again. - Lots of fixes to the INT10 video parameter table. (Seven spirits of ra and others) + - Add VGA blanking in machine=vgaonly. (used by Alien Carnage) + - CGA, PCJr, Tandy: Add video blanking, change display start latch + timing, sync pulse width correction. + - PCJr, Tandy: implement vertical retrace interrupt. + - PCJr, CGA: line-by-line video emulation. + - PCJr: support on-screen change of color modes 4medium to 16low. (used + by Ghostbusters booter) + - Hercules: Add green and amber monochrome support. + - All machines: only update the video timing when needed. (Jungle Hunt, + others that synchronize to the video screen might profit) - Several small DOS fixes. - - Some UMB related fixes. ( The Legacy without umb) + - Some UMB related fixes. (The Legacy without UMB) - Fix version number of DSP for SB 1.5. (fixes a few games) - - Several vga emulation improvements (Allertone football manager) - - Some tandy fixes. (mech warrior) + - Several VGA emulation improvements. (Allertone football manager) + - Some Tandy fixes. (Mech Warrior) - Small improvements and fixes to the OPL emulation. - - Add low Level tandy DAC emulation. - - Some EMS fixes. (Fixes Mortal Kombat and others) - - Change SoundBlaster DSP reset mechanism, add sb irq acknowledge logic - (fixes stmik-based applications). - - Some interrupt pointer location modifications. (fixes tinker tales) - - Some fixes to the BOOT code. (fixes last mission) - - Respect write-only. (fixes champions of zulala) - - Some RTC fix. (Fixes Tully Bodine and others) + - Add low level Tandy DAC emulation. + - Some EMS fixes. (fixes Mortal Kombat and others) + - Change SoundBlaster DSP reset mechanism, add sb irq acknowledge logic. + (fixes stmik-based applications) + - Some interrupt pointer location modifications. (fixes Tinker Tales) + - Some fixes to the BOOT code. (fixes Last Mission) + - Respect write-only file information. (fixes Champions of Zulala) + - Some RTC fix. (fixes Tully Bodine and others) - Improve mouse emulation to work better with Water World. - Hopefully fix the translation of the configuration file. - Speed up and fixes for the recompiler core. (pitfall2 pcjr) - - Change memory start location. (Fixes 7th Guest installer) - - Several fixes to the BAT files handling. (Shift and + - Change memory start location. (fixes 7th Guest installer) + - Several fixes to the batch file handling. (Shift and use the typed first %0 instead of the parsed %0) - - Improve file redirection and redirected line ends. (Fixes + - Improve file redirection and redirected line ends. (fixes Phantasmagoria 2 DOS installer) - Fix compilation with new MAC os X version. - Add 16C550A FIFO support to the serial port emulation. - Improve modem emulation to get higher speeds. - - Change default samplerates to 44100, so that hopefully certain - soundcards produce more fluent sound playback. + - Change default samplerates to 44100, blocksize to 1024 and prebuffer to 20, + so that hopefully certain soundcards produce more fluent sound playback. - Add some rarely used, but for some games critical flags to the internal commands. - - Improve internal timing with repeatings timers (especially with + - Add -userconf flag, so that the userspecific configuration can + easily be used together with -conf configfile. + - Improve internal timing with repeating timers (especially with the dynamic core). 0.73 diff --git a/NEWS b/NEWS index d303e45..adc6875 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,82 @@ +0.74 + - Several small game specific fixes/hacks/support. (Offensive, + Roadhog, GTA installer, Kingdom O' Magic soundcard detection, + Pirate booter, Armored Fist installer) + - Add the S3-specific 640x480 256 color mode. (fixes regression in "Wooden + Ships and Iron Men" and "I Have No Mouth And I Must Scream") + - Fix a stack overflow that could crash DOSBox. + - Add fake microphone input. (fixes Talking Parrot) + - Modify adlib turn off code, so that it doesn't turn off in + cases where the same sound is repeated over and over again. + - Several small fixes to the CDROM audio code. (HOMM2, Redneck + Rampage and others) + - Several improvements to the CDROM emulation code. (fixes Alpha + Storm and GT Racing 97) + - Some small CPU fixes that might fix something. + - Handle opcode 0xff subcode 7 as invalid instruction. (fixes dif-2 & others) + - Some hercules fixes. (Testdrive) + - Improve support for blanked parts that wrap around to the start of + the screen. (fixes Magic Circle demo and Sid&Al) + - Remove old OPL cores as the new ones seem to work very nicely. + - Modify movie recording code so that the movies aren't corrupt when + you exit dosbox without stopping the movie. + - Change RGB3x scaler to look more pretty. + - Improve initial register values compatility of the GUS. + - Added autodetection for Gameblaster. (games can find it now) + - Change render preferences a bit to be more compatible with Windows 7. + - Add DOS fixes to terminate program. (fixes Fortune Teller) + - Add FFREEP. (fixes Trucks) + - Improve FPU ST80 in C mode when writing zero. (fixes Antigok) + - Add special int10 scanline function. (fixes mz700 and probably lots + of games that mess with them) + - Fix scrolling in rarely used video modes. (fixes Orphee) + - Modify game specific hacks a bit so that Kick off 3 works again. + - Lots of fixes to the INT10 video parameter table. (Seven spirits + of ra and others) + - Add VGA blanking in machine=vgaonly. (used by Alien Carnage) + - CGA, PCJr, Tandy: Add video blanking, change display start latch + timing, sync pulse width correction. + - PCJr, Tandy: implement vertical retrace interrupt. + - PCJr, CGA: line-by-line video emulation. + - PCJr: support on-screen change of color modes 4medium to 16low. (used + by Ghostbusters booter) + - Hercules: Add green and amber monochrome support. + - All machines: only update the video timing when needed. (Jungle Hunt, + others that synchronize to the video screen might profit) + - Several small DOS fixes. + - Some UMB related fixes. (The Legacy without UMB) + - Fix version number of DSP for SB 1.5. (fixes a few games) + - Several VGA emulation improvements. (Allertone football manager) + - Some Tandy fixes. (Mech Warrior) + - Small improvements and fixes to the OPL emulation. + - Add low level Tandy DAC emulation. + - Some EMS fixes. (fixes Mortal Kombat and others) + - Change SoundBlaster DSP reset mechanism, add sb irq acknowledge logic. + (fixes stmik-based applications) + - Some interrupt pointer location modifications. (fixes Tinker Tales) + - Some fixes to the BOOT code. (fixes Last Mission) + - Respect write-only file information. (fixes Champions of Zulala) + - Some RTC fix. (fixes Tully Bodine and others) + - Improve mouse emulation to work better with Water World. + - Hopefully fix the translation of the configuration file. + - Speed up and fixes for the recompiler core. (pitfall2 pcjr) + - Change memory start location. (fixes 7th Guest installer) + - Several fixes to the batch file handling. (Shift and + use the typed first %0 instead of the parsed %0) + - Improve file redirection and redirected line ends. (fixes + Phantasmagoria 2 DOS installer) + - Fix compilation with new MAC os X version. + - Add 16C550A FIFO support to the serial port emulation. + - Improve modem emulation to get higher speeds. + - Change default samplerates to 44100, blocksize to 1024 and prebuffer to 20, + so that hopefully certain soundcards produce more fluent sound playback. + - Add some rarely used, but for some games critical flags to + the internal commands. + - Add -userconf flag, so that the userspecific configuration can + easily be used together with -conf configfile. + - Improve internal timing with repeating timers (especially with + the dynamic core). + 0.73 - Add two new opl2+opl3 emulators. (better speed, different implementation approach) diff --git a/README b/README index ed8730a..236613f 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ ¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - DOSBox Wii - - Version 1.2 + Version 1.3 http://code.google.com/p/dosbox-wii (Under GPL License) @@ -19,6 +19,12 @@ A port of DOSBox to the Wii using SDL Wii. -=[ Update History ]=- +[1.3 - June 23, 2010] + +* Updated to latest DOSBox SVN +* Updated to latest libwiigui +* Improved on-screen keyboard + [1.2 - February 18, 2010] * Updated to latest DOSBox SVN @@ -79,39 +85,43 @@ you want to play on the PC version of DOSBox first to discover the optimum settings. ------------------------------------------------------------------------------- -DOSBox v0.73 +DOSBox v0.74 Manual (always use the latest version from www.dosbox.com) + ===== -NOTE: +NOTE: ===== -While we are hoping that one day DOSBox will run all programs ever -made for the PC, we are not there yet. At present, DOSBox running -on a high-end machine will roughly be the equivalent of a 486 PC. -DOSBox can be configured to run a wide range of DOS games, from -CGA/Tandy/PCjr classics up to games from the Quake era. +While we are hoping that one day DOSBox will run all programs ever made for +the PC, we are not there yet. +At present, DOSBox running on a high-end machine will roughly be the equivalent +of a Pentium I PC. DOSBox can be configured to run a wide range of DOS games, +from CGA/Tandy/PCjr classics up to games from the Quake era. ====== INDEX: ====== + 1. Quickstart -2. FAQ -3. Usage +2. Start (FAQ) +3. Command Line Parameters 4. Internal Programs 5. Special Keys -6. Mapper -7. Keyboard Layout -8. Serial Multiplayer feature -9. How to run resource-demanding games -10. Troubleshooting -11. The config file -12. The language file -13. Building your own version of DOSBox -14. Special thanks -15. Contact +6. Joystick/Gamepad +7. KeyMapper +8. Keyboard Layout +9. Serial Multiplayer feature +10. How to speed up/slow down DOSBox +11. Troubleshooting +12. DOSBox Status Window +13. The configuration (options) file +14. The language file +15. Building your own version of DOSBox +16. Special thanks +17. Contact @@ -120,335 +130,366 @@ INDEX: ============== Type INTRO in DOSBox for a quick tour. -It is essential that you get familiar with the idea of mounting, -DOSBox does not automatically make any drive (or a part of it) -accessible to the emulation. -See the FAQ entry "I've got a Z instead of a C at the prompt" as -well as the description of the MOUNT command (section 4). +It is essential that you get familiar with the idea of mounting, DOSBox does not +automatically make any drive (or a part of it) accessible to the emulation. See +the FAQ entry "How to start?" as well as the description of the MOUNT command +(section 4: "Internal Programs"). If you have your game on a cdrom you may try +this guide: http://vogons.zetafleet.com/viewtopic.php?t=8933 -======= -2. FAQ: -======= +=============== +2. Start (FAQ): +=============== -Some Frequently Asked Questions: - -Q: I've got a Z instead of a C at the prompt. -Q: Do I always have to type these commands? Automation? -Q: How do I change to fullscreen? -Q: My CD-ROM doesn't work. -Q: The game/application can't find its CD-ROM. -Q: The mouse doesn't work. -Q: There is no sound. -Q: The sound stutters or sounds stretched/weird. -Q: I can't type \ or : in DOSBox. -Q: The keyboard lags. -Q: The cursor always moves into one direction! -Q: The game/application runs much too slow! -Q: The game/application does not run at all/crashes! -Q: Can DOSBox harm my computer? -Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. -Q: What sound hardware does DOSBox presently emulate? -Q: DOSBox crashes on startup and I'm running arts. -Q: My Build game(Duke3D/Blood/Shadow Warrior) has problems. -Q: Great README, but I still don't get it. +START: How to start? +AUTOMATION: Do I always have to type these "mount" commands? +FULLSCREEN: How do I change to fullscreen? +CD-ROM: My CD-ROM doesn't work. +CD-ROM: The game/application can't find its CD-ROM. +MOUSE: The mouse doesn't work. +SOUND: There is no sound. +SOUND: What sound hardware does DOSBox presently emulate? +SOUND: The sound stutters or sounds stretched/weird. +KEYBOARD: I can't type \ or : in DOSBox. +KEYBOARD: Right Shift and "\" doesn't work in DOSBox. (Windows only) +KEYBOARD: The keyboard lags. +CONTROL: The character/cursor/mouse pointer always moves into one direction! +SPEED: The game/application runs much too slow/too fast! +CRASH: The game/application does not run at all/crashes! +CRASH: DOSBox crashes on startup! +GAME: My Build game(Duke3D/Blood/Shadow Warrior) has problems. +SAFETY: Can DOSBox harm my computer? +OPTIONS: I would like to change DOSBox's options. +HELP: Great Manual, but I still don't get it. - -Q: I've got a Z instead of a C at the prompt. -A: You have to make your directories available as drives in DOSBox by using - the "mount" command. For example, in Windows "mount C D:\GAMES" will give - you a C drive in DOSBox which points to your Windows D:\GAMES directory. - In Linux, "mount c /home/username" will give you a C drive in DOSBox - which points to /home/username in Linux. - To change to the drive mounted like above, type "C:". If everything went - fine, DOSBox will display the prompt "C:\>". +START: How to start? + At the beginning you've got a Z:\> instead of a C:\> at the prompt. + You have to make your directories available as drives in DOSBox by using + the "mount" command. For example, in Windows "mount C D:\GAMES" will give + you a C drive in DOSBox which points to your Windows D:\GAMES directory + (that was created before). In Linux, "mount c /home/username" will give you + a C drive in DOSBox which points to /home/username in Linux. + To change to the drive mounted like above, type "C:". If everything went + fine, DOSBox will display the prompt "C:\>". -Q: Do I always have to type these commands? Automation? -A: In the DOSBox configuration file is an [autoexec] section. The commands - present there are run when DOSBox starts, so you can use this section - for the mounting. +AUTOMATION: Do I always have to type these commands? + In the DOSBox configuration file is an [autoexec] section. The commands + present there are run when DOSBox starts, so you can use this section + for the mounting. Look at Section 13: The configuration (options) file -Q: How do I change to fullscreen? -A: Press alt-enter. Alternatively: Edit the configuration file of DOSBox and - change the option fullscreen=false to fullscreen=true. If fullscreen looks - wrong in your opinion: Play with the option fullresolution in the - configuration file of DOSBox. To get back from fullscreen mode: - Press alt-enter again. +FULLSCREEN: How do I change to fullscreen? + Press alt-enter. Alternatively: Edit the configuration file of DOSBox and + change the option fullscreen=false to fullscreen=true. If fullscreen looks + wrong in your opinion: Play with the options: fullresolution, output and + aspect in the configuration file of DOSBox. To get back from fullscreen + mode: Press alt-enter again. -Q: My CD-ROM doesn't work. -A: To mount your CD-ROM in DOSBox you have to specify some additional options - when mounting the CD-ROM. - To enable CD-ROM support (includes MSCDEX): - - mount d f:\ -t cdrom (windows) - - mount d /media/cdrom -t cdrom (linux) +CD-ROM: My CD-ROM doesn't work. + To mount your CD-ROM in DOSBox you have to specify some additional options + when mounting the CD-ROM. + To enable CD-ROM support (includes MSCDEX) in Windows: + - mount d f:\ -t cdrom + in Linux: + - mount d /media/cdrom -t cdrom - In some cases you might want to use a different CD-ROM interface, - for example if CD audio does not work: - To enable SDL-support (does not include low-level CD access!): - - mount d f:\ -t cdrom -usecd 0 -noioctl - To enable ioctl access using digital audio extraction for CD audio - (windows-only, useful for Vista): - - mount d f:\ -t cdrom -ioctl_dx - To enable ioctl access using MCI for CD audio (windows-only): - - mount d f:\ -t cdrom -ioctl_mci - To force ioctl-only access (windows-only): - - mount d f:\ -t cdrom -ioctl_dio - To enable low-level aspi-support (win98 with aspi-layer installed): - - mount d f:\ -t cdrom -aspi - - In the commands: - d driveletter you will get in DOSBox - - f:\ location of CD-ROM on your PC. - - 0 The number of the CD-ROM drive, reported by "mount -cd" + In some cases you might want to use a different CD-ROM interface, + for example if CD audio does not work: + To enable SDL-support (does not include low-level CD access!): + - mount d f:\ -t cdrom -usecd 0 -noioctl + To enable ioctl access using digital audio extraction for CD audio + (windows-only, useful for Vista): + - mount d f:\ -t cdrom -ioctl_dx + To enable ioctl access using MCI for CD audio (windows-only): + - mount d f:\ -t cdrom -ioctl_mci + To force ioctl-only access (windows-only): + - mount d f:\ -t cdrom -ioctl_dio + To enable low-level aspi-support (win98 with aspi-layer installed): + - mount d f:\ -t cdrom -aspi + + explanation: - d driveletter you will get in DOSBox (d is the best, + don't change it!) + - f:\ location of CD-ROM on your PC. In most cases it will + be d:\ or e:\ + - 0 The number of the CD-ROM drive, reported by "mount -cd" (note that this value is only needed when using SDL - for CD audio, otherwise it is ignored) - See also the next question: The game/application can't find its CD-ROM. + for CD audio, otherwise it is ignored) + See also the next question: The game/application can't find its CD-ROM. -Q: The game/application can't find its CD-ROM. -A: Be sure to mount the CD-ROM with -t cdrom switch, this will enable the - MSCDEX interface required by DOS games to interface with CD-ROMs. - Also try adding the correct label (-label LABEL) to the mount command, - where LABEL is the CD-label (volume ID) of the CD-ROM. - Under Windows you can specify -ioctl, -aspi or -noioctl. Look at the - description of the mount command in Section 4 for their meaning and the - additional audio-CD related options -ioctl_dx, ioctl_mci, ioctl_dio. - - Try creating a CD-ROM image (preferably CUE/BIN pair) and use the - DOSBox-internal IMGMOUNT tool to mount the image (the CUE sheet). - This enables very good low-level CD-ROM support on any operating system. +CD-ROM: The game/application can't find its CD-ROM. + Be sure to mount the CD-ROM with -t cdrom switch, this will enable the + MSCDEX interface required by DOS games to interface with CD-ROMs. + Also try adding the correct label (-label LABEL) to the mount command, + where LABEL is the CD-label (volume ID) of the CD-ROM. + Under Windows you can specify -ioctl, -aspi or -noioctl. Look at the + description of the mount command in Section 4: "Internal programs" + for their meaning and the + additional audio-CD related options -ioctl_dx, -ioctl_mci, -ioctl_dio. + + Try creating a CD-ROM image (preferably CUE/BIN pair) and use the + DOSBox's internal IMGMOUNT tool to mount the image (the CUE sheet). + This enables very good low-level CD-ROM support on any operating system. -Q: The mouse doesn't work. -A: Usually, DOSBox detects when a game uses mouse control. When you click on - the screen it should get locked (confined to the DOSBox window) and work. - With certain games, the DOSBox mouse detection doesn't work. In that case - you will have to lock the mouse manually by pressing CTRL-F10. +MOUSE: The mouse doesn't work. + Usually, DOSBox detects when a game uses mouse control. When you click on + the screen it should get locked (confined to the DOSBox window) and work. + With certain games, the DOSBox mouse detection doesn't work. In that case + you will have to lock the mouse manually by pressing CTRL-F10. -Q: There is no sound. -A: Be sure that the sound is correctly configured in the game. This might be - done during the installation or with a setup/setsound utility that - accompanies the game. First see if an autodetection option is provided. If - there is none try selecting soundblaster or soundblaster16 with the default - settings being "address=220 irq=7 dma=1". You might also want to select - midi at address 330 as music device. - The parameters of the emulated soundcards can be changed in the DOSBox - configuration file. - If you still don't get any sound set the core to normal and use some lower - fixed cycles value (like cycles=2000). Also assure that your host operating - sound does provide sound. - In certain cases it might be useful to use a different emulated sound device - like a soundblaster pro (sbtype=sbpro1 in the DOSBox configuration file) or - the gravis ultrasound (gus=true). +SOUND: There is no sound. + Be sure that the sound is correctly configured in the game. This might be + done during the installation or with a setup/setsound utility that + accompanies the game. First see if an autodetection option is provided. If + there is none try selecting Soundblaster or Soundblaster 16 with the default + settings being "address=220 irq=7 dma=1" (sometimes highdma=5). You might + also want to select Sound Canvas/SCC/MPU-401/General MIDI/Wave Blaster + at "address=330 IRQ=2" as music device. + The parameters of the emulated sound cards can be changed in the DOSBox + configuration file. + If you still don't get any sound set the core to normal in DOSBox + configuration and use some lower fixed cycles value (like cycles=2000). Also + assure that your host operating sound does provide sound. + In certain cases it might be useful to use a different emulated sound device + like a soundblaster pro (sbtype=sbpro1 in the DOSBox configuration file) or + the gravis ultrasound (gus=true). -Q: The sound stutters or sounds stretched/weird. -A: You're using too much CPU power to keep DOSBox running at the current speed. - You can lower the cycles, skip frames, reduce the sampling rate of - the respective sound device (see the DOSBox configuration file) or - the mixer device. You can also increase the prebuffer in the configfile. - If you are using cycles=max or =auto, then make sure that there is no - background processes interfering! (especially if they access the harddisk) +SOUND: What sound hardware does DOSBox presently emulate? + DOSBox emulates several legacy sound devices: + - Internal PC speaker/Buzzer + This emulation includes both the tone generator and several forms of + digital sound output through the internal speaker. + - Creative CMS/Gameblaster + The is the first card released by Creative Labs(R). The default + configuration places it on address 220. It is disabled as default. + - Tandy 3 voice + The emulation of this sound hardware is complete with the exception of + the noise channel. The noise channel is not very well documented and as + such is only a best guess as to the sound's accuracy. It is disabled as + default. + - Tandy DAC + Some games may require turning off sound blaster emulation (sbtype=none) + for better tandy DAC sound support. Don't forget to set the sbtype back to + sb16 if you don't use tandy sound. + - Adlib + This emulation is almost perfect and includes the Adlib's ability to + almost play digitized sound. Placed at address 220 (also on 388). + - SoundBlaster 16 / SoundBlaster Pro I & II / SoundBlaster I & II + By default DOSBox provides Soundblaster 16 level 16-bit stereo sound. + You can select a different SoundBlaster version in the configuration of + DOSBox. AWE32 music is not emulated as you can use MPU-401 instead + (see below). + - Disney Sound Source and Covox Speech Thing + Using the printer port, this sound device outputs digital sound only. + Placed at LPT1 + - Gravis Ultrasound + The emulation of this hardware is nearly complete, though the MIDI + capabilities have been left out, since an MPU-401 has been emulated + in other code. For Gravis music you also have to install Gravis drivers + inside DOSBox. It is disabled as default. + - MPU-401 + A MIDI passthrough interface is also emulated. This method of sound + output will only work when used with external device/emulator. + Every Windows XP/Vista/7 and MAC OS has got a default emulator compatible + with: Sound Canvas/SCC/General Standard/General MIDI/Wave Blaster. + A different device/emulator is needed for Roland LAPC/CM-32L/MT-32 + compatibility. -Q: I can't type \ or : in DOSBox. -A: This can happen in various cases, like your host keyboard layout does not - have a matching DOS layout representation (or it was not correctly detected), - or the key mapping is wrong. - Some possible fixes: - 1. Use / instead, or ALT-58 for : and ALT-92 for \. - 2. Change the DOS keyboard layout (see Section 7: Keyboard Layout). - 3. Add the commands you want to execute to the [autoexec]-section - of the DOSBox configuration file. - 4. Open the DOSBox configuration file and change the usescancodes entry. - 5. Switch the keyboard layout of your operating system. - - Note that if the host layout can not be identified, or keyboardlayout is set - to none in the DOSBox configuration file, the standard US layout is used. - In this configuration try the keys around "enter" for the key \ (backslash), - and for the key : (colon) use shift and the keys between "enter" and "l". +SOUND: The sound stutters or sounds stretched/weird. + You may be using too much CPU power to keep DOSBox running at the current + speed. You can lower the cycles, skip frames, reduce the sampling rate of + the respective sound device, increase the prebuffer. See section 13: "The + configuration (options) file" + If you are using cycles=max or =auto, then make sure that there is no + background processes interfering! (especially if they access the harddisk) + Also look at Section 10. "How to speed up/slow down DOSBox" -Q: The keyboard lags. -A: Lower the priority setting in the DOSBox configuration file, for example - set "priority=normal,normal". You might also want to try lowering the cycles - (use a fixed cycle count to start with, like cycles=10000). +KEYBOARD: I can't type \ or : in DOSBox. + This can happen in various cases, like your host keyboard layout does not + have a matching DOS layout representation (or it was not correctly + detected), or the key mapping is wrong. + Some possible fixes: + 1. Use / instead, or ALT-58 for : and ALT-92 for \. + 2. Change the DOS keyboard layout (see Section 8: Keyboard Layout). + 3. Add the commands you want to execute to the [autoexec] section + of the DOSBox configuration file. + 4. Open the DOSBox configuration file and change the usescancodes entry. + 5. Switch the keyboard layout of your operating system. + + Note that if the host layout can not be identified, or keyboardlayout is + set to none in the DOSBox configuration file, the standard US layout is + used. In this configuration try the keys around "enter" for the key \ + (backslash), and for the key : (colon) use shift and the keys between + "enter" and "L". -Q: The cursor always moves into one direction! -A: See if it still happens if you disable the joystick emulation, - set joysticktype=none in the [joystick] section of your DOSBox - configuration file. Maybe also try unplugging any joystick/gamepad. - If you want to use the joystick in the game, try setting timed=false - and be sure to calibrate the joystick (both in your OS as well as - in the game or the game's setup program). +KEYBOARD: Right Shift and "\" doesn't work in DOSBox. (Windows only) + This may happen if Windows thinks that you have more than one keyboard + connected to your PC when you use some remote control devices. + To verity this problem run cmd.exe, navigate to DOSBox program folder + and type: + set sdl_videodriver=windib + dosbox.exe + check whether keyboard started to work properly. As windib is slower it is + best to use one of the two solutions provided here: + http://vogons.zetafleet.com/viewtopic.php?t=24072 -Q: The game/application runs much too slow! -A: Look at the section "How to run resource-demanding games" for more - information. +KEYBOARD: The keyboard lags. + Lower the priority setting in the DOSBox configuration file, for example + set "priority=normal,normal". You might also want to try lowering the + cycles (use a fixed cycle amount to start with, like cycles=10000). -Q: The game/application does not run at all/crashes! -A: Look at Section 10: Troubleshooting +CONTROL: The character/cursor/mouse pointer always moves into one direction! + See if it still happens if you disable the joystick emulation, + set joysticktype=none in the [joystick] section of your DOSBox + configuration file. Maybe also try unplugging any joystick/gamepad. + If you want to use the joystick in the game, try setting timed=false + and be sure to calibrate the joystick (both in your OS as well as + in the game or the game's setup program). -Q: Can DOSBox harm my computer? -A: DOSBox can not harm your computer more than any other resource demanding - program. Increasing the cycles does not overclock your real CPU. - Setting the cycles too high has a negative performance effect on the - software running inside DOSBox. +SPEED: The game/application runs much too slow/too fast! + Look at the section 10: "How to speed up/slow down DOSBox" for more + information. -Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. -A: This is possible! Just create a config file: config -writeconf configfile. - Start your favourite editor and look through the settings. To start DOSBox - with your new settings: dosbox -conf configfile - See the description of the config command in Section 4 for more details. +CRASH: The game/application does not run at all/crashes! + Look at Section 11: Troubleshooting -Q: What sound hardware does DOSBox presently emulate? -A: DOSBox emulates several legacy sound devices: - - Internal PC speaker - This emulation includes both the tone generator and several forms of - digital sound output through the internal speaker. - - Creative CMS/Gameblaster - The is the first card released by Creative Labs(R). The default - configuration places it on port 0x220. It should be noted that enabling - this with the Adlib emulation may result in conflicts. - - Tandy 3 voice - The emulation of this sound hardware is complete with the exception of - the noise channel. The noise channel is not very well documented and as - such is only a best guess as to the sound's accuracy. - - Tandy DAC - Emulation of the Tandy DAC utilizes the soundblaster emulation, thus - be sure the soundblaster is not disabled in the DOSBox configuration - file. The Tandy DAC is only emulated at the BIOS level. - - Adlib - This emulation is almost perfect and includes the Adlib's ability to - almost play digitized sound. - - SoundBlaster 16 / SoundBlaster Pro I & II / SoundBlaster I & II - By default DOSBox provides Soundblaster 16 level 16-bit stereo sound. - You can select a different SoundBlaster version in the configfile of - DOSBox (See Internal Commands: CONFIG). - - Disney Soundsource - Using the printer port, this sound device outputs digital sound only. - - Gravis Ultrasound - The emulation of this hardware is nearly complete, though the MIDI - capabilities have been left out, since an MPU-401 has been - emulated in other code. - - MPU-401 - A MIDI passthrough interface is also emulated. This method of sound - output will only work when used with a General Midi or MT-32 device. +CRASH: DOSBox crashes on startup!. + Look at Section 11: Troubleshooting -Q: DOSBox crashes on startup and I'm running arts. -A: This isn't really a DOSBox problem, but the solution is to set the - environment variable SDL_AUDIODRIVER to alsa or oss. +GAME: My Build game(Duke3D/Blood/Shadow Warrior) has problems. + First of all, try to find a port of the game. Those will offer a better + experience. To fix the graphics problem that occurs in DOSBox on higher + resolutions: Open the configuration file of DOSBox and search for + machine=svga_s3. Change svga_s3 to vesa_nolfb + Change memsize=16 to memsize=63 -Q: My Build game(Duke3D/Blood/Shadow Warrior) has problems. -A: First of all, try to find a port of the game. Those will offer a - better experience. To fix the graphics problem that occurs in - DOSBox on higher resolutions. Open the configuration file of - DOSBox and search for machine=svga_s3. Change svga_s3 to vesa_nolfb +SAFETY: Can DOSBox harm my computer? + DOSBox can not harm your computer more than any other resource demanding + program. Increasing the cycles does not overclock your real CPU. + Setting the cycles too high has a negative performance effect on the + software running inside DOSBox. -Q: Great README, but I still don't get it. -A: A look at "The Newbie's pictorial guide to DOSBox" located at - http://vogons.zetafleet.com/viewforum.php?f=39 might help you. - Also try the wiki of DOSBox: - http://www.dosbox.com/wiki/ +OPTIONS: I would like to change DOSBox's options. + Look at Section 13. "The configuration (options) file" -For more questions read the remainder of this README and/or check -the site/forum: -http://www.dosbox.com +HELP: Great Manual, but I still don't get it. + For more questions read the rest of this Manual. You may also look at: + guides located at http://vogons.zetafleet.com/viewforum.php?f=39 + the wiki of DOSBox http://www.dosbox.com/wiki/ + the site/forum: http://www.dosbox.com -========= -3. Usage: -========= +=========================== +3. Command Line Parameters: +=========================== + +An overview of the command line options you can give to DOSBox. Although +in most cases it is easier to use DOSBox's configuration file instead. +See: Section 13. "The configuration (options) file" + +To be able to use Command Line Parameters: +(Windows) open cmd.exe or command.com or edit the shortcut to dosbox.exe +(Linux) use console +(MAC OS X) start terminal.app and navigate to: + /applications/dosbox.app/contents/macos/dosbox -An overview of the command line options you can give to DOSBox. -Windows Users must open cmd.exe or command.com or edit the shortcut to -dosbox.exe for this. The options are valid for all operating systems unless noted in the option description: -dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] - [-lang languagefile] [-machine machinetype] [-noconsole] - [-startmapper] [-noautoexec] [-securemode] - [-scaler scaler | -forcescaler scaler] - [-version] +dosbox [name] [-exit] [-c command] [-fullscreen] [-userconf] + [-conf congfigfilelocation] [-lang languagefilelocation] + [-machine machine type] [-noconsole] [-startmapper] [-noautoexec] + [-securemode] [-scaler scaler | -forcescaler scaler] [-version] + [-socket socket] dosbox -version dosbox -editconf program dosbox -opencaptures program dosbox -printconf dosbox -eraseconf +dosbox -erasemapper - name + name If "name" is a directory it will mount that as the C: drive. - If "name" is an executable it will mount the directory of "name" + If "name" is an executable it will mount the directory of "name" as the C: drive and execute "name". - - -exit + + -exit DOSBox will close itself when the DOS application "name" ends. -c command Runs the specified command before running "name". Multiple commands can be specified. Each command should start with "-c" though. - A command can be: an Internal Program, a DOS command or an executable + A command can be: an Internal Program, a DOS command or an executable on a mounted drive. -fullscreen Starts DOSBox in fullscreen mode. - -conf configfile - Start DOSBox with the options specified in "configfile". - Multiple -conf options may be present. - See Section 11 for more details. + -userconf + Start DOSBox with the users specific configuration file. Can be used + together with multiple -conf parameters, but -userconf will always be + loaded before them. - -lang languagefile - Start DOSBox using the language specified in "languagefile". + -conf configfilelocation + Start DOSBox with the options specified in "configfilelocation". + Multiple -conf options may be present. + See Section 13 for more details. + + -lang languagefilelocation + Start DOSBox using the language specified in "languagefilelocation". + See Section 14 for more details. -machine machinetype Setup DOSBox to emulate a specific type of machine. Valid choices are: - hercules, cga, pcjr, tandy, svga_s3 (default) as well as the additional - svga chipsets listed in the help of the DOSBox configuration file. + hercules, cga, ega, pcjr, tandy, svga_s3 (default) as well as + the additional svga chipsets listed in the DOSBox configuration file. svga_s3 enables vesa emulation as well. For some special vga effects the machinetype vgaonly can be used, - note that this disables svga capabilites and might be (considerably) - slower due to the much higher emulation precision. - The machinetype affects both the videocard and the available soundcards. + note that this disables svga capabilities and might be slower due to the + higher emulation precision. + The machinetype affects the video card and the available sound cards. -noconsole (Windows Only) - Start DOSBox without showing the console window. Output will - be redirected to stdout.txt and stderr.txt - + Start DOSBox without showing DOSBox Status Window (console). + Output will be redirected to stdout.txt and stderr.txt + -startmapper - Enter the keymapper directly on startup. Useful for people with + Enter the keymapper directly on startup. Useful for people with keyboard problems. -noautoexec Skips the [autoexec] section of the loaded configuration file. -securemode - Same as -noautoexec, but adds config.com -securemode at the + Same as -noautoexec, but adds config.com -securemode at the bottom of AUTOEXEC.BAT (which in turn disables any changes to how the drives are mounted inside DOSBox). -scaler scaler - Uses the scaler specified by "scaler". See the DOSBox configuration - file for the available scalers. + Uses the scaler specified by "scaler". See the DOSBox configuration file + for the available scalers. -forcescaler scaler Similar to the -scaler parameter, but tries to force usage of @@ -463,30 +504,36 @@ dosbox -eraseconf move to second program if the first one fails to start. -opencaptures program - calls program with as first paramater the location of the captures + calls program with as first parameter the location of the captures folder. - + -printconf prints the location of the default configuration file. - -eraseconf + -resetconf removes the default configuration file. -Note: If a name/command/configfile/languagefile contains a space, put - the whole name/command/configfile/languagefile between quotes - ("command or file name"). If you need to use quotes within quotes - (most likely with -c and mount): - Windows and OS/2 users can use single quotes inside the double quotes. - Other people should be able to use escaped double quotes inside the - double quotes. - Windows: -c "mount c 'c:\program files\'" - Linux: -c "mount c \"/tmp/name with space\"" + -resetmapper + removes the mapperfile used by the default clean configuration file. -For example (Windows): + -socket + passes the socket number to the nullmodem emulation. See Section 9: + "Serial Multiplayer feature." -dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" - This mounts c:\atlantis as c:\ and runs atlantis.exe. - Before it does that it would first mount C:\SAVES as the D drive. +Note: If a name/command/configfilelocation/languagefilelocation contains + a space, put the whole name/command/configfilelocation/languagefilelocation + between quotes ("command or file name"). If you need to use quotes within + quotes (most likely with -c and mount): + Windows and OS/2 users can use single quotes inside the double quotes. + Other people should be able to use escaped double quotes inside the + double quotes. + Windows: -c "mount c 'c:\My folder with DOS games\'" + Linux: -c "mount c \"/tmp/name with space\"" + +A rather unusual example, just to demonstrate what you can do (Windows): +dosbox D:\folder\file.exe -c "MOUNT Y H:\MyFolder" + This mounts D:\folder as C:\ and runs file.exe. + Before it does that, it will first mount H:\MyFolder as the Y drive. In Windows, you can also drag directories/files onto the DOSBox executable. @@ -499,10 +546,10 @@ In Windows, you can also drag directories/files onto the DOSBox executable. DOSBox supports most of the DOS commands found in command.com. To get a list of the internal commands type "HELP" at the prompt. -In addition, the following commands are available: +In addition, the following commands are available: -MOUNT "Emulated Drive letter" "Real Drive or Directory" - [-t type] [-aspi] [-ioctl] [-noioctl] [-usecd number] [-size drivesize] +MOUNT "Emulated Drive letter" "Real Drive or Directory" + [-t type] [-aspi] [-ioctl] [-noioctl] [-usecd number] [-size drivesize] [-label drivelabel] [-freesize size_in_mb] [-freesize size_in_kb (floppies)] MOUNT -cd @@ -511,16 +558,17 @@ MOUNT -u "Emulated Drive letter" Program to mount local directories as drives inside DOSBox. "Emulated Drive letter" - The driveletter inside DOSBox (eg. C). + The driveletter inside DOSBox (for example C). "Real Drive letter (usually for CD-ROMs in Windows) or Directory" The local directory you want accessible inside DOSBox. -t type - Type of the mounted directory. Supported are: dir (default), - floppy, cdrom. + Type of the mounted directory. + Supported are: dir (default), floppy, cdrom. -size drivesize + (experts only) Sets the size of the drive, where drivesize is of the form "bps,spc,tcl,fcl": bps: bytes per sector, by default 512 for regular drives and @@ -530,16 +578,16 @@ MOUNT -u "Emulated Drive letter" fcl: total free clusters, between 1 and tcl -freesize size_in_mb | size_in_kb - Sets the amount of free space available on a drive in megabytes - (regular drives) or kilobytes (floppy drives). - This is a simpler version of -size. + Sets the amount of free space available on a drive + in megabytes (regular drives) or kilobytes (floppy drives). + This is a simpler version of -size. -label drivelabel - Sets the name of the drive to "drivelabel". Needed on some - systems if the CD-ROM label isn't read correctly (useful when a - program can't find its CD-ROM). If you don't specify a label and no - lowlevel support is selected (that is omitting the -usecd # and/or - -aspi parameters, or specifying -noioctl): + Sets the name of the drive to "drivelabel". Needed on some systems + if the CD-ROM label isn't read correctly (useful when a program + can't find its CD-ROM). If you don't specify a label + and no lowlevel support is selected (that is omitting the -usecd # + and/or -aspi parameters, or specifying -noioctl): For Windows: label is extracted from "Real Drive". For Linux: label is set to NO_LABEL. @@ -547,18 +595,18 @@ MOUNT -u "Emulated Drive letter" is mounted. It will not be updated !! -aspi - Forces use of the aspi layer. Only valid if mounting a CD-ROM under + Forces use of the aspi layer. Only valid if mounting a CD-ROM under Windows systems with an ASPI-Layer. -ioctl (automatic selection of the CD audio interface) -ioctl_dx (digital audio extraction used for CD audio) -ioctl_dio (ioctl calls used for CD audio) -ioctl_mci (MCI used for CD audio) - Forces use of ioctl commands. Only valid if mounting a CD-ROM under + Forces use of ioctl commands. Only valid if mounting a CD-ROM under a Windows OS which support them (Win2000/XP/NT). The various choices only differ in the way CD audio is handled, - preferrably -ioctl_dio is used (lowest workload), but this might not - work on all systems so -ioctl_dx (or -ioctl_mci) can be used. + preferably -ioctl_dio is used (lowest workload), but this might not + work on all systems, so -ioctl_dx (or -ioctl_mci) can be used. -noioctl Forces use of the SDL CD-ROM layer. Valid on all systems. @@ -577,48 +625,78 @@ MOUNT -u "Emulated Drive letter" -u Removes the mount. Doesn't work for Z:\. - Note: It's possible to mount a local directory as CD-ROM drive. - Hardware support is then missing. + Note: It's possible to mount a local directory as CD-ROM drive, + but hardware support is then missing. Basically MOUNT allows you to connect real hardware to DOSBox's emulated PC. So MOUNT C C:\GAMES tells DOSBox to use your C:\GAMES directory as drive C: - in DOSBox. It also allows you to change the drive letter identification - for programs that demand specific drive letters. - - For example: Touche: Adventures of The Fifth Musketeer must be run on your C: - drive. Using DOSBox and its mount command, you can trick the game into - believing it is on the C drive, while you can still place it where you - like. For example, if the game is in D:\OLDGAMES\TOUCHE, the command - MOUNT C D:\OLDGAMES will allow you to run Touche from the D drive. + in DOSBox. MOUNT C E:\SomeFolder tells DOSBox to use your E:\SomeFolder + directory as drive C: in DOSBox. Mounting your entire C drive with MOUNT C C:\ is NOT recommended! The same is true for mounting the root of any other drive, except for CD-ROMs (due to - their read-only nature). Otherwise if you or DOSBox make a mistake you may - lose all your files. - It is recommended to put all your applications/games into a subdirectory - and mount that. + their read-only nature). + Otherwise if you or DOSBox make a mistake you may lose all your files. + Also never mount a "Windows" or "Program Files" folders or their subfolders + in Windows Vista/7 as DOSBox may not work correctly, or will stop working + correctly later. It is recommended to keep all your dos applications/games + in a simple folder (for example c:\dosgames) and mount that. - General MOUNT Examples: - 1. To mount c:\DirX as a floppy : - mount a c:\DirX -t floppy - 2. To mount system CD-ROM drive E as CD-ROM drive D in DOSBox: - mount d e:\ -t cdrom - 3. To mount system CD-ROM drive at mountpoint /media/cdrom as CD-ROM drive D - in DOSBox: - mount d /media/cdrom -t cdrom -usecd 0 - 4. To mount a drive with ~870 mb free diskspace (simple version): - mount c d:\ -freesize 870 - 5. To mount a drive with ~870 mb free diskspace (experts only, full control): - mount c d:\ -size 512,127,16513,13500 - 6. To mount /home/user/dirY as drive C in DOSBox: - mount c /home/user/dirY - 7. To mount the directory where DOSBox was started as D in DOSBox: - mount d . - (note the . which represents the directory where DOSBox was started) + You should always install your game inside DOSBox. + So if you have the game on CD you always (even after installation!) + have to mount both: folder as a harddisk drive and a CD-ROM. + HardDisk should always be mounted as c + CD-ROM should always be mounted as d + Floppy should always be mounted as a (or b) + + Basic MOUNT Examples for normal usage (Windows): + + 1. To mount a folder as a harddisk drive: + mount c d:\dosgames + + 3. To mount your CD-ROM drive E as CD-ROM drive D in DOSBox: + mount d e:\ -t cdrom + + 2. To mount your drive a: as a floppy: + mount a a:\ -t floppy + + Advanced MOUNT examples (Windows): + + 4. To mount a hard disk drive with ~870 mb free diskspace (simple version): + mount c d:\dosgames -freesize 870 + + 5. To mount a drive with ~870 mb free diskspace (experts only, full control): + mount c d:\dosgames -size 512,127,16513,13500 + + 1. To mount c:\dosgames\floppy as a floppy: + mount a c:\dosgames\floppy -t floppy + + + Other MOUNT examples: + + 3. To mount system CD-ROM drive at mountpoint /media/cdrom as CD-ROM drive D + in DOSBox: + mount d /media/cdrom -t cdrom -usecd 0 + + 6. To mount /home/user/dosgames as drive C in DOSBox: + mount c /home/user/dosgames + + 7. To mount the directory where DOSBox was started as C in DOSBox: + mount c . + (note the . which represents the directory where DOSBox was started, + on Windows Vista/7 don't use this if you installed DOSBox + to your "Program Files" folder) + + If you want to mount a CD image or floppy image, check IMGMOUNT. + MOUNT also works with images but only if you use external program, + for example (both are free): + - Daemon Tools Lite (for CD images), + - Virtual Floppy Drive (for floppy images). + Although IMGMOUNT can give better compatibility. MEM - Program to display the amount of free memory. + Program to display the amount and type of free memory. VER @@ -626,56 +704,57 @@ VER set major_version [minor_version] Display the current DOSBox version and reported DOS version (parameterless usage). Change the reported DOS version with the "set" parameter, - for example: "VER set 6 22" to have DOSBox report DOS 6.22 - as version number. + for example: "VER set 6 22" to have DOSBox report DOS 6.22 as version number. -CONFIG -writeconf localfile -CONFIG -writelang localfile +CONFIG -writeconf filelocation +CONFIG -writelang filelocation CONFIG -securemode CONFIG -set "section property=value" CONFIG -get "section property" - CONFIG can be used to change or query various settings of DOSBox + CONFIG can be used to change or query various settings of DOSBox during runtime. It can save the current settings and language strings to - disk. Information about all possible sections and properties can - be found in Section 11 (The Config File). + disk. Information about all possible sections and properties can + be found in Section 13: "The configuration (options) file". - -writeconf localfile - Write the current configuration settings to file. "localfile" is - located on the local drive, not a mounted drive in DOSBox. - The configuration file controls various settings of DOSBox: - the amount of emulated memory, the emulated soundcards and many more - things. It allows access to AUTOEXEC.BAT as well. - See Section 11 (The Config File) for more information. + -writeconf filelocation + Write the current configuration settings to a file in a specified location. + "filelocation" is located on the local drive, not a mounted drive in DOSBox. + The configuration file controls various settings of DOSBox: + the amount of emulated memory, the emulated sound cards and many more + things. It allows access to AUTOEXEC.BAT as well. + See Section 13: "The configuration (options) file" for more information. - -writelang localfile - Write the current language settings to file. "localfile" is - located on the local drive, not a mounted drive in DOSBox. - The language file controls all visible output of the internal commands - and the internal DOS. + -writelang filelocation + Write the current language settings to a file in a specified location. + "filelocation" is located on the local drive, not a mounted drive + in DOSBox. The language file controls all visible output of the internal + commands and the internal DOS. + See Section 14: "The Language File" for more information. -securemode - Switches DOSBox to a more secure mode. In this mode the internal - commands MOUNT, IMGMOUNT and BOOT won't work. It's not possible either - to create a new configfile or languagefile in this mode. - (Warning: you can only undo this mode by restarting DOSBox.) + Switches DOSBox to a more secure mode. In this mode the internal + commands MOUNT, IMGMOUNT and BOOT won't work. It's not possible either + to create a new configfile or languagefile in this mode. + (Warning: you can only undo this mode by restarting DOSBox.) -set "section property=value" - CONFIG will attempt to set the property to new value. Currently - CONFIG can not report whether the command succeeded or not. + CONFIG will attempt to set the property to new value. + Currently CONFIG can not report whether the command succeeded or not. -get "section property" - The current value of the property is reported and stored in the - environment variable %CONFIG%. This can be used to store the value - when using batch files. + The current value of the property is reported and stored in the + environment variable %CONFIG%. This can be used to store the value + when using batch files. Both "-set" and "-get" work from batch files and can be used to set up your - own preferences for each game. - + own preferences for each game. Although it may be easier to use separate + DOSBox's configuration files for each game instead. + Examples: - 1. To create a configfile in your current directory: - config -writeconf dosbox.conf + 1. To create a configuration file in your c:\dosgames directory: + config -writeconf c:\dosgames\dosbox.conf 2. To set the cpu cycles to 10000: config -set "cpu cycles=10000" 3. To turn ems memory emulation off: @@ -687,120 +766,134 @@ CONFIG -get "section property" LOADFIX [-size] [program] [program-parameters] LOADFIX -f Program to reduce the amount of available conventional memory. - Useful for old programs which don't expect much memory to be free. + Useful for old programs which don't expect much memory to be free. - -size + -size number of kilobytes to "eat up", default = 64kb - + -f frees all previously allocated memory - + Examples: - 1. To start mm2.exe and allocate 64kb memory - (mm2 will have 64 kb less available) : + 1. To start mm2.exe and allocate 64kb memory + (mm2 will have 64 kb less available): loadfix mm2 - 2. To start mm2.exe and allocate 32kb memory : + 2. To start mm2.exe and allocate 32kb memory: loadfix -32 mm2 - 3. To free previous allocated memory : + 3. To free previous allocated memory: loadfix -f RESCAN Make DOSBox reread the directory structure. Useful if you changed something on a mounted drive outside of DOSBox. (CTRL - F4 does this as well!) - + MIXER - Makes DOSBox display its current volume settings. + Makes DOSBox display its current volume settings. Here's how you can change them: - + mixer channel left:right [/NOSHOW] [/LISTMIDI] - + channel - Can be one of the following: MASTER, DISNEY, SPKR, GUS, SB, FM [, CDAUDIO]. - CDAUDIO is only available if a CD-ROM interface with volume control is - enabled (CD image, ioctl_dx). - + Can be one of the following: MASTER, DISNEY, SPKR, GUS, SB, FM [, CDAUDIO]. + CDAUDIO is only available if a CD-ROM interface with volume control is + enabled (CD image, ioctl_dx). + left:right - The volume levels in percentages. If you put a D in front it will be - in decibel (Example: mixer gus d-10). - + The volume levels in percentages. If you put a D in front it will be + in decibel (Example: mixer gus d-10). + /NOSHOW - Prevents DOSBox from showing the result if you set one - of the volume levels. + Prevents DOSBox from showing the result if you set one + of the volume levels. /LISTMIDI - Lists the available midi devices on your PC (Windows). To select a - device other than the Windows default midi-mapper, add a line - 'midiconfig=id' to the [midi] section in the configuration file, - where 'id' is the number for the device as listed by LISTMIDI. + In Windows lists the available midi devices on your PC. To select a device + other than the Windows default midi-mapper, change the line 'midiconfig=' + in the [midi] section of the configuration file to 'midiconfig=id', where + 'id' is the number for the device as listed by LISTMIDI. eg. midiconfig=2 + + In Linux this option doesn't work, but you get similar results by using + 'pmidi -l' in console. Then change the line 'midiconfig=' to + 'midiconfig=port', where 'port' is the port for the device as listed by + 'pmidi -l'. eg. midiconfig=128:0 IMGMOUNT A utility to mount disk images and CD-ROM images in DOSBox. - - IMGMOUNT DRIVE [imagefile] -t [image_type] -fs [image_format] + + IMGMOUNT DRIVE [imagefile] -t [image_type] -fs [image_format] -size [sectorsbytesize, sectorsperhead, heads, cylinders] - IMGMOUNT DRIVE [imagefile1, .. ,imagefileN] -t iso -fs iso + IMGMOUNT DRIVE [imagefile1 imagefile2 .. imagefileN] -t cdrom -fs iso imagefile - Location of the image file to mount in DOSBox. The location can - be on a mounted drive inside DOSBox, or on your real disk. It is - possible to mount CD-ROM images (ISOs or CUE/BIN) as well, if you - need CD swapping capabilities specify all images in succession + Location of the image file to mount in DOSBox. The location can be + on a mounted drive inside DOSBox, or on your real disk. It is possible + to mount CD-ROM images (ISOs or CUE/BIN or CUE/IMG) too. + If you need CD swapping capabilities, specify all images in succession (see the next entry). - CUE/BIN pairs are the preferred CD-ROM image type as they can + CUE/BIN pairs and cue/img are the preferred CD-ROM image types as they can store audio tracks compared to ISOs (which are data-only). For the CUE/BIN mounting always specify the CUE sheet. - - imagefile1, .. ,imagefileN + + imagefile1 imagefile2 .. imagefileN Location of the image files to mount in DOSBox. Specifying a number - of image files is only allowed for CD-ROM images. The CD's can be - swapped with CTRL-F4 at any time. This is required for games which - use multiple CD-ROMs and require the CD to be switched during the - gameplay at some point. - - -t + of image files is only allowed for CD-ROM images. + The CD's can be swapped with CTRL-F4 at any time. + This is required for games which use multiple CD-ROMs and require the CD + to be switched during the gameplay at some point. + + -t The following are valid image types: floppy: Specifies a floppy image. DOSBox will automatically identify the disk geometry (360K, 1.2MB, 720K, 1.44MB, etc). - iso: Specifies a CD-ROM iso image. The geometry is automatic and - set for this size. This can be an iso or a cue/bin pair. - hdd: Specifies a harddrive image. The proper CHS geometry - must be set for this to work. + cdrom: Specifies a CD-ROM image. The geometry is automatic and + set for this size. This can be an iso or a cue/bin pair or + a cue/img pair. + hdd: Specifies a harddrive image. The proper CHS geometry must be set + for this to work. - -fs + -fs The following are valid file system formats: iso: Specifies the ISO 9660 CD-ROM format. - fat: Specifies that the image uses the FAT file system. DOSBox will attempt - to mount this image as a drive in DOSBox and make the files - available from inside DOSBox. + fat: Specifies that the image uses the FAT file system. DOSBox will + attempt to mount this image as a drive in DOSBox and make + the files available from inside DOSBox. none: DOSBox will make no attempt to read the file system on the disk. - This is useful if you need to format it or if you want to boot - the disk using the BOOT command. When using the "none" - filesystem, you must specify the drive number (2 or 3, - where 2 = master, 3 = slave) rather than a drive letter. - For example, to mount a 70MB image as the slave drive device, + This is useful if you need to format it or if you want to boot + the disk using the BOOT command. When using the "none" + filesystem, you must specify the drive number (2 or 3, + where 2 = master, 3 = slave) rather than a drive letter. + For example, to mount a 70MB image as the slave drive device, you would type (without the quotes): - "imgmount 3 d:\test.img -size 512,63,16,142 -fs none" + "imgmount 3 d:\test.img -size 512,63,16,142 -fs none" Compare this with a mount to be able to access the drive - within DOSBox, which would read as: + within DOSBox, which would read as: "imgmount e: d:\test.img -size 512,63,16,142" - -size + -size The Cylinders, Heads and Sectors of the drive. Required to mount hard drive images. - - An example how to mount CD-ROM images: - 1a. mount c /tmp - 1b. imgmount d c:\myiso.iso -t iso + + An example how to mount CD-ROM images (in Linux): + 1. imgmount d /tmp/cdimage1.cue /tmp/cdimage2.cue -t cdrom or (which also works): - 2. imgmount d /tmp/myiso.iso -t iso + 2a. mount c /tmp + 2b. imgmount d c:\cdimage1.cue c:\cdimage2.cue -t cdrom + (in Windows): + imgmount d f:\img\CD1.cue f:\img\CD2.cue f:\img\CD3.cue -t cdrom + imgmount d "g:\img\7th Guest CD1.cue" "g:\img\7th Guest CD2.cue" -t cdrom + Don't forget that you can also use MOUNT with images, but only if you use + external program, for example (both are free): + - Daemon Tools Lite (for CD images), + - Virtual Floppy Drive (for floppy images). + Although IMGMOUNT can give better compatibility. BOOT - Boot will start floppy images or hard disk images independent of the - operating system emulation offered by DOSBox. This will allow you to + Boot will start floppy images or hard disk images independent of + the operating system emulation offered by DOSBox. This will allow you to play booter floppies or boot other operating systems inside DOSBox. If the target emulated system is PCjr (machine=pcjr) the boot command can be used to load PCjr cartridges (.jrc). @@ -808,19 +901,19 @@ BOOT BOOT [diskimg1.img diskimg2.img .. diskimgN.img] [-l driveletter] BOOT [cart.jrc] (PCjr only) - diskimgN.img - This can be any number of floppy disk images one wants mounted after + diskimg1.img diskimg2.img .. diskimgN.img + This can be any number of floppy disk images one wants mounted after DOSBox boots the specified drive letter. - To swap between images, hit CTRL-F4 to change from the current disk - to the next disk in the list. The list will loop back from the last + To swap between images, hit CTRL-F4 to change from the current disk + to the next disk in the list. The list will loop back from the last disk image to the beginning. [-l driveletter] - This parameter allows you to specify the drive to boot from. - The default is the A drive, the floppy drive. You can also boot - a hard drive image mounted as master by specifying "-l C" + This parameter allows you to specify the drive to boot from. + The default is the A drive, the floppy drive. You can also boot + a hard drive image mounted as master by specifying "-l C" without the quotes, or the drive as slave by specifying "-l D" - + cart.jrc (PCjr only) When emulation of a PCjr is enabled, cartridges can be loaded with the BOOT command. Support is still limited. @@ -830,50 +923,50 @@ IPX You need to enable IPX networking in the configuration file of DOSBox. - All of the IPX networking is managed through the internal DOSBox program - IPXNET. For help on the IPX networking from inside DOSBox, type - "IPXNET HELP" (without quotes) and the program will list the commands - and relevant documentation. + All of the IPX networking is managed through the internal DOSBox program + IPXNET. For help on the IPX networking from inside DOSBox, type + "IPXNET HELP" (without quotes) and the program will list the commands + and relevant documentation. - With regard to actually setting up a network, one system needs to be + With regard to actually setting up a network, one system needs to be the server. To set this up, type "IPXNET STARTSERVER" (without the quotes) in a DOSBox session. The server DOSBox session will automatically add itself to the virtual IPX network. For every additional computer that should be part of the virtual IPX network, you'll need to type - "IPXNET CONNECT ". + "IPXNET CONNECT ". For example, if your server is at bob.dosbox.com, you would type - "IPXNET CONNECT bob.dosbox.com" on every non-server system. - - To play games that need Netbios a file named NETBIOS.EXE from Novell is - needed. Establish the IPX connection as explained above, then run - "netbios.exe". + "IPXNET CONNECT bob.dosbox.com" on every non-server system. - The following is an IPXNET command reference: + To play games that need Netbios a file named NETBIOS.EXE from Novell is + needed. Establish the IPX connection as explained above, then run + "netbios.exe". - IPXNET CONNECT + The following is an IPXNET command reference: - IPXNET CONNECT opens a connection to an IPX tunnelling server - running on another DOSBox session. The "address" parameter specifies - the IP address or host name of the server computer. You can also - specify the UDP port to use. By default IPXNET uses port 213 - the - assigned IANA port for IPX tunnelling - for its connection. + IPXNET CONNECT - The syntax for IPXNET CONNECT is: - IPXNET CONNECT address + IPXNET CONNECT opens a connection to an IPX tunneling server + running on another DOSBox session. The "address" parameter specifies + the IP address or host name of the server computer. You can also + specify the UDP port to use. By default IPXNET uses port 213 - the + assigned IANA port for IPX tunneling - for its connection. - IPXNET DISCONNECT + The syntax for IPXNET CONNECT is: + IPXNET CONNECT address - IPXNET DISCONNECT closes the connection to the IPX tunnelling server. + IPXNET DISCONNECT - The syntax for IPXNET DISCONNECT is: - IPXNET DISCONNECT + IPXNET DISCONNECT closes the connection to the IPX tunneling server. - IPXNET STARTSERVER + The syntax for IPXNET DISCONNECT is: + IPXNET DISCONNECT - IPXNET STARTSERVER starts an IPX tunnelling server on this DOSBox - session. By default, the server will accept connections on UDP port - 213, though this can be changed. Once the server is started, DOSBox - will automatically start a client connection to the IPX tunnelling server. + IPXNET STARTSERVER + + IPXNET STARTSERVER starts an IPX tunneling server on this DOSBox + session. By default, the server will accept connections on UDP port + 213, though this can be changed. Once the server is started, DOSBox + will automatically start a client connection to the IPX tunneling server. The syntax for IPXNET STARTSERVER is: IPXNET STARTSERVER @@ -886,40 +979,43 @@ IPX IPXNET STOPSERVER - IPXNET STOPSERVER stops the IPX tunnelling server running on this DOSBox - session. Care should be taken to ensure that all other connections have - terminated as well, since stopping the server may cause lockups on other - machines that are still using the IPX tunnelling server. + IPXNET STOPSERVER stops the IPX tunneling server running on this DOSBox + session. Care should be taken to ensure that all other connections have + terminated as well, since stopping the server may cause lockups on other + machines that are still using the IPX tunneling server. - The syntax for IPXNET STOPSERVER is: - IPXNET STOPSERVER + The syntax for IPXNET STOPSERVER is: + IPXNET STOPSERVER IPXNET PING - IPXNET PING broadcasts a ping request through the IPX tunnelled network. - In response, all other connected computers will respond to the ping - and report the time it took to receive and send the ping message. + IPXNET PING broadcasts a ping request through the IPX tunneled network. + In response, all other connected computers will respond to the ping + and report the time it took to receive and send the ping message. - The syntax for IPXNET PING is: + The syntax for IPXNET PING is: IPXNET PING IPXNET STATUS - IPXNET STATUS reports the current state of this DOSBox session's - IPX tunnelling network. For a list of all computers connected to the - network use the IPXNET PING command. + IPXNET STATUS reports the current state of this DOSBox session's + IPX tunneling network. For a list of all computers connected to the + network use the IPXNET PING command. - The syntax for IPXNET STATUS is: - IPXNET STATUS + The syntax for IPXNET STATUS is: + IPXNET STATUS -KEYB [languagecode [codepage [codepagefile]]] - Change the keyboard layout. For detailed information about keyboard - layouts please see Section 7. +KEYB [keyboardlayoutcode [codepage [codepagefile]]] - [languagecode] is a string consisting of two (in special cases more) - characters, examples are GK (Greece) or IT (Italy). It specifies - the keyboard layout to be used. + Change the keyboard layout. For detailed information about keyboard layouts + please see Section 8: "Keyboard Layout" + + [keyboardlayoutcode] is a string consisting of five or less characters, + examples are PL214 (Polish typists) or PL457 (Polish programmers). + It specifies the keyboard layout to be used. + The list of all layouts built into DOSBox is here: + http://vogons.zetafleet.com/viewtopic.php?t=21824 [codepage] is the number of the codepage to be used. The keyboard layout has to provide support for the specified codepage, otherwise the layout @@ -929,17 +1025,19 @@ KEYB [languagecode [codepage [codepagefile]]] [codepagefile] can be used to load codepages that are yet not compiled into DOSBox. This is only needed when DOSBox does not find the codepage. - + If no codepagefile is specified, but you place all ten ega.cpx files + (from FreeDOS) in the DOSBox program folder, an appropriate codepagefile + for the requested layout/codepage is chosen automatically. Examples: - 1. To load the german keyboard layout (automatically uses codepage 858): - keyb gr - 2. To load the russian keyboard layout with codepage 866: - keyb ru 866 + 1. To load the polish typist keys layout (automatically uses codepage 852): + keyb pl214 + 2. To load one of russian keyboard layouts with codepage 866: + keyb ru441 866 In order to type russian characters press ALT+RIGHT-SHIFT. - 3. To load the french keyboard layout with codepage 850 (where the + 3. To load one of french keyboard layouts with codepage 850 (where the codepage is defined in EGACPI.DAT): - keyb fr 850 EGACPI.DAT + keyb fr189 850 EGACPI.DAT 4. To load codepage 858 (without a keyboard layout): keyb none 858 This can be used to change the codepage for the FreeDOS keyb2 utility. @@ -959,7 +1057,8 @@ For more information use the /? command line switch with the programs. ALT-ENTER Switch to full screen and back. ALT-PAUSE Pause emulation (hit ALT-PAUSE again to continue). CTRL-F1 Start the keymapper. -CTRL-F4 Change between mounted disk-images. Update directory cache for all drives! +CTRL-F4 Change between mounted floppy/CD images. Update directory cache + for all drives. CTRL-ALT-F5 Start/Stop creating a movie of the screen. (avi video capturing) CTRL-F5 Save a screenshot. (PNG format) CTRL-F6 Start/Stop recording sound output to a wave file. @@ -970,31 +1069,80 @@ CTRL-F8 Increase frameskip. CTRL-F9 Kill DOSBox. CTRL-F10 Capture/Release the mouse. CTRL-F11 Slow down emulation (Decrease DOSBox Cycles). -CTRL-F12 Speed up emulation (Increase DOSBox Cycles). -ALT-F12 Unlock speed (turbo button). +CTRL-F12 Speed up emulation (Increase DOSBox Cycles)*. +ALT-F12 Unlock speed (turbo button/fast forward)**. +F11, ALT-F11 (machine=cga) change tint in NTSC output modes*** +F11 (machine=hercules) cycle through amber, green, white colouring*** -(NOTE: Once you increase your DOSBox cycles beyond your computer's maximum -capacity, it will produce the same effect as slowing down the emulation. -This maximum will vary from computer to computer.) +*NOTE: Once you increase your DOSBox cycles beyond your computer CPU resources, + it will produce the same effect as slowing down the emulation. + This maximum will vary from computer to computer. +**NOTE: You need free CPU resources for this (the more you have, the faster + it goes), so it won't work at all with cycles=max or a too high amount + of fixed cycles. You have to keep the keys pressed for it to work! + +***NOTE: These keys won't work if you saved a mapper file earlier with + a different machine type. So either reassign them or reset the mapper. These are the default keybindings. They can be changed in the keymapper -(see Section 6: Mapper). +(see Section 7: KeyMapper). -Saved/recorded files can be found in current_directory/capture -(this can be changed in the DOSBox configuration file). -The directory has to exist prior to starting DOSBox, otherwise nothing -gets saved/recorded ! +In MAC OS you can try using cmd(applekey) together with Ctrl if the key doesn't +work eg. cmd-ctrl-F1, but some keys may still need remapping (in Linux too). + +Saved/recorded files can be found in: + (Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Extras + (Linux) ~/.dosbox/capture + (MAC OS X) "~/Library/Preferences/capture" +This can be changed in the DOSBox configuration file. -========== -6. Mapper: -========== +==================== +6. Joystick/Gamepad: +==================== -When you start the DOSBox mapper (either with CTRL-F1 or -startmapper as -a command line argument to the DOSBox executable) you are presented with -a virtual keyboard and a virtual joystick. +The standard joystick port in DOS supports a maximum of 4 axes and 4 buttons. +For more, different modifications of that configuration were used. + +To force DOSBox to use a different type of emulated joystick/gamepad, the entry +"joysticktype" in the [joystick] section of the DOSBox configuration file can +be used. + +none - disables controller support. +auto - (default) autodetects whether you have one or two controllers connected: + if you have one - '4axis' setting is used, + if you have two - '2axis' setting is used. +2axis - If you have two controllers connected, each will emulate a joystick + with 2 axes and 2 buttons. If you have only one controller connected, + it will emulate a joystick with only 2 axis and 2 buttons. +4axis - supports only first controller, emulates a joystick + with 4 axis and 4 buttons or a gamepad with 2axis and 6 buttons. +4axis_2 - supports only second controller. +fcs - supports only first controller, emulates ThrustMaster + Flight Control System, with 3-axes, 4 buttons and 1 hat. +ch - supports only first controller, emulates CH Flightstick, + with 4-axes, 6 buttons and 1 hat, but you cannot press more + than one button at the same time. + +You also have to configure controller properly inside the game. +It is important to remember that if you saved the mapperfile without joystick +connected, or with a different joystick setting, your new setting will not work +properly, or not work at all, until you reset DOSBox's mapperfile. + +If controller is working properly outside DOSBox, but doesn't calibrate properly +inside DOSBox, try different 'timed' setting in DOSBox's configuration file. + + + +============= +7. KeyMapper: +============= + +You start the DOSBox mapper either with CTRL-F1 (see section 5. Special Keys) +or -startmapper (see Section 3. Command Line Parameters). +You are presented with a virtual keyboard and a virtual joystick. These virtual devices correspond to the keys and events DOSBox will report to the DOS applications. If you click on a button with your mouse, @@ -1002,27 +1150,29 @@ you can see in the lower left corner with which event it is associated (EVENT) and to what events it is currently bound. Event: EVENT -BIND: BIND - Add Del -mod1 hold Next +BIND: BIND (the real key/button/axis you push with your finger/hand) + + Add Del +mod1 hold Next mod2 mod3 EVENT The key or joystick axis/button/hat DOSBox will report to DOS applications. + (the event that will happen during the game, (eg. shooting/jumping/walking) BIND The key on your real keyboard or the axis/button/hat on your real - joystick(s) (as reported by SDL) which is connected to the EVENT. -mod1,2,3 - Modfiers. These are keys you need to have to be pressed while pressing + joystick(s) (as reported by SDL), which is connected to the EVENT. +mod1,2,3 + Modifiers. These are keys you need to have to be pressed while pressing BIND. mod1 = CTRL and mod2 = ALT. These are generally only used when you want to change the special keys of DOSBox. -Add +Add Add a new BIND to this EVENT. Basically add a key from your keyboard or an - event from the joystick (button press, axis/hat movement) which will + event from the joystick (button press, axis/hat movement) which will produce the EVENT in DOSBox. -Del +Del Delete the BIND to this EVENT. If an EVENT has no BINDS, then it is not possible to trigger this event in DOSBox (that is there's no way to type the key or use the respective action of the joystick). @@ -1032,18 +1182,18 @@ Next Example: Q1. You want to have the X on your keyboard to type a Z in DOSBox. - A. Click on the Z on the keyboard mapper. Click "Add". - Now press the X key on your keyboard. + A. Click on the Z on the keyboard mapper. Click "Add". + Now press the X key on your keyboard. -Q2. If you click "Next" a couple of times, you will notice that the Z on your +Q2. If you click "Next" a couple of times, you will notice that the Z on your keyboard also produces an Z in DOSBox. - A. Therefore select the Z again, and click "Next" until you have the Z on + A. Therefore select the Z again, and click "Next" until you have the Z on your keyboard. Now click "Del". Q3. If you try it out in DOSBox, you will notice that pressing X makes ZX appear. A. The X on your keyboard is still mapped to the X as well! Click on - the X in the keyboard mapper and search with "Next" until you find the + the X in the keyboard mapper and search with "Next" until you find the mapped key X. Click "Del". @@ -1051,8 +1201,7 @@ Examples about remapping the joystick: You have a joystick attached, it is working fine under DOSBox and you want to play some keyboard-only game with the joystick (it is assumed that the game is controlled by the arrows on the keyboard): - 1. Start the mapper, then click on one of the arrows in the middle - of the left part of the screen (right above the Mod1/Mod2 buttons). + 1. Start the mapper, then click on one of the left keyboard arrow. EVENT should be key_left. Now click on Add and move your joystick in the respective direction, this should add an event to the BIND. 2. Repeat the above for the missing three directions, additionally @@ -1062,51 +1211,55 @@ Examples about remapping the joystick: You want to swap the y-axis of the joystick because some flightsim uses the up/down joystick movement in a way you don't like, and it is not configurable in the game itself: - 1. Start the mapper and click on Y- in the upper joystick field (this - is for the first joystick if you have two joysticks attached) or the - lower joystick field (second joystick or, if you have only one - joystick attached, the second axes cross). - EVENT should be jaxis_0_1- (or jaxis_1_1-). + 1. Start the mapper and click on Y- in the first joystick field. + EVENT should be jaxis_0_1-. 2. Click on Del to remove the current binding, then click Add and move your joystick downwards. A new bind should be created. 3. Repeat this for Y+, save the layout and finally test it with some game. + If you want to remap anything to your d-pad/hat you will have to change + 'joysticktype=auto' to 'joysticktype=fcs' in configuration file. Maybe this + will be improved in the next dosbox version. If you change the default mapping, you can save your changes by clicking on -"Save". DOSBox will save the mapping to a location specified in the configuration -file (the mapperfile= entry). At startup, DOSBox will load your mapperfile, -if it is present in the DOSBox configuration file. +"Save". DOSBox will save the mapping to a location specified in +the configuration file (the mapperfile= entry). At startup, DOSBox will load +your mapperfile, if it is present in the DOSBox configuration file. =================== -7. Keyboard Layout: +8. Keyboard Layout: =================== To switch to a different keyboard layout, either the entry "keyboardlayout" in the [dos] section of the DOSBox configuration file can be used, or the -internal DOSBox program keyb.com. Both accept DOS conforming language codes -(see below), but only by using keyb.com a custom codepage can be specified. +internal DOSBox program keyb.com (Section 4: Internal Programs) +Both accept DOS conforming language codes (see below), +but only by using keyb.com a custom codepage can be specified. -The default keyboardlayout=auto currently works under windows only, the -layout is chosen according to the OS layout. +The default keyboardlayout=auto currently works under windows only. The language +is chosen according to the OS language, but the keyboard layout is not detected. Layout switching DOSBox supports a number of keyboard layouts and codepages by default, in this case just the layout identifier needs to be specified (like - keyboardlayout=sv in the DOSBox configuration file, or using "keyb sv" - at the DOSBox command prompt). - - Some keyboard layouts (for example layout GK codepage 869 and layout RU - codepage 808) have support for dual layouts that can be activated by - pressing LEFT-ALT+RIGHT-SHIFT and deactivated by LEFT-ALT+LEFT-SHIFT. + keyboardlayout=PL214 in the DOSBox configuration file, or using "keyb PL214" + at the DOSBox command prompt). The list of all layouts built into DOSBox is + here: http://vogons.zetafleet.com/viewtopic.php?t=21824 + + Some keyboard layouts (for example layout GK319 codepage 869 and layout RU441 + codepage 808) have support for dual layouts that can be accessed by pressing + LeftALT+RrightSHIFT for one layout and LeftALT+LeftSHIFT for the other. + Some keyboard layouts (for example layout LT456 codepage 771) have support + for three layouts, third can be accessed by pressing LeftALT+LeftCTRL Supported external files The FreeDOS .kl files are supported (FreeDOS keyb2 keyboard layoutfiles) as well as the FreeDOS keyboard.sys/keybrd2.sys/keybrd3.sys libraries which consist of all available .kl files. - See http://projects.freedos.net/keyb/ for precompiled keyboard layouts if + See http://www.freedos.org/ for precompiled keyboard layouts if the DOSBox-integrated layouts don't work for some reason, or if updated or new layouts become available. @@ -1114,8 +1267,10 @@ Supported external files UPX-compressed codepage files) can be used. Some codepages are compiled into DOSBox, so it is mostly not needed to care about external codepage files. If you need a different (or custom) codepage file, copy it into - the directory of the DOSBox configuration file so it is accessible for - DOSBox. + the directory of the DOSBox so it is accessible for DOSBox. + If you place all ten ega.cpx files (from FreeDOS) in DOSBox folder, + an appropriate codepagefile for the requested layout/codepage is + chosen automatically. Additional layouts can be added by copying the corresponding .kl file into the directory of the DOSBox configuration file and using the first part of @@ -1124,7 +1279,6 @@ Supported external files "keyboardlayout=uz" in the DOSBox configuration file. The integration of keyboard layout packages (like keybrd2.sys) works similar. - Note that the keyboard layout allows foreign characters to be entered, but there is NO support for them in filenames. Try to avoid them both inside DOSBox as well as in files on your host operating system that are accessible @@ -1133,9 +1287,9 @@ by DOSBox. ============================== -8. Serial Multiplayer feature: +9. Serial Multiplayer feature: ============================== - + DOSBox can emulate a serial nullmodem cable over network and internet. It can be configured through the [serialports] section in the DOSBox configuration file. @@ -1179,52 +1333,68 @@ Example: Be a server listening on TCP port 5000. -======================================= -9. How to run resource-demanding games: -======================================= +===================================== +10. How to speed up/slow down DOSBox: +===================================== DOSBox emulates the CPU, the sound and graphic cards, and other peripherals of a PC, all at the same time. The speed of an emulated DOS application depends on how many instructions can be emulated, which is adjustable (number of cycles). -CPU Cycles +CPU Cycles (speed up/slow down) By default (cycles=auto) DOSBox tries to detect whether a game needs to - be run with as many instructions emulated per time interval as possible. - You can force this behaviour by setting cycles=max in the DOSBox - configuration file. The DOSBox window will display a line "Cpu Cyles: max" - at the top then. In this mode you can reduce the amount of cycles on a - percentage-basis (hit CTRL-F11) or raise it again (CTRL-F12). - - Sometimes manually setting the number of cycles achieves better results, - in the DOSBox configuration file specify for example cycles=30000. When - running some DOS application you can raise the cycles with CTRL-F12 even - more, but you will be limited by the power of your actual CPU. You can see - how much free time your real CPU has by looking at the Task Manager in - Windows 2000/XP and the System Monitor in Windows 95/98/ME. Once 100% of - your real CPU time is used there is no further way to speed up DOSBox - unless you reduce the load generated by the non-CPU parts of DOSBox. + be run with as many instructions emulated per time interval as possible + (cycles=max, sometimes this results in game working too fast or unstable), + or whether to use fixed amount of cycles (cycles=3000, sometimes this results + in game working too slow or too fast). But you can always manually force + a different setting in the DOSBox's configuration file. -CPU Cores + You can force the slow or fast behavior by setting a fixed amount of cycles + in the DOSBox's configuration file. If you for example set cycles=10000, then + DOSBox window will display a line "Cpu Speed: fixed 10000 cycles" at the top. + In this mode you can reduce the amount of cycles even more by hitting CTRL-F11 + (you can go as low as you want) or raise it by hitting CTRL-F12 as much as you + want, but you will be limited by the power of one core of your computer's CPU. + You can see how much free time your real CPU's cores have by looking at + the Task Manager in Windows 2000/XP/Vista/7 and the System Monitor + in Windows 95/98/ME. Once 100% of the power of your computer's real CPU's one + core is used, there is no further way to speed up DOSBox (it will actually + start to slow down), unless you reduce the load generated by the non-CPU parts + of DOSBox. DOSBox can use only one core of your CPU, so If you have + for example a CPU with 4 cores, DOSBox will not be able to use the power + of three other cores. + + You can also force the fast behavior by setting cycles=max in the DOSBox + configuration file. The DOSBox window will display a line + "Cpu Speed: max 100% cycles" at the top then. This time you won't have to care + how much free time your real CPU's cores have, because DOSBox will always use + 100% of your real CPU's one core. In this mode you can reduce the amount + of your real CPU's core usage by CTRL-F11 or raise it with CTRL-F12. + +CPU Core (speed up) On x86 architectures you can try to force the usage of a dynamically recompiling core (set core=dynamic in the DOSBox configuration file). This usually gives better results if the auto detection (core=auto) fails. - It is best accompanied by cycles=max. Note that there might be games - that work worse with the dynamic core, or do not work at all! + It is best accompanied by cycles=max. But you may also try using it with + high amounts of cycles (for example 20000 or more). Note that there might be + games that work worse/crash with the dynamic core (so save your game often), + or do not work at all! -Graphics emulation - VGA emulation is a very demanding part of DOSBox in terms of actual CPU - usage. Increase the number of frames skipped (in increments of one) by - pressing CTRL-F8. Your CPU usage should decrease when using a fixed - cycle setting. - Go back one step and repeat this until the game runs fast enough for you. +Graphics emulation (speed up) + VGA emulation is a demanding part of DOSBox in terms of actual CPU usage. + Increase the number of frames skipped (in increments of one) by pressing + CTRL-F8. Your CPU usage should decrease when using a fixed cycle setting, + and you will be able to increase cycles with CTRL-F12. + You can repeat this until the game runs fast enough for you. Please note that this is a trade-off: you lose in fluidity of video what you gain in speed. -Sound emulation +Sound emulation (speed up) You can also try to disable the sound through the setup utility of the game - to reduce load on your CPU further. Setting nosound=true does NOT disable - the emulation of sound devices, just the output of sound will be disabled. + to reduce load on your CPU further. Setting nosound=true in DOSBox's + configuration does NOT disable the emulation of sound devices, just + the output of sound will be disabled. Also try to close every program but DOSBox to reserve as much resources as possible for DOSBox. @@ -1233,24 +1403,28 @@ as possible for DOSBox. Advanced cycles configuration: The cycles=auto and cycles=max settings can be parameterized to have different startup defaults. The syntax is - cycles=auto ["realmode default"] ["protected mode default"%] + cycles=auto ["realmode default"] ["protected mode default"%] [limit "cycle limit"] cycles=max ["protected mode default"%] [limit "cycle limit"] Example: - cycles=auto 1000 80% limit 20000 - will use cycles=1000 for real mode games, 80% CPU throttling for + cycles=auto 5000 80% limit 20000 + will use cycles=5000 for real mode games, 80% CPU throttling for protected mode games along with a hard cycle limit of 20000 ==================== -10. Troubleshooting: +11. Troubleshooting: ==================== +General tip: + Check messages in DOSBox Status Window. See section 12. "DOSBox Status Window" + DOSBox crashes right after starting it: - use different values for the output= entry in your DOSBox configuration file - try to update your graphics card driver and DirectX + - (Linux) set the environment variable SDL_AUDIODRIVER to alsa or oss. Running a certain game closes DOSBox, crashes with some message or hangs: - see if it works with a default DOSBox installation @@ -1286,46 +1460,71 @@ The game exits to the DOSBox prompt with some error message: -==================== -11. The Config File: -==================== +========================= +12. DOSBox Status Window: +========================= -A config file can be generated by CONFIG.COM, which can be found on the -internal DOSBox Z: drive when you start up DOSBox. Look in the internal -programs section of the readme for usage of CONFIG.COM. -You can edit the generated configfile to customize DOSBox. +DOSBox's Staus window contains many useful information about your currant +configuration, your actions in DOSBox, errors that happened and more. +Whenever you have any problem with DOSBox check these messages. -The file is divided into several sections (the names have [] around it). -Some sections have options you can set. -# and % indicate comment-lines. -The DOSBox configuration file contains the current settings. You can -alter them and start DOSBox with the -conf switch to load the file and -use these settings. +To start DOSBox Status Window: + (Windows) Status Window is being started together with main DOSBox window. + (Linux) You may have to start DOSBox from a console to see Status Window. + (MAC OS X) Right click on DOSBox.app, choose "Show Package Contents"-> + ->enter "Contents"->enter "MacOS"->run "DOSBox" -DOSBox will parse configuration files that are specified with -conf. If -none were specified it will try to load "dosbox.conf" from the local -directory. If there is none, DOSBox will load the user configuration -file. This file will be created if it doesn't exist. The file can be -found in ~/.dosbox (Linux) or "~/Library/Preferences" (MAC OS X). -Windows users should use the shortcuts in the startmenu to find it. +===================================== +13. The configuration (options) file: +===================================== + +The configuration file is automatically created the first time you run DOSBox. +The file can be found in: + (Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Options + (Linux) ~/.dosbox/dosbox-0.74.conf + (MAC OS X) "~/Library/Preferences/DOSBox 0.74 Preferences" +The file is divided into several sections. Each section starts with a +[section name] line. The settings are the property=value lines where value can +be altered to customize DOSBox. +# and % indicate comment-lines. + + +An extra configuration file can be generated by CONFIG.COM, which can be found +on the internal DOSBox Z: drive when you start up DOSBox. Look in the Section 4: +"Internal programs" for usage of CONFIG.COM. You can start DOSBox with +the -conf switch to load the generated file and use its settings. + +DOSBox will load configuration files that are specified with -conf. If none were +specified, it will try to load "dosbox.conf" from the local directory. +If there is none, DOSBox will load the user configuration file. +This file will be created if it doesn't exist. + +Important!: In Windows Vista/7 the configuration file won't work correctly +if it is located in "Windows" or "Program Files" folder or their subfolders, +or directly on c:\, so the best place for storing extra configuration files is +for example: C:\oldgames + ====================== -12. The Language File: +14. The Language File: ====================== -A language file can be generated by CONFIG.COM (CONFIG -writelang langfile). -Read it, and you will hopefully understand how to change it. +A language file can be generated by CONFIG.COM, which can be found on the +internal DOSBox Z: drive when you start up DOSBox. Look in the Section 4: +"Internal programs" for usage of CONFIG.COM. +Read the language file, and you will hopefully understand how to change it. Start DOSBox with the -lang switch to use your new language file. -Alternatively, you can setup the filename in the config file in the [dosbox] -section. There's a language= entry that can be changed with the filename. +Alternatively, you can setup the filename in the configuration file +in the [dosbox] section. There's a language= entry that can be changed with +the filelocation. ======================================== -13. Building your own version of DOSBox: +15. Building your own version of DOSBox: ======================================== Download the source. @@ -1334,16 +1533,19 @@ Check the INSTALL in the source distribution. =================== -14. Special thanks: +16. Special thanks: =================== See the THANKS file. + ============ -15. Contact: +17. Contact: ============ See the site: http://www.dosbox.com for an email address (The Crew-page). + + diff --git a/THANKS b/THANKS index 811f6c8..8b0e5d9 100644 --- a/THANKS +++ b/THANKS @@ -7,7 +7,7 @@ Jarek Burczynski for the new OPL3 emulator. Ken Silverman for his work on an OPL2 emulator. The Bochs and DOSemu projects which I used for information. -Freedos for ideas in making my shell. +FreeDOS for ideas in making my shell. Pierre-Yves Gérardy for hosting the old Beta Board. Colin Snover for hosting our forum. @@ -22,6 +22,7 @@ Jantien for the version management. Shawn, Johannes and Marcus for creating the MAC OS X version. Jochen for creating the OS/2 version. Ido Beeri for the icon. +ripsaw8080 for his hard debugging work. GOG Team for the splash screen. All the people who submitted a bug. The Beta Testers. diff --git a/VERSION b/VERSION index 6ab5ccf..3ea25f5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.73 +0.74 diff --git a/acinclude.m4 b/acinclude.m4 index 61e3d06..0a9f310 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -390,9 +390,9 @@ typedef double Real64; #if SIZEOF_INT_P == 4 typedef Bit32u Bitu; typedef Bit32s Bits; - #else +#else typedef Bit64u Bitu; typedef Bit64s Bits; - #endif +#endif ]) diff --git a/configure.in b/configure.in index a24f9bf..016ea95 100644 --- a/configure.in +++ b/configure.in @@ -1,11 +1,11 @@ dnl Init. -AC_INIT(dosbox,0.73) +AC_INIT(dosbox,0.74) AC_PREREQ(2.50) AC_CONFIG_SRCDIR(README) dnl Detect the canonical host and target build environment AC_CANONICAL_HOST -AC_CANONICAL_TARGET +AC_CANONICAL_BUILD dnl Setup for automake AM_INIT_AUTOMAKE @@ -21,7 +21,7 @@ AC_PROG_RANLIB dnl Some needed libaries for OS2 dnl perharps join this with the other target depended checks. move them upwards -if test x$target = xi386-pc-os2-emx ; then +if test x$host = xi386-pc-os2-emx ; then CXXFLAGS="$CXXFLAGS -Zmt" LDFLAGS="$LDFLAGS -Zomf -Zmt" LIBS="$LIBS -los2me" @@ -231,7 +231,7 @@ AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--enable-core-inline],[Enable inlined dnl The target cpu checks for dynamic cores AH_TEMPLATE(C_TARGETCPU,[The type of cpu this target has]) AC_MSG_CHECKING(for target cpu type) -case "$target_cpu" in +case "$host_cpu" in x86_64 | amd64) AC_DEFINE(C_TARGETCPU,X86_64) AC_MSG_RESULT(x86-64 bit compatible) @@ -343,7 +343,7 @@ fi AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng]) AC_CHECK_HEADER(png.h,have_png_h=yes,) -AC_CHECK_LIB(png, png_check_sig, have_png_lib=yes, ,-lz) +AC_CHECK_LIB(png, png_get_io_ptr, have_png_lib=yes, ,-lz) if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then LIBS="$LIBS -lpng -lz" AC_DEFINE(C_SSHOT,1) @@ -355,7 +355,7 @@ AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_ AH_TEMPLATE(C_IPX,[Define to 1 to enable IPX over Internet networking, requires SDL_net]) AC_CHECK_HEADER(SDL_net.h,have_sdl_net_h=yes,) -if test x$target = xi386-pc-os2-emx ; then +if test x$host = xi386-pc-os2-emx ; then AC_MSG_CHECKING(for SDLNet_Init in SDL_net); LIBS_BACKUP=$LIBS; LIBS="$LIBS -lSDL_Net"; @@ -393,7 +393,7 @@ AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , ) AC_ARG_ENABLE(opengl,AC_HELP_STRING([--disable-opengl],[Disable opengl support]),,enable_opengl=yes) AC_MSG_CHECKING(whether opengl display output will be enabled) if test x$enable_opengl = xyes; then -case "$target" in +case "$host" in *-*-darwin*) AC_MSG_RESULT(yes) LIBS="$LIBS -framework OpenGL" @@ -448,7 +448,7 @@ int main(int argc,char * argv[]) { dnl Some target detection and actions for them -case "$target" in +case "$host" in *-*-cygwin* | *-*-mingw32*) LIBS="$LIBS -lwinmm" AC_CHECK_HEADERS(ddraw.h) @@ -486,7 +486,7 @@ case "$target" in esac dnl Some stuff for the icon. -case "$target" in +case "$host" in *-*-cygwin* | *-*-mingw32*) dnl Some stuff for the ico AC_CHECK_TOOL(WINDRES, windres, :) diff --git a/docs/dosbox.1 b/docs/dosbox.1 index edef4bc..cf96475 100644 --- a/docs/dosbox.1 +++ b/docs/dosbox.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH DOSBOX 1 "May 27, 2009" +.TH DOSBOX 1 "Feb 26, 2010" .\" Please adjust this date whenever revising the manpage. .SH NAME dosbox \- an x86/DOS emulator with sound/graphics @@ -9,6 +9,7 @@ dosbox \- an x86/DOS emulator with sound/graphics .B [\-startmapper] .B [\-noautoexec] .B [\-securemode] +.B [\-userconf] .BI "[\-scaler " scaler ] .BI "[\-forcescaler " scaler ] .BI "[\-conf " configfile ] @@ -27,6 +28,12 @@ dosbox \- an x86/DOS emulator with sound/graphics .B dosbox \-printconf .LP .B dosbox \-eraseconf +.LP +.B dosbox \-resetconf +.LP +.B dosbox \-erasemapper +.LP +.B dosbox \-resetmapper .SH DESCRIPTION This manual page briefly documents .BR "dosbox" ", an x86/DOS emulator." @@ -57,6 +64,10 @@ at the end of (which in turn disables any changes to how the drives are mounted .RB "inside " dosbox ) .TP +.B \-userconf +Load the configuration file located in ~/.dosbox. Can be combined with +.RB "the " \-conf " option." +.TP .BI \-scaler " scaler" .RI "Uses the graphical scaler specified by " scaler ". See the configuration" file for the available scalers @@ -100,13 +111,16 @@ You can specify this command more than once. In this case it will .RI " move to second " program " if the first one fails to start." .TP .BI \-opencaptures " program" -.RI "calls " program " with as first paramater the location of the captures folder." +.RI "calls " program " with as first parameter the location of the captures folder." .TP .B \-printconf prints the location of the default configuration file. .TP -.B \-eraseconf +.B \-eraseconf, \-resetconf removes the default configuration file. +.TP +.B \-erasemapper, \-resetmapper +removes the mapperfile configured in the clean default configuration file. .SH "INTERNAL COMMANDS" .B dosbox supports most of the DOS commands found in command.com. In addition, the diff --git a/include/render.h b/include/render.h index bbfd90e..3ed3eb5 100644 --- a/include/render.h +++ b/include/render.h @@ -23,7 +23,7 @@ // 1: complex scalers off, scaler cache off, all simple scalers on // 2: complex scalers off, scaler cache on // 3: complex scalers on -#define RENDER_USE_ADVANCED_SCALERS 3 +#define RENDER_USE_ADVANCED_SCALERS 2 #include "../src/gui/render_scalers.h" @@ -91,7 +91,7 @@ extern Render_t render; extern ScalerLineHandler_t RENDER_DrawLine; void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh); bool RENDER_StartUpdate(void); -void RENDER_EndUpdate( ); +void RENDER_EndUpdate(bool abort); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); diff --git a/include/setup.h b/include/setup.h index 5a0d605..4b4940f 100644 --- a/include/setup.h +++ b/include/setup.h @@ -45,6 +45,11 @@ #include #endif +#ifndef CH_CSTDIO +#define CH_CSTDIO +#include +#endif + class Hex { private: diff --git a/include/vga.h b/include/vga.h index 55abf2f..a3d02c2 100644 --- a/include/vga.h +++ b/include/vga.h @@ -111,6 +111,12 @@ typedef struct { Bit32u full_enable_and_set_reset; } VGA_Config; +typedef enum { + PART, + LINE, + //EGALINE +} Drawmode; + typedef struct { bool resizing; Bitu width; @@ -144,6 +150,7 @@ typedef struct { double hdend, htotal; double parts; } delay; + Bitu bpp; double aspect_ratio; bool double_scan; bool doublewidth,doubleheight; @@ -156,6 +163,7 @@ typedef struct { Bit8u count,delay; Bit8u enabled; } cursor; + Drawmode mode; bool vret_triggered; } VGA_Draw; @@ -216,7 +224,7 @@ typedef struct { Bit8u htotal; Bit8u hdend; Bit8u hsyncp; - Bit8u syncw; + Bit8u hsyncw; Bit8u vtotal; Bit8u vdend; Bit8u vadjust; @@ -262,7 +270,12 @@ typedef struct { Bit8u color_plane_enable; Bit8u color_select; Bit8u index; - Bit8u enabled; + Bit8u disabled; // Used for disabling the screen. + // Bit0: screen disabled by attribute controller index + // Bit1: screen disabled by sequencer index 1 bit 5 + // These are put together in one variable for performance reasons: + // the line drawing function is called maybe 60*480=28800 times/s, + // and we only need to check one variable for zero this way. } VGA_Attr; typedef struct { @@ -367,8 +380,6 @@ typedef struct { typedef struct { VGAModes mode; /* The mode the vga system is in */ - VGAModes lastmode; - Bits screenflip; Bit8u misc_output; VGA_Draw draw; VGA_Config config; @@ -397,6 +408,8 @@ typedef struct { } VGA_Type; +/* Hercules Palette function */ +void Herc_Palette(void); /* Functions for different resolutions */ void VGA_SetMode(VGAModes mode); diff --git a/scripts/captures.bat b/scripts/captures.bat new file mode 100644 index 0000000..8eebbc8 --- /dev/null +++ b/scripts/captures.bat @@ -0,0 +1 @@ +DOSBox.exe -opencaptures explorer.exe \ No newline at end of file diff --git a/scripts/dosbox-installer.nsi b/scripts/dosbox-installer.nsi index 629bca5..31aee2b 100644 --- a/scripts/dosbox-installer.nsi +++ b/scripts/dosbox-installer.nsi @@ -1,8 +1,8 @@ !define VER_MAYOR 0 -!define VER_MINOR 73 +!define VER_MINOR 74 !define APP_NAME "DOSBox ${VER_MAYOR}.${VER_MINOR} Installer" !define COMP_NAME "DOSBox Team" -!define COPYRIGHT "Copyright © 2002-2009 DOSBox Team" +!define COPYRIGHT "Copyright © 2002-2010 DOSBox Team" !define DESCRIPTION "DOSBox Installer" VIProductVersion "${VER_MAYOR}.${VER_MINOR}.0.0" @@ -47,44 +47,57 @@ SetShellVarContext all ; Put file there - CreateDirectory "$INSTDIR\zmbv" + CreateDirectory "$INSTDIR\Video Codec" + CreateDirectory "$INSTDIR\Documentation" + SetOutPath "$INSTDIR\Documentation" File /oname=README.txt README File /oname=COPYING.txt COPYING File /oname=THANKS.txt THANKS File /oname=NEWS.txt NEWS File /oname=AUTHORS.txt AUTHORS File /oname=INSTALL.txt INSTALL - File DOSBox.exe + SetOutPath "$INSTDIR" + + File "/oname=DOSBox ${VER_MAYOR}.${VER_MINOR} Manual.txt" README + File "/oname=DOSBox.exe" DOSBox.exe File SDL.dll File SDL_net.dll - File /oname=zmbv\zmbv.dll zmbv.dll - File /oname=zmbv\zmbv.inf zmbv.inf - File /oname=zmbv\README.txt README.video + File "/oname=Video Codec\zmbv.dll" zmbv.dll + File "/oname=Video Codec\zmbv.inf" zmbv.inf + File "/oname=Video Codec\Video Instructions.txt" README.video + File "/oname=DOSBox ${VER_MAYOR}.${VER_MINOR} Options.bat" editconf.bat + File "/oname=Reset KeyMapper.bat" resetmapper.bat + File "/oname=Reset Options.bat" resetconf.bat + File "/oname=Screenshots & Recordings.bat" captures.bat CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}" - CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video" - CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" "$INSTDIR\DOSBox.exe" "" "$INSTDIR\DOSBox.exe" 0 - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" "$INSTDIR\DOSBox.exe" "-noconsole" "$INSTDIR\DOSBox.exe" 0 - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" "$INSTDIR\README.txt" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Edit Configuration.lnk" "$INSTDIR\DOSBox.exe" "-editconf notepad.exe -editconf $\"%SystemRoot%\system32\notepad.exe$\" -editconf $\"%WINDIR%\notepad.exe$\"" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Reset Configuration.lnk" "$INSTDIR\DOSBox.exe" "-eraseconf" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" "$INSTDIR\DOSBox.exe" "-opencaptures explorer.exe" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" "$INSTDIR\zmbv\README.txt" + CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras" + CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video" + CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options" + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.exe" "-userconf" "$INSTDIR\DOSBox.exe" 0 + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox ${VER_MAYOR}.${VER_MINOR} Manual.lnk" "$INSTDIR\Documentation\README.txt" + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\DOSBox ${VER_MAYOR}.${VER_MINOR} (noconsole).lnk" "$INSTDIR\DOSBox.exe" "-noconsole -userconf" "$INSTDIR\DOSBox.exe" 0 + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Screenshots & Recordings.lnk" "$INSTDIR\DOSBox.exe" "-opencaptures explorer.exe" + + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options\DOSBox ${VER_MAYOR}.${VER_MINOR} Options.lnk" "$INSTDIR\DOSBox.exe" "-editconf notepad.exe -editconf $\"%SystemRoot%\system32\notepad.exe$\" -editconf $\"%WINDIR%\notepad.exe$\"" + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options\Reset Options.lnk" "$INSTDIR\DOSBox.exe" "-eraseconf" + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options\Reset KeyMapper.lnk" "$INSTDIR\DOSBox.exe" "-erasemapper" + + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video\Video instructions.lnk" "$INSTDIR\Video Codec\Video Instructions.txt" ;change outpath so the working directory gets set to zmbv -SetOutPath "$INSTDIR\zmbv" +SetOutPath "$INSTDIR\Video Codec" ; Shortcut creation depends on wether we are 9x of NT ClearErrors ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion IfErrors we_9x we_nt we_nt: ;shortcut for win NT - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" "rundll32" "setupapi,InstallHinfSection DefaultInstall 128 $INSTDIR\zmbv\zmbv.inf" + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video\Install movie codec.lnk" "rundll32" "setupapi,InstallHinfSection DefaultInstall 128 $INSTDIR\Video Codec\zmbv.inf" goto end we_9x: ;shortcut for we_9x - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" "rundll" "setupx.dll,InstallHinfSection DefaultInstall 128 $INSTDIR\zmbv\zmbv.inf" + CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video\Install movie codec.lnk" "rundll" "setupx.dll,InstallHinfSection DefaultInstall 128 $INSTDIR\Video Codec\zmbv.inf" end: SetOutPath $INSTDIR WriteUninstaller "uninstall.exe" @@ -102,9 +115,9 @@ SectionEnd ; end the section Section "Desktop Shortcut" SecDesktop SetShellVarContext all -CreateShortCut "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.exe" "" "$INSTDIR\DOSBox.exe" 0 +CreateShortCut "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.exe" "-userconf" "$INSTDIR\DOSBox.exe" 0 - SectionEnd ; end the section +SectionEnd ; end the section UninstallText "This will uninstall DOSBox v${VER_MAYOR}.${VER_MINOR}. Hit next to continue." @@ -117,40 +130,54 @@ SetShellVarContext all Delete "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" ; remove registry keys ; remove files - Delete $INSTDIR\README.txt - Delete $INSTDIR\COPYING.txt - Delete $INSTDIR\THANKS.txt - Delete $INSTDIR\NEWS.txt - Delete $INSTDIR\AUTHORS.txt - Delete $INSTDIR\INSTALL.txt - Delete $INSTDIR\DOSBox.exe + Delete $INSTDIR\Documentation\README.txt + Delete $INSTDIR\Documentation\COPYING.txt + Delete $INSTDIR\Documentation\THANKS.txt + Delete $INSTDIR\Documentation\NEWS.txt + Delete $INSTDIR\Documentation\AUTHORS.txt + Delete $INSTDIR\Documentation\INSTALL.txt + Delete "$INSTDIR\DOSBox ${VER_MAYOR}.${VER_MINOR} Manual.txt" + Delete "$INSTDIR\DOSBox.exe" Delete $INSTDIR\SDL.dll Delete $INSTDIR\SDL_net.dll - Delete $INSTDIR\zmbv\zmbv.dll - Delete $INSTDIR\zmbv\zmbv.inf - Delete $INSTDIR\zmbv\README.txt + Delete "$INSTDIR\Video Codec\zmbv.dll" + Delete "$INSTDIR\Video Codec\zmbv.inf" + Delete "$INSTDIR\Video Codec\Video Instructions.txt" ;Files left by sdl taking over the console Delete $INSTDIR\stdout.txt Delete $INSTDIR\stderr.txt + Delete "$INSTDIR\DOSBox ${VER_MAYOR}.${VER_MINOR} Options.bat" + Delete "$INSTDIR\Reset KeyMapper.bat" + Delete "$INSTDIR\Reset Options.bat" + Delete "$INSTDIR\Screenshots & Recordings.bat" ; MUST REMOVE UNINSTALLER, too Delete $INSTDIR\uninstall.exe - ; remove shortcuts, if any. - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Uninstall.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Edit Configuration.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Reset Configuration.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" + + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox ${VER_MAYOR}.${VER_MINOR} Manual.lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\DOSBox ${VER_MAYOR}.${VER_MINOR} (noconsole).lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Uninstall.lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Screenshots & Recordings.lnk" + + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options\DOSBox ${VER_MAYOR}.${VER_MINOR} Options.lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options\Reset Options.lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options\Reset KeyMapper.lnk" + + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video\Video instructions.lnk" + Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video\Install movie codec.lnk" + + + +; remove shortcuts, if any. ; remove directories used. - RMDir "$INSTDIR\zmbv" + RMDir "$INSTDIR\Documentation" + RMDir "$INSTDIR\Video Codec" RMDir "$INSTDIR" - RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration" - RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video" + RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Options" + RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras\Video" + RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Extras" RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}" SectionEnd diff --git a/scripts/editconf.bat b/scripts/editconf.bat new file mode 100644 index 0000000..a48d102 --- /dev/null +++ b/scripts/editconf.bat @@ -0,0 +1 @@ +DOSBox.exe -editconf notepad.exe -editconf %SystemRoot%\system32\notepad.exe -editconf %WINDIR%\notepad.exe \ No newline at end of file diff --git a/scripts/resetconf.bat b/scripts/resetconf.bat new file mode 100644 index 0000000..0ad3b95 --- /dev/null +++ b/scripts/resetconf.bat @@ -0,0 +1 @@ +DOSBox.exe -resetconf \ No newline at end of file diff --git a/scripts/resetmapper.bat b/scripts/resetmapper.bat new file mode 100644 index 0000000..86299bb --- /dev/null +++ b/scripts/resetmapper.bat @@ -0,0 +1 @@ +DOSBox.exe -resetmapper \ No newline at end of file diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index 8cedf92..627b548 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -423,7 +423,13 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_ } phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction phys_writeb(physAddress+0x02,(Bit8u)0xCB); //A RETF Instruction - return (use_cb?7:3); + phys_writeb(physAddress+0x03,(Bit8u)0x51); // push cx + phys_writeb(physAddress+0x04,(Bit8u)0xB9); // mov cx, + phys_writew(physAddress+0x05,(Bit16u)0x0140); // 0x140 + phys_writew(physAddress+0x07,(Bit16u)0xFEE2); // loop $-2 + phys_writeb(physAddress+0x09,(Bit8u)0x59); // pop cx + phys_writeb(physAddress+0x0A,(Bit8u)0xCF); //An IRET Instruction + return (use_cb?15:11); default: E_Exit("CALLBACK:Setup:Illegal type %d",type); diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 98b1b1a..5a6b150 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -1546,7 +1546,7 @@ Bitu CPU_SIDT_limit(void) { return cpu.idt.GetLimit(); } - +static bool printed_cycles_auto_info = false; void CPU_SET_CRX(Bitu cr,Bitu value) { switch (cr) { case 0: @@ -1567,6 +1567,10 @@ void CPU_SET_CRX(Bitu cr,Bitu value) { CPU_Cycles=0; CPU_OldCycleMax=CPU_CycleMax; GFX_SetTitle(CPU_CyclePercUsed,-1,false); + if(!printed_cycles_auto_info) { + printed_cycles_auto_info = true; + LOG_MSG("DOSBox switched to max cycles, because of the setting: cycles=auto. If the game runs too fast try a fixed cycles amount in DOSBox's options."); + } } else { GFX_SetTitle(-1,-1,false); } @@ -2099,8 +2103,8 @@ static void CPU_CycleIncrease(bool pressed) { if (!pressed) return; if (CPU_CycleAutoAdjust) { CPU_CyclePercUsed+=5; - if (CPU_CyclePercUsed>100) CPU_CyclePercUsed=100; - LOG_MSG("CPU:%d percent",CPU_CyclePercUsed); + if (CPU_CyclePercUsed>105) CPU_CyclePercUsed=105; + LOG_MSG("CPU speed: max %d percent.",CPU_CyclePercUsed); GFX_SetTitle(CPU_CyclePercUsed,-1,false); } else { Bit32s old_cycles=CPU_CycleMax; @@ -2112,7 +2116,10 @@ static void CPU_CycleIncrease(bool pressed) { CPU_CycleLeft=0;CPU_Cycles=0; if (CPU_CycleMax==old_cycles) CPU_CycleMax++; - LOG_MSG("CPU:%d cycles",CPU_CycleMax); + if(CPU_CycleMax > 15000 ) + LOG_MSG("CPU speed: fixed %d cycles. If you need more than 20000, try core=dynamic in DOSBox's options.",CPU_CycleMax); + else + LOG_MSG("CPU speed: fixed %d cycles.",CPU_CycleMax); GFX_SetTitle(CPU_CycleMax,-1,false); } } @@ -2122,7 +2129,10 @@ static void CPU_CycleDecrease(bool pressed) { if (CPU_CycleAutoAdjust) { CPU_CyclePercUsed-=5; if (CPU_CyclePercUsed<=0) CPU_CyclePercUsed=1; - LOG_MSG("CPU:%d percent",CPU_CyclePercUsed); + if(CPU_CyclePercUsed <=70) + LOG_MSG("CPU speed: max %d percent. If the game runs too fast, try a fixed cycles amount in DOSBox's options.",CPU_CyclePercUsed); + else + LOG_MSG("CPU speed: max %d percent.",CPU_CyclePercUsed); GFX_SetTitle(CPU_CyclePercUsed,-1,false); } else { if (CPU_CycleDown < 100) { @@ -2132,7 +2142,7 @@ static void CPU_CycleDecrease(bool pressed) { } CPU_CycleLeft=0;CPU_Cycles=0; if (CPU_CycleMax <= 0) CPU_CycleMax=1; - LOG_MSG("CPU:%d cycles",CPU_CycleMax); + LOG_MSG("CPU speed: fixed %d cycles.",CPU_CycleMax); GFX_SetTitle(CPU_CycleMax,-1,false); } } @@ -2246,7 +2256,7 @@ public: int percval=0; std::istringstream stream(str); stream >> percval; - if ((percval>0) && (percval<=100)) CPU_CyclePercUsed=(Bit32s)percval; + if ((percval>0) && (percval<=105)) CPU_CyclePercUsed=(Bit32s)percval; } else if (str=="limit") { cmdnum++; if (cmd.FindCommand(cmdnum,str)) { @@ -2271,7 +2281,7 @@ public: int percval=0; std::istringstream stream(str); stream >> percval; - if ((percval>0) && (percval<=100)) CPU_CyclePercUsed=(Bit32s)percval; + if ((percval>0) && (percval<=105)) CPU_CyclePercUsed=(Bit32s)percval; } else if (str=="limit") { cmdnum++; if (cmd.FindCommand(cmdnum,str)) { diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index 356ccea..5b165de 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -76,6 +76,7 @@ static void DrawVariables(void); char* AnalyzeInstruction(char* inst, bool saveSelector); Bit32u GetHexValue(char* str, char*& hex); +#if 0 class DebugPageHandler : public PageHandler { public: Bitu readb(PhysPt /*addr*/) { @@ -90,10 +91,8 @@ public: } void writed(PhysPt /*addr*/,Bitu /*val*/) { } - - - }; +#endif class DEBUG; @@ -123,7 +122,6 @@ static char curSelectorName[3] = { 0,0,0 }; static Segment oldsegs[6]; static Bitu oldflags,oldcpucpl; DBGBlock dbg; -static Bitu input_count; Bitu cycle_count; static bool debugging; @@ -136,23 +134,34 @@ static void SetColor(Bitu test) { } } +#define MAXCMDLEN 254 struct SCodeViewData { - int cursorPos; + int cursorPos; Bit16u firstInstSize; - Bit16u useCS; - Bit32u useEIPlast, useEIPmid; - Bit32u useEIP; + Bit16u useCS; + Bit32u useEIPlast, useEIPmid; + Bit32u useEIP; Bit16u cursorSeg; - Bit32u cursorOfs; - bool inputMode; - char inputStr[255]; - char prevInputStr[255]; - + Bit32u cursorOfs; + bool ovrMode; + char inputStr[MAXCMDLEN+1]; + char suspInputStr[MAXCMDLEN+1]; + int inputPos; } codeViewData; -static Bit16u dataSeg; -static Bit32u dataOfs; -static bool showExtend = true; +static Bit16u dataSeg; +static Bit32u dataOfs; +static bool showExtend = true; + +static void ClearInputLine(void) { + codeViewData.inputStr[0] = 0; + codeViewData.inputPos = 0; +} + +// History stuff +#define MAX_HIST_BUFFER 50 +static list histBuff; +static list::iterator histBuffPos = histBuff.end(); /***********/ /* Helpers */ @@ -775,6 +784,8 @@ static void DrawCode(void) { wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK)); if (codeViewData.cursorPos==-1) { codeViewData.cursorPos = i; // Set Cursor + } + if (i == codeViewData.cursorPos) { codeViewData.cursorSeg = SegValue(cs); codeViewData.cursorOfs = disEIP; } @@ -837,12 +848,18 @@ static void DrawCode(void) { wattrset(dbg.win_code,0); if (!debugging) { - mvwprintw(dbg.win_code,10,0,"(Running)",codeViewData.inputStr); - } else { - if(!*codeViewData.inputStr) { //Clear old commands - mvwprintw(dbg.win_code,10,0," "); - } - mvwprintw(dbg.win_code,10,0,"-> %s_ ",codeViewData.inputStr); + mvwprintw(dbg.win_code,10,0,"%s","(Running)"); + wclrtoeol(dbg.win_code); + } else { + //TODO long lines + char* dispPtr = codeViewData.inputStr; + char* curPtr = &codeViewData.inputStr[codeViewData.inputPos]; + mvwprintw(dbg.win_code,10,0,"%c-> %s%c", + (codeViewData.ovrMode?'O':'I'),dispPtr,(*curPtr?' ':'_')); + wclrtoeol(dbg.win_code); // not correct in pdcurses if full line + if (*curPtr) { + mvwchgat(dbg.win_code,10,(curPtr-dispPtr+4),1,0,(PAIR_BLACK_GREY),NULL); + } } wrefresh(dbg.win_code); @@ -1121,6 +1138,7 @@ bool ParseCommand(char* str) { DEBUG_ShowMsg("DEBUG: Set code overview to %04X:%04X\n",codeSeg,codeOfs); codeViewData.useCS = codeSeg; codeViewData.useEIP = codeOfs; + codeViewData.cursorPos = 0; return true; }; @@ -1226,6 +1244,7 @@ bool ParseCommand(char* str) { DEBUG_ShowMsg("DEBUG: Set code overview to interrupt handler %X\n",intNr); codeViewData.useCS = mem_readw(intNr*4+2); codeViewData.useEIP = mem_readw(intNr*4); + codeViewData.cursorPos = 0; return true; } }; @@ -1259,7 +1278,8 @@ bool ParseCommand(char* str) { if (command == "HELP" || command == "?") { DEBUG_ShowMsg("Debugger commands (enter all values in hex or as register):\n"); DEBUG_ShowMsg("--------------------------------------------------------------------------\n"); - DEBUG_ShowMsg("F3/F6 - Re-enter previous command.\n"); + DEBUG_ShowMsg("F3/F6 - Previous command in history.\n"); + DEBUG_ShowMsg("F4/F7 - Next command in history.\n"); DEBUG_ShowMsg("F5 - Run.\n"); DEBUG_ShowMsg("F9 - Set/Remove breakpoint.\n"); DEBUG_ShowMsg("F10/F11 - Step over / trace into instruction.\n"); @@ -1476,12 +1496,12 @@ char* AnalyzeInstruction(char* inst, bool saveSelector) { if (jmp) { pos = strchr(instu,'$'); if (pos) { - pos = strchr(instu,'+'); - if (pos) { - strcpy(result,"(down)"); - } else { - strcpy(result,"(up)"); - } + pos = strchr(instu,'+'); + if (pos) { + strcpy(result,"(down)"); + } else { + strcpy(result,"(up)"); + } } } else { sprintf(result,"(no jmp)"); @@ -1497,6 +1517,11 @@ Bit32u DEBUG_CheckKeys(void) { if (key>0) { #if defined(WIN32) && defined(__PDCURSES__) switch (key) { + case PADENTER: key=0x0A; break; + case PADSLASH: key='/'; break; + case PADSTAR: key='*'; break; + case PADMINUS: key='-'; break; + case PADPLUS: key='+'; break; case ALT_D: if (ungetch('D') != ERR) key=27; break; @@ -1518,7 +1543,7 @@ Bit32u DEBUG_CheckKeys(void) { case 27: // escape (a bit slow): Clears line. and processes alt commands. key=getch(); if(key < 0) { //Purely escape Clear line - codeViewData.inputStr[0] = 0; + ClearInputLine(); break; } @@ -1584,23 +1609,54 @@ Bit32u DEBUG_CheckKeys(void) { case KEY_END: // End: scroll log page down DEBUG_RefreshPage(1); break; - case KEY_F(6): // Re-enter previous command (f1-f4 generate rubbish at my place) - case KEY_F(3): // Re-enter previous command - // copy prevInputStr back into inputStr - safe_strncpy(codeViewData.inputStr, codeViewData.prevInputStr, sizeof(codeViewData.inputStr)); + case KEY_IC: // Insert: toggle insert/overwrite + codeViewData.ovrMode = !codeViewData.ovrMode; break; + case KEY_LEFT: // move to the left in command line + if (codeViewData.inputPos > 0) codeViewData.inputPos--; + break; + case KEY_RIGHT: // move to the right in command line + if (codeViewData.inputStr[codeViewData.inputPos]) codeViewData.inputPos++; + break; + case KEY_F(6): // previous command (f1-f4 generate rubbish at my place) + case KEY_F(3): // previous command + if (histBuffPos == histBuff.begin()) break; + if (histBuffPos == histBuff.end()) { + // copy inputStr to suspInputStr so we can restore it + safe_strncpy(codeViewData.suspInputStr, codeViewData.inputStr, sizeof(codeViewData.suspInputStr)); + } + safe_strncpy(codeViewData.inputStr,(*--histBuffPos).c_str(),sizeof(codeViewData.inputStr)); + codeViewData.inputPos = strlen(codeViewData.inputStr); + break; + case KEY_F(7): // next command (f1-f4 generate rubbish at my place) + case KEY_F(4): // next command + if (histBuffPos == histBuff.end()) break; + if (++histBuffPos != histBuff.end()) { + safe_strncpy(codeViewData.inputStr,(*histBuffPos).c_str(),sizeof(codeViewData.inputStr)); + } else { + // copy suspInputStr back into inputStr + safe_strncpy(codeViewData.inputStr, codeViewData.suspInputStr, sizeof(codeViewData.inputStr)); + } + codeViewData.inputPos = strlen(codeViewData.inputStr); + break; case KEY_F(5): // Run Program debugging=false; CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); ignoreAddressOnce = SegPhys(cs)+reg_eip; DOSBOX_SetNormalLoop(); break; - case KEY_F(9): // Set/Remove TBreakpoint + case KEY_F(9): // Set/Remove Breakpoint { PhysPt ptr = GetAddress(codeViewData.cursorSeg,codeViewData.cursorOfs); - if (CBreakpoint::IsBreakpoint(ptr)) CBreakpoint::DeleteBreakpoint(ptr); - else CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false); + if (CBreakpoint::IsBreakpoint(ptr)) { + CBreakpoint::DeleteBreakpoint(ptr); + DEBUG_ShowMsg("DEBUG: Breakpoint deletion success.\n"); + } + else { + CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false); + DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X\n",codeViewData.cursorSeg,codeViewData.cursorOfs); + } } - break; + break; case KEY_F(10): // Step over inst if (StepOver()) return 0; else { @@ -1621,28 +1677,54 @@ Bit32u DEBUG_CheckKeys(void) { CBreakpoint::ignoreOnce = 0; break; case 0x0A: //Parse typed Command - codeViewData.inputMode = true; + codeViewData.inputStr[MAXCMDLEN] = '\0'; if(ParseCommand(codeViewData.inputStr)) { - // copy inputStr to prevInputStr so we can restore it if the user hits F3 - safe_strncpy(codeViewData.prevInputStr, codeViewData.inputStr, sizeof(codeViewData.prevInputStr)); - // clear input line ready for next command - codeViewData.inputStr[0] = 0; + char* cmd = ltrim(codeViewData.inputStr); + if (histBuff.empty() || *--histBuff.end()!=cmd) + histBuff.push_back(cmd); + if (histBuff.size() > MAX_HIST_BUFFER) histBuff.pop_front(); + histBuffPos = histBuff.end(); + ClearInputLine(); + } else { + codeViewData.inputPos = strlen(codeViewData.inputStr); + } + break; + case KEY_BACKSPACE: //backspace (linux) + case 0x7f: // backspace in some terminal emulators (linux) + case 0x08: // delete + if (codeViewData.inputPos == 0) break; + codeViewData.inputPos--; + // fallthrough + case KEY_DC: // delete character + if ((codeViewData.inputPos<0) || (codeViewData.inputPos>=MAXCMDLEN)) break; + if (codeViewData.inputStr[codeViewData.inputPos] != 0) { + codeViewData.inputStr[MAXCMDLEN] = '\0'; + for(char* p=&codeViewData.inputStr[codeViewData.inputPos];(*p=*(p+1));p++) {} + } + break; + default: + if ((key>=32) && (key<127)) { + if ((codeViewData.inputPos<0) || (codeViewData.inputPos>=MAXCMDLEN)) break; + codeViewData.inputStr[MAXCMDLEN] = '\0'; + if (codeViewData.inputStr[codeViewData.inputPos] == 0) { + codeViewData.inputStr[codeViewData.inputPos++] = char(key); + codeViewData.inputStr[codeViewData.inputPos] = '\0'; + } else if (!codeViewData.ovrMode) { + int len = (int) strlen(codeViewData.inputStr); + if (len < MAXCMDLEN) { + for(len++;len>codeViewData.inputPos;len--) + codeViewData.inputStr[len]=codeViewData.inputStr[len-1]; + codeViewData.inputStr[codeViewData.inputPos++] = char(key); + } + } else { + codeViewData.inputStr[codeViewData.inputPos++] = char(key); + } + } else if (key==killchar()) { + ClearInputLine(); } break; - case 0x107: //backspace (linux) - case 0x7f: //backspace in some terminal emulators (linux) - case 0x08: // delete - if (strlen(codeViewData.inputStr)>0) codeViewData.inputStr[strlen(codeViewData.inputStr)-1] = 0; - break; - default : if ((key>=32) && (key<=128) && (strlen(codeViewData.inputStr)<253)) { - Bit32u len = strlen(codeViewData.inputStr); - codeViewData.inputStr[len] = char(key); - codeViewData.inputStr[len+1] = 0; - } - break; - } - if (ret<0) return ret; + if (ret<0) return ret; if (ret>0) { ret=(*CallBack_Handlers[ret])(); if (ret) { @@ -1902,7 +1984,7 @@ static void LogInstruction(Bit16u segValue, Bit32u eipValue, ofstream& out) { char ibytes[200]=""; char tmpc[200]; for (Bitu i=0; iFindCommand(i++,temp_line)==true;) { strncat(args,temp_line.c_str(),256); @@ -2027,8 +2108,7 @@ void DEBUG_SetupConsole(void) { #endif memset((void *)&dbg,0,sizeof(dbg)); debugging=false; - dbg.active_win=3; - input_count=0; +// dbg.active_win=3; /* Start the Debug Gui */ DBGUI_StartUp(); } @@ -2037,6 +2117,7 @@ static void DEBUG_ShutDown(Section * /*sec*/) { CBreakpoint::DeleteAll(); CDebugVar::DeleteAll(); curs_set(old_cursor_state); + endwin(); #ifndef WIN32 tcsetattr(0, TCSANOW,&consolesettings); // printf("\e[0m\e[2J"); //Seems to destroy scrolling @@ -2049,11 +2130,11 @@ Bitu debugCallback; void DEBUG_Init(Section* sec) { - MSG_Add("DEBUG_CONFIGFILE_HELP","Debugger related options.\n"); +// MSG_Add("DEBUG_CONFIGFILE_HELP","Debugger related options.\n"); DEBUG_DrawScreen(); /* Add some keyhandlers */ MAPPER_AddHandler(DEBUG_Enable,MK_pause,MMOD2,"debugger","Debugger"); - /* Clear the TBreakpoint list */ + /* Reset code overview and input line */ memset((void*)&codeViewData,0,sizeof(codeViewData)); /* setup debug.com */ PROGRAMS_MakeFile("DEBUG.COM",DEBUG_ProgramStart); @@ -2154,7 +2235,7 @@ static void SaveMemory(Bitu seg, Bitu ofs1, Bit32u num) { sprintf(buffer,"%04X:%04X ",seg,ofs1); for (Bit16u x=0; x<16; x++) { Bit8u value; - if (mem_readb_checked(GetAddress(seg,ofs1+x),&value)) sprintf(temp,"?? ",value); + if (mem_readb_checked(GetAddress(seg,ofs1+x),&value)) sprintf(temp,"%s","?? "); else sprintf(temp,"%02X ",value); strcat(buffer,temp); } @@ -2167,7 +2248,7 @@ static void SaveMemory(Bitu seg, Bitu ofs1, Bit32u num) { sprintf(buffer,"%04X:%04X ",seg,ofs1); for (Bit16u x=0; xGetAdr(),&value)) - snprintf(buffer,DEBUG_VAR_BUF_LEN, "??????", value); + snprintf(buffer,DEBUG_VAR_BUF_LEN, "%s", "??????"); else snprintf(buffer,DEBUG_VAR_BUF_LEN, "0x%04x", value); @@ -2248,8 +2329,6 @@ static void DrawVariables(void) { const Bit32u LOGCPUMAX = 20000; -static Bit16u logCpuCS [LOGCPUMAX]; -static Bit32u logCpuEIP[LOGCPUMAX]; static Bit32u logCount = 0; struct TLogInst { @@ -2287,7 +2366,7 @@ void DEBUG_HeavyLogInstruction(void) { PhysPt start = GetAddress(SegValue(cs),reg_eip); char dline[200]; - Bitu size = DasmI386(dline, start, reg_eip, cpu.code.big); + DasmI386(dline, start, reg_eip, cpu.code.big); char* res = empty; if (showExtend) { res = AnalyzeInstruction(dline,false); diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index fc9f1ca..936086c 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -154,7 +154,7 @@ static void DrawBars(void) { /* Show the Variable Overview bar */ mvaddstr(dbg.win_var->_begy-1,0, "---(Variable Overview )---"); /* Show the Output OverView */ - mvaddstr(dbg.win_out->_begy-1,0, "---(OutPut/Input Scroll: home/end )---"); + mvaddstr(dbg.win_out->_begy-1,0, "---(Output Scroll: home/end )---"); attrset(0); } @@ -178,8 +178,8 @@ static void MakeSubWindows(void) { dbg.win_var=subwin(dbg.win_main,4,win_main_maxx,outy,0); outy+=5; /* The Output Window */ - dbg.win_out=subwin(dbg.win_main,win_main_maxy-outy-1,win_main_maxx,outy,0); - dbg.input_y=win_main_maxy-1; + dbg.win_out=subwin(dbg.win_main,win_main_maxy-outy,win_main_maxx,outy,0); +// dbg.input_y=win_main_maxy-1; scrollok(dbg.win_out,TRUE); DrawBars(); Draw_RegisterLayout(); @@ -257,7 +257,7 @@ void LOG_StartUp(void) { Prop_bool* Pbool = sect->Add_bool(buf,Property::Changeable::Always,true); Pbool->Set_help("Enable/Disable logging of this type."); } - MSG_Add("LOG_CONFIGFILE_HELP","Logging related options for the debugger.\n"); +// MSG_Add("LOG_CONFIGFILE_HELP","Logging related options for the debugger.\n"); } diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 2073a55..35eb73e 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -44,7 +44,10 @@ void DOS_SetError(Bit16u code) { #define DATA_TRANSFERS_TAKE_CYCLES 1 #ifdef DATA_TRANSFERS_TAKE_CYCLES + +#ifndef DOSBOX_CPU_H #include "cpu.h" +#endif static inline void modify_cycles(Bits value) { if((4*value+5) < CPU_Cycles) { CPU_Cycles -= 4*value; @@ -59,6 +62,20 @@ static inline void modify_cycles(Bits /* value */) { return; } #endif +#define DOS_OVERHEAD 1 +#ifdef DOS_OVERHEAD +#ifndef DOSBOX_CPU_H +#include "cpu.h" +#endif + +static inline void overhead() { + reg_ip += 2; +} +#else +static inline void overhead() { + return; +} +#endif #define DOSNAMEBUF 256 static Bitu DOS_21Handler(void) { @@ -121,6 +138,9 @@ static Bitu DOS_21Handler(void) { switch (reg_dl) { case 0xFF: /* Input */ { + //Simulate DOS overhead for timing sensitive games + //MM1 + overhead(); //TODO Make this better according to standards if (!DOS_GetSTDINStatus()) { reg_al=0; @@ -201,6 +221,9 @@ static Bitu DOS_21Handler(void) { case 0x0b: /* Get STDIN Status */ if (!DOS_GetSTDINStatus()) {reg_al=0x00;} else {reg_al=0xFF;} + //Simulate some overhead for timing issues + //Tankwar menu (needs maybe even more) + overhead(); break; case 0x0c: /* Flush Buffer and read STDIN call */ { @@ -369,6 +392,9 @@ static Bitu DOS_21Handler(void) { reg_dh=(Bit8u)(seconds % 60); reg_dl=(Bit8u)(ticks % 100); } + //Simulate DOS overhead for timing-sensitive games + //Robomaze 2 + overhead(); break; case 0x2d: /* Set System Time */ LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported"); @@ -1061,7 +1087,7 @@ static Bitu DOS_20Handler(void) { static Bitu DOS_27Handler(void) { // Terminate & stay resident Bit16u para = (reg_dx/16)+((reg_dx % 16)>0); - Bit16u psp = mem_readw(SegPhys(ss)+reg_sp+2); + Bit16u psp = dos.psp(); //mem_readw(SegPhys(ss)+reg_sp+2); if (DOS_ResizeMemory(psp,¶)) DOS_Terminate(psp,true,0); return CBRET_NONE; } diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index 8db998c..ca9e559 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -213,8 +213,12 @@ bool DOS_NewPSP(Bit16u segment, Bit16u size) { bool DOS_ChildPSP(Bit16u segment, Bit16u size) { DOS_PSP psp(segment); psp.MakeNew(size); - DOS_PSP psp_parent(psp.GetParent()); + Bit16u parent_psp_seg = psp.GetParent(); + DOS_PSP psp_parent(parent_psp_seg); psp.CopyFileTable(&psp_parent,true); + psp.SetCommandTail(RealMake(parent_psp_seg,0x80)); + psp.SetFCB1(RealMake(parent_psp_seg,0x5c)); + psp.SetFCB2(RealMake(parent_psp_seg,0x6c)); psp.SetEnvironment(psp_parent.GetEnvironment()); psp.SetSize(size); return true; @@ -412,7 +416,7 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { } else { csip=RealMake(loadseg+head.initCS,head.initIP); sssp=RealMake(loadseg+head.initSS,head.initSP); - if (head.initSP<4) E_Exit("stack underflow/wrap at EXEC"); + if (head.initSP<4) LOG(LOG_EXEC,LOG_ERROR)("stack underflow/wrap at EXEC"); } if (flags==LOAD) { @@ -434,7 +438,7 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { } if (flags==LOADNGO) { - if ((reg_sp>0xfffe) || (reg_sp<18)) E_Exit("stack underflow/wrap at EXEC"); + if ((reg_sp>0xfffe) || (reg_sp<18)) LOG(LOG_EXEC,LOG_ERROR)("stack underflow/wrap at EXEC"); /* Get Caller's program CS:IP of the stack and set termination address to that */ RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp))); SaveRegisters(); diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index d01c7de..d74b60c 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -50,7 +50,7 @@ Bitu DEBUG_EnableDebugger(void); void MSCDEX_SetCDInterface(int intNr, int forceCD); - +#ifdef HW_RVL // Mounts a folder as a harddrive before starting the shell // Designed for the Wii int MountDOSBoxDir(char DriveLetter, const char *path) { @@ -118,7 +118,7 @@ int MountDOSBoxDir(char DriveLetter, const char *path) { newdrive->dirCache.SetLabel(label.c_str(),false,true); return 1; } - +#endif class MOUNT : public Program { public: @@ -1142,7 +1142,7 @@ public: return; } } else { - WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED")); + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED"),fstype.c_str()); return; } @@ -1292,7 +1292,7 @@ public: case 0 : break; case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break; case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break; - case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_PATH")); break; + case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_OPEN")); break; case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break; case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; case 6 : WriteOut(MSG_Get("MSCDEX_INVALID_FILEFORMAT")); break; @@ -1452,7 +1452,7 @@ void DOS_SetupPrograms(void) { MSG_Add("MSCDEX_SUCCESS","MSCDEX installed.\n"); MSG_Add("MSCDEX_ERROR_MULTIPLE_CDROMS","MSCDEX: Failure: Drive-letters of multiple CDRom-drives have to be continuous.\n"); MSG_Add("MSCDEX_ERROR_NOT_SUPPORTED","MSCDEX: Failure: Not yet supported.\n"); - MSG_Add("MSCDEX_ERROR_PATH","MSCDEX: Failure: Path not valid.\n"); + MSG_Add("MSCDEX_ERROR_OPEN","MSCDEX: Failure: Invalid file or unable to open.\n"); MSG_Add("MSCDEX_TOO_MANY_DRIVES","MSCDEX: Failure: Too many CDRom-drives (max: 5). MSCDEX Installation failed.\n"); MSG_Add("MSCDEX_LIMITED_SUPPORT","MSCDEX: Mounted subdirectory: limited support.\n"); MSG_Add("MSCDEX_INVALID_FILEFORMAT","MSCDEX: Failure: File is either no iso/cue image or contains errors.\n"); @@ -1553,7 +1553,7 @@ void DOS_SetupPrograms(void) { "\033[33;1mCTRL-F10\033[0m : Capture/Release the mouse.\n" "\033[33;1mCTRL-F11\033[0m : Slow down emulation (Decrease DOSBox Cycles).\n" "\033[33;1mCTRL-F12\033[0m : Speed up emulation (Increase DOSBox Cycles).\n" - "\033[33;1mALT-F12\033[0m : Unlock speed (turbo button).\n" + "\033[33;1mALT-F12\033[0m : Unlock speed (turbo button/fast forward).\n" ); MSG_Add("PROGRAM_BOOT_NOT_EXIST","Bootdisk file does not exist. Failing.\n"); MSG_Add("PROGRAM_BOOT_NOT_OPEN","Cannot open bootdisk file. Failing.\n"); diff --git a/src/dosbox.cpp b/src/dosbox.cpp index b55a8d4..b0b07aa 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -248,6 +248,7 @@ void DOSBOX_RunMachine(void){ static void DOSBOX_UnlockSpeed( bool pressed ) { static bool autoadjust = false; if (pressed) { + LOG_MSG("Fast Forward ON"); ticksLocked = true; if (CPU_CycleAutoAdjust) { autoadjust = true; @@ -255,7 +256,8 @@ static void DOSBOX_UnlockSpeed( bool pressed ) { CPU_CycleMax /= 3; if (CPU_CycleMax<1000) CPU_CycleMax=1000; } - } else { + } else { + LOG_MSG("Fast Forward OFF"); ticksLocked = false; if (autoadjust) { autoadjust = false; @@ -317,8 +319,13 @@ void DOSBOX_Init(void) { SDLNetInited = false; // Some frequently used option sets +#ifdef HW_RVL const char *rates[] = { "22050", "44100", "48000", "32000", "16000", "11025", "8000", "49716", 0 }; const char *oplrates[] = { "22050", "49716", "44100", "48000", "32000", "16000", "11025", "8000", 0 }; +#else + const char *rates[] = { "44100", "48000", "32000","22050", "16000", "11025", "8000", "49716", 0 }; + const char *oplrates[] = { "44100", "49716", "48000", "32000","22050", "16000", "11025", "8000", 0 }; +#endif const char *ios[] = { "220", "240", "260", "280", "2a0", "2c0", "2e0", "300", 0 }; const char *irqssb[] = { "7", "5", "3", "9", "10", "11", "12", 0 }; const char *dmassb[] = { "1", "5", "0", "3", "6", "7", 0 }; @@ -374,7 +381,8 @@ void DOSBOX_Init(void) { Pmulti = secprop->Add_multi("scaler",Property::Changeable::Always," "); Pmulti->SetValue("normal2x"); - Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended,the scaler will be used even if the result might not be desired."); + Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes.\n" + " If 'forced' is appended, then the scaler will be used even if the result might not be desired."); Pstring = Pmulti->GetSection()->Add_string("type",Property::Changeable::Always,"normal2x"); const char *scalers[] = { @@ -410,11 +418,13 @@ void DOSBOX_Init(void) { Pmulti_remain = secprop->Add_multiremain("cycles",Property::Changeable::Always," "); Pmulti_remain->Set_help( - "Amount of instructions DOSBox tries to emulate each millisecond. Setting this value too high results in sound dropouts and lags. Cycles can be set in 3 ways:\n" + "Amount of instructions DOSBox tries to emulate each millisecond.\n" + "Setting this value too high results in sound dropouts and lags.\n" + "Cycles can be set in 3 ways:\n" " 'auto' tries to guess what a game needs.\n" " It usually works, but can fail for certain games.\n" " 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails.\n" - " (Example: fixed 4000)\n" + " (Example: fixed 4000).\n" " 'max' will allocate as much cycles as your computer is able to handle.\n"); const char* cyclest[] = { "auto","fixed","max","%u",0 }; @@ -424,9 +434,9 @@ void DOSBOX_Init(void) { Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::Always,""); - Pint = secprop->Add_int("cycleup",Property::Changeable::Always,500); + Pint = secprop->Add_int("cycleup",Property::Changeable::Always,10); Pint->SetMinMax(1,1000000); - Pint->Set_help("Amount of cycles to increase/decrease with keycombo."); + Pint->Set_help("Amount of cycles to decrease/increase with keycombo.(CTRL-F11/CTRL-F12)"); Pint = secprop->Add_int("cycledown",Property::Changeable::Always,20); Pint->SetMinMax(1,1000000); @@ -442,25 +452,30 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("mixer",&MIXER_Init); Pbool = secprop->Add_bool("nosound",Property::Changeable::OnlyAtStart,false); Pbool->Set_help("Enable silent mode, sound is still emulated though."); - +#ifdef HW_RVL Pint = secprop->Add_int("rate",Property::Changeable::OnlyAtStart,22050); +#else + Pint = secprop->Add_int("rate",Property::Changeable::OnlyAtStart,44100); +#endif Pint->Set_values(rates); Pint->Set_help("Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality."); +#ifdef HW_RVL const char *blocksizes[] = { "2048", "4096", "8192", "1024", "512", "256", 0}; -#ifdef HW_RVL Pint = secprop->Add_int("blocksize",Property::Changeable::OnlyAtStart,512); #else + const char *blocksizes[] = { + "1024", "2048", "4096", "8192", "512", "256", 0}; Pint = secprop->Add_int("blocksize",Property::Changeable::OnlyAtStart,2048); #endif Pint->Set_values(blocksizes); Pint->Set_help("Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged."); - Pint = secprop->Add_int("prebuffer",Property::Changeable::OnlyAtStart,10); + Pint = secprop->Add_int("prebuffer",Property::Changeable::OnlyAtStart,20); Pint->SetMinMax(0,100); Pint->Set_help("How many milliseconds of data to keep on top of the blocksize."); - + secprop=control->AddSection_prop("midi",&MIDI_Init,true);//done secprop->AddInitFunction(&MPU401_Init,true);//done @@ -476,7 +491,8 @@ void DOSBOX_Init(void) { Pstring->Set_help("Device that will receive the MIDI data from MPU-401."); Pstring = secprop->Add_string("midiconfig",Property::Changeable::WhenIdle,""); - Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use. See README for details."); + Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use.\n" + " See the README/Manual for more details."); #if C_DEBUG secprop=control->AddSection_prop("debug",&DEBUG_Init); @@ -517,8 +533,11 @@ void DOSBOX_Init(void) { Pstring = secprop->Add_string("oplemu",Property::Changeable::WhenIdle,"default"); Pstring->Set_values(oplemus); Pstring->Set_help("Provider for the OPL emulation. compat might provide better quality (see oplrate as well)."); - +#ifdef HW_RVL Pint = secprop->Add_int("oplrate",Property::Changeable::WhenIdle,22050); +#else + Pint = secprop->Add_int("oplrate",Property::Changeable::WhenIdle,44100); +#endif Pint->Set_values(oplrates); Pint->Set_help("Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly)."); @@ -526,8 +545,11 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("gus",&GUS_Init,true); //done Pbool = secprop->Add_bool("gus",Property::Changeable::WhenIdle,false); Pbool->Set_help("Enable the Gravis Ultrasound emulation."); - +#ifdef HW_RVL Pint = secprop->Add_int("gusrate",Property::Changeable::WhenIdle,22050); +#else + Pint = secprop->Add_int("gusrate",Property::Changeable::WhenIdle,44100); +#endif Pint->Set_values(rates); Pint->Set_help("Sample rate of Ultrasound emulation."); @@ -553,8 +575,11 @@ void DOSBOX_Init(void) { secprop = control->AddSection_prop("speaker",&PCSPEAKER_Init,true);//done Pbool = secprop->Add_bool("pcspeaker",Property::Changeable::WhenIdle,true); Pbool->Set_help("Enable PC-Speaker emulation."); - +#ifdef HW_RVL Pint = secprop->Add_int("pcrate",Property::Changeable::WhenIdle,22050); +#else + Pint = secprop->Add_int("pcrate",Property::Changeable::WhenIdle,44100); +#endif Pint->Set_values(rates); Pint->Set_help("Sample rate of the PC-Speaker sound generation."); @@ -563,8 +588,12 @@ void DOSBOX_Init(void) { Pstring = secprop->Add_string("tandy",Property::Changeable::WhenIdle,"auto"); Pstring->Set_values(tandys); Pstring->Set_help("Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'."); - + +#ifdef HW_RVL Pint = secprop->Add_int("tandyrate",Property::Changeable::WhenIdle,22050); +#else + Pint = secprop->Add_int("tandyrate",Property::Changeable::WhenIdle,44100); +#endif Pint->Set_values(rates); Pint->Set_help("Sample rate of the Tandy 3-Voice generation."); @@ -587,10 +616,11 @@ void DOSBOX_Init(void) { "4axis_2 (supports one joystick, second joystick used),\n" "fcs (Thrustmaster), ch (CH Flightstick).\n" "none disables joystick emulation.\n" - "auto chooses emulation depending on real joystick(s)."); + "auto chooses emulation depending on real joystick(s).\n" + "(Remember to reset dosbox's mapperfile if you saved it earlier)"); Pbool = secprop->Add_bool("timed",Property::Changeable::WhenIdle,true); - Pbool->Set_help("enable timed intervals for axis. (false is old style behaviour)."); + Pbool->Set_help("enable timed intervals for axis. Experiment with this option, if your joystick drifts (away)."); Pbool = secprop->Add_bool("autofire",Property::Changeable::WhenIdle,false); Pbool->Set_help("continuously fires as long as you keep the button pressed."); @@ -676,10 +706,11 @@ void DOSBOX_Init(void) { secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); MSG_Add("AUTOEXEC_CONFIGFILE_HELP", "Lines in this section will be run at startup.\n" + "You can put your MOUNT lines here.\n" ); MSG_Add("CONFIGFILE_INTRO", - "# This is the configurationfile for DOSBox %s.\n" - "# Lines starting with a # are commentlines.\n" + "# This is the configurationfile for DOSBox %s. (Please use the latest version of DOSBox)\n" + "# Lines starting with a # are commentlines and are ignored by DOSBox.\n" "# They are used to (briefly) document the effect of each option.\n"); MSG_Add("CONFIG_SUGGESTED_VALUES", "Possible values"); diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index 9a505a2..06b9747 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -97,7 +97,7 @@ static Real64 FPU_FLD80(PhysPt addr) { test.eind.l.lower = mem_readd(addr); test.eind.l.upper = mem_readd(addr+4); test.begin = mem_readw(addr+8); - + Bit64s exp64 = (((test.begin&0x7fff) - BIAS80)); Bit64s blah = ((exp64 >0)?exp64:-exp64)&0x3ff; Bit64s exp64final = ((exp64 >0)?blah:-blah) +BIAS64; @@ -106,6 +106,11 @@ static Real64 FPU_FLD80(PhysPt addr) { Bit64s sign = (test.begin&0x8000)?1:0; FPU_Reg result; result.ll = (sign <<63)|(exp64final << 52)| mant64; + + if(test.eind.l.lower == 0 && test.eind.l.upper == 0x80000000 && (test.begin&0x7fff) == 0x7fff) { + //Detect INF and -INF (score 3.11 when drawing a slur.) + result.d = sign?-HUGE_VAL:HUGE_VAL; + } return result.d; //mant64= test.mant80/2***64 * 2 **53 diff --git a/src/gui/render.cpp b/src/gui/render.cpp index c76047c..1ba6097 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -201,7 +201,7 @@ static void RENDER_Halt( void ) { } extern Bitu PIC_Ticks; -void RENDER_EndUpdate( void ) { +void RENDER_EndUpdate( bool abort ) { if (GCC_UNLIKELY(!render.updating)) return; RENDER_DrawLine = RENDER_EmptyLineHandler; @@ -220,7 +220,7 @@ void RENDER_EndUpdate( void ) { flags, fps, (Bit8u *)&scalerSourceCache, (Bit8u*)&render.pal.rgb ); } if ( render.scale.outWrite ) { - GFX_EndUpdate( Scaler_ChangedLines ); + GFX_EndUpdate( abort? NULL : Scaler_ChangedLines ); render.frameskip.hadSkip[render.frameskip.index] = 0; } else { #if 0 diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp index 60393cf..c905c05 100644 --- a/src/gui/sdl_mapper.cpp +++ b/src/gui/sdl_mapper.cpp @@ -1776,7 +1776,7 @@ static void CreateLayout(void) { #define BH 20 #define DX 5 #define PX(_X_) ((_X_)*BW + DX) -#define PY(_Y_) (30+(_Y_)*BH) +#define PY(_Y_) (10+(_Y_)*BH) AddKeyButtonEvent(PX(0),PY(0),BW,BH,"ESC","esc",KBD_esc); for (i=0;i<12;i++) AddKeyButtonEvent(PX(2+i),PY(0),BW,BH,combo_f[i].title,combo_f[i].entry,combo_f[i].key); for (i=0;i<14;i++) AddKeyButtonEvent(PX( i),PY(1),BW,BH,combo_1[i].title,combo_1[i].entry,combo_1[i].key); @@ -1801,62 +1801,71 @@ static void CreateLayout(void) { AddKeyButtonEvent(PX(14),PY(5),BW*2,BH,"CTRL","rctrl",KBD_rightctrl); /* Arrow Keys */ - AddKeyButtonEvent(PX(0),PY(7),BW,BH,"PRT","printscreen",KBD_printscreen); - AddKeyButtonEvent(PX(1),PY(7),BW,BH,"SCL","scrolllock",KBD_scrolllock); - AddKeyButtonEvent(PX(2),PY(7),BW,BH,"PAU","pause",KBD_pause); - AddKeyButtonEvent(PX(0),PY(8),BW,BH,"INS","insert",KBD_insert); - AddKeyButtonEvent(PX(1),PY(8),BW,BH,"HOM","home",KBD_home); - AddKeyButtonEvent(PX(2),PY(8),BW,BH,"PUP","pageup",KBD_pageup); - AddKeyButtonEvent(PX(0),PY(9),BW,BH,"DEL","delete",KBD_delete); - AddKeyButtonEvent(PX(1),PY(9),BW,BH,"END","end",KBD_end); - AddKeyButtonEvent(PX(2),PY(9),BW,BH,"PDN","pagedown",KBD_pagedown); - AddKeyButtonEvent(PX(1),PY(10),BW,BH,"\x18","up",KBD_up); - AddKeyButtonEvent(PX(0),PY(11),BW,BH,"\x1B","left",KBD_left); - AddKeyButtonEvent(PX(1),PY(11),BW,BH,"\x19","down",KBD_down); - AddKeyButtonEvent(PX(2),PY(11),BW,BH,"\x1A","right",KBD_right); +#define XO 17 +#define YO 0 + AddKeyButtonEvent(PX(XO+0),PY(YO),BW,BH,"PRT","printscreen",KBD_printscreen); + AddKeyButtonEvent(PX(XO+1),PY(YO),BW,BH,"SCL","scrolllock",KBD_scrolllock); + AddKeyButtonEvent(PX(XO+2),PY(YO),BW,BH,"PAU","pause",KBD_pause); + AddKeyButtonEvent(PX(XO+0),PY(YO+1),BW,BH,"INS","insert",KBD_insert); + AddKeyButtonEvent(PX(XO+1),PY(YO+1),BW,BH,"HOM","home",KBD_home); + AddKeyButtonEvent(PX(XO+2),PY(YO+1),BW,BH,"PUP","pageup",KBD_pageup); + AddKeyButtonEvent(PX(XO+0),PY(YO+2),BW,BH,"DEL","delete",KBD_delete); + AddKeyButtonEvent(PX(XO+1),PY(YO+2),BW,BH,"END","end",KBD_end); + AddKeyButtonEvent(PX(XO+2),PY(YO+2),BW,BH,"PDN","pagedown",KBD_pagedown); + AddKeyButtonEvent(PX(XO+1),PY(YO+4),BW,BH,"\x18","up",KBD_up); + AddKeyButtonEvent(PX(XO+0),PY(YO+5),BW,BH,"\x1B","left",KBD_left); + AddKeyButtonEvent(PX(XO+1),PY(YO+5),BW,BH,"\x19","down",KBD_down); + AddKeyButtonEvent(PX(XO+2),PY(YO+5),BW,BH,"\x1A","right",KBD_right); +#undef XO +#undef YO +#define XO 0 +#define YO 7 /* Numeric KeyPad */ - num_lock_event=AddKeyButtonEvent(PX(4),PY(7),BW,BH,"NUM","numlock",KBD_numlock); - AddKeyButtonEvent(PX(5),PY(7),BW,BH,"/","kp_divide",KBD_kpdivide); - AddKeyButtonEvent(PX(6),PY(7),BW,BH,"*","kp_multiply",KBD_kpmultiply); - AddKeyButtonEvent(PX(7),PY(7),BW,BH,"-","kp_minus",KBD_kpminus); - AddKeyButtonEvent(PX(4),PY(8),BW,BH,"7","kp_7",KBD_kp7); - AddKeyButtonEvent(PX(5),PY(8),BW,BH,"8","kp_8",KBD_kp8); - AddKeyButtonEvent(PX(6),PY(8),BW,BH,"9","kp_9",KBD_kp9); - AddKeyButtonEvent(PX(7),PY(8),BW,BH*2,"+","kp_plus",KBD_kpplus); - AddKeyButtonEvent(PX(4),PY(9),BW,BH,"4","kp_4",KBD_kp4); - AddKeyButtonEvent(PX(5),PY(9),BW,BH,"5","kp_5",KBD_kp5); - AddKeyButtonEvent(PX(6),PY(9),BW,BH,"6","kp_6",KBD_kp6); - AddKeyButtonEvent(PX(4),PY(10),BW,BH,"1","kp_1",KBD_kp1); - AddKeyButtonEvent(PX(5),PY(10),BW,BH,"2","kp_2",KBD_kp2); - AddKeyButtonEvent(PX(6),PY(10),BW,BH,"3","kp_3",KBD_kp3); - AddKeyButtonEvent(PX(7),PY(10),BW,BH*2,"ENT","kp_enter",KBD_kpenter); - AddKeyButtonEvent(PX(4),PY(11),BW*2,BH,"0","kp_0",KBD_kp0); - AddKeyButtonEvent(PX(6),PY(11),BW,BH,".","kp_period",KBD_kpperiod); - + num_lock_event=AddKeyButtonEvent(PX(XO),PY(YO),BW,BH,"NUM","numlock",KBD_numlock); + AddKeyButtonEvent(PX(XO+1),PY(YO),BW,BH,"/","kp_divide",KBD_kpdivide); + AddKeyButtonEvent(PX(XO+2),PY(YO),BW,BH,"*","kp_multiply",KBD_kpmultiply); + AddKeyButtonEvent(PX(XO+3),PY(YO),BW,BH,"-","kp_minus",KBD_kpminus); + AddKeyButtonEvent(PX(XO+0),PY(YO+1),BW,BH,"7","kp_7",KBD_kp7); + AddKeyButtonEvent(PX(XO+1),PY(YO+1),BW,BH,"8","kp_8",KBD_kp8); + AddKeyButtonEvent(PX(XO+2),PY(YO+1),BW,BH,"9","kp_9",KBD_kp9); + AddKeyButtonEvent(PX(XO+3),PY(YO+1),BW,BH*2,"+","kp_plus",KBD_kpplus); + AddKeyButtonEvent(PX(XO),PY(YO+2),BW,BH,"4","kp_4",KBD_kp4); + AddKeyButtonEvent(PX(XO+1),PY(YO+2),BW,BH,"5","kp_5",KBD_kp5); + AddKeyButtonEvent(PX(XO+2),PY(YO+2),BW,BH,"6","kp_6",KBD_kp6); + AddKeyButtonEvent(PX(XO+0),PY(YO+3),BW,BH,"1","kp_1",KBD_kp1); + AddKeyButtonEvent(PX(XO+1),PY(YO+3),BW,BH,"2","kp_2",KBD_kp2); + AddKeyButtonEvent(PX(XO+2),PY(YO+3),BW,BH,"3","kp_3",KBD_kp3); + AddKeyButtonEvent(PX(XO+3),PY(YO+3),BW,BH*2,"ENT","kp_enter",KBD_kpenter); + AddKeyButtonEvent(PX(XO),PY(YO+4),BW*2,BH,"0","kp_0",KBD_kp0); + AddKeyButtonEvent(PX(XO+2),PY(YO+4),BW,BH,".","kp_period",KBD_kpperiod); +#undef XO +#undef YO +#define XO 10 +#define YO 8 /* Joystick Buttons/Texts */ /* Buttons 1+2 of 1st Joystick */ - AddJButtonButton(PX(18),PY(0),BW,BH,"1" ,0,0); - AddJButtonButton(PX(20),PY(0),BW,BH,"2" ,0,1); + AddJButtonButton(PX(XO),PY(YO),BW,BH,"1" ,0,0); + AddJButtonButton(PX(XO+2),PY(YO),BW,BH,"2" ,0,1); /* Axes 1+2 (X+Y) of 1st Joystick */ - CJAxisEvent * cjaxis=AddJAxisButton(PX(19),PY(0),BW,BH,"Y-",0,1,false,NULL); - AddJAxisButton (PX(19),PY(1),BW,BH,"Y+",0,1,true,cjaxis); - cjaxis=AddJAxisButton (PX(18),PY(1),BW,BH,"X-",0,0,false,NULL); - AddJAxisButton (PX(20),PY(1),BW,BH,"X+",0,0,true,cjaxis); + CJAxisEvent * cjaxis=AddJAxisButton(PX(XO+1),PY(YO),BW,BH,"Y-",0,1,false,NULL); + AddJAxisButton (PX(XO+1),PY(YO+1),BW,BH,"Y+",0,1,true,cjaxis); + cjaxis=AddJAxisButton (PX(XO),PY(YO+1),BW,BH,"X-",0,0,false,NULL); + AddJAxisButton (PX(XO+2),PY(YO+1),BW,BH,"X+",0,0,true,cjaxis); if (joytype==JOY_2AXIS) { /* Buttons 1+2 of 2nd Joystick */ - AddJButtonButton(PX(18),PY(3),BW,BH,"1" ,1,0); - AddJButtonButton(PX(20),PY(3),BW,BH,"2" ,1,1); + AddJButtonButton(PX(XO+4),PY(YO),BW,BH,"1" ,1,0); + AddJButtonButton(PX(XO+4+2),PY(YO),BW,BH,"2" ,1,1); /* Buttons 3+4 of 1st Joystick, not accessible */ AddJButtonButton_hidden(0,2); AddJButtonButton_hidden(0,3); /* Axes 1+2 (X+Y) of 2nd Joystick */ - cjaxis= AddJAxisButton(PX(18),PY(4),BW,BH,"X-",1,0,false,NULL); - AddJAxisButton(PX(20),PY(4),BW,BH,"X+",1,0,true,cjaxis); - cjaxis= AddJAxisButton(PX(19),PY(3),BW,BH,"Y-",1,1,false,NULL); - AddJAxisButton(PX(19),PY(4),BW,BH,"Y+",1,1,true,cjaxis); + cjaxis= AddJAxisButton(PX(XO+4),PY(YO+1),BW,BH,"X-",1,0,false,NULL); + AddJAxisButton(PX(XO+4+2),PY(YO+1),BW,BH,"X+",1,0,true,cjaxis); + cjaxis= AddJAxisButton(PX(XO+4+1),PY(YO+0),BW,BH,"Y-",1,1,false,NULL); + AddJAxisButton(PX(XO+4+1),PY(YO+1),BW,BH,"Y+",1,1,true,cjaxis); /* Axes 3+4 (X+Y) of 1st Joystick, not accessible */ cjaxis= AddJAxisButton_hidden(0,2,false,NULL); AddJAxisButton_hidden(0,2,true,cjaxis); @@ -1864,17 +1873,17 @@ static void CreateLayout(void) { AddJAxisButton_hidden(0,3,true,cjaxis); } else { /* Buttons 3+4 of 1st Joystick */ - AddJButtonButton(PX(18),PY(3),BW,BH,"3" ,0,2); - AddJButtonButton(PX(20),PY(3),BW,BH,"4" ,0,3); + AddJButtonButton(PX(XO+4),PY(YO),BW,BH,"3" ,0,2); + AddJButtonButton(PX(XO+4+2),PY(YO),BW,BH,"4" ,0,3); /* Buttons 1+2 of 2nd Joystick, not accessible */ AddJButtonButton_hidden(1,0); AddJButtonButton_hidden(1,1); /* Axes 3+4 (X+Y) of 1st Joystick */ - cjaxis= AddJAxisButton(PX(18),PY(4),BW,BH,"X-",0,2,false,NULL); - AddJAxisButton(PX(20),PY(4),BW,BH,"X+",0,2,true,cjaxis); - cjaxis= AddJAxisButton(PX(19),PY(3),BW,BH,"Y-",0,3,false,NULL); - AddJAxisButton(PX(19),PY(4),BW,BH,"Y+",0,3,true,cjaxis); + cjaxis= AddJAxisButton(PX(XO+4),PY(YO+1),BW,BH,"X-",0,2,false,NULL); + AddJAxisButton(PX(XO+4+2),PY(YO+1),BW,BH,"X+",0,2,true,cjaxis); + cjaxis= AddJAxisButton(PX(XO+4+1),PY(YO+0),BW,BH,"Y-",0,3,false,NULL); + AddJAxisButton(PX(XO+4+1),PY(YO+1),BW,BH,"Y+",0,3,true,cjaxis); /* Axes 1+2 (X+Y) of 2nd Joystick , not accessible*/ cjaxis= AddJAxisButton_hidden(1,0,false,NULL); AddJAxisButton_hidden(1,0,true,cjaxis); @@ -1884,8 +1893,8 @@ static void CreateLayout(void) { if (joytype==JOY_CH) { /* Buttons 5+6 of 1st Joystick */ - AddJButtonButton(PX(18),PY(6),BW,BH,"5" ,0,4); - AddJButtonButton(PX(20),PY(6),BW,BH,"6" ,0,5); + AddJButtonButton(PX(XO+8),PY(YO),BW,BH,"5" ,0,4); + AddJButtonButton(PX(XO+8+2),PY(YO),BW,BH,"6" ,0,5); } else { /* Buttons 5+6 of 1st Joystick, not accessible */ AddJButtonButton_hidden(0,4); @@ -1893,17 +1902,42 @@ static void CreateLayout(void) { } /* Hat directions up, left, down, right */ - AddJHatButton(PX(19),PY(6),BW,BH,"UP",0,0,0); - AddJHatButton(PX(18),PY(7),BW,BH,"LFT",0,0,3); - AddJHatButton(PX(19),PY(7),BW,BH,"DWN",0,0,2); - AddJHatButton(PX(20),PY(7),BW,BH,"RGT",0,0,1); + AddJHatButton(PX(XO+8+1),PY(YO),BW,BH,"UP",0,0,0); + AddJHatButton(PX(XO+8+0),PY(YO+1),BW,BH,"LFT",0,0,3); + AddJHatButton(PX(XO+8+1),PY(YO+1),BW,BH,"DWN",0,0,2); + AddJHatButton(PX(XO+8+2),PY(YO+1),BW,BH,"RGT",0,0,1); + /* Labels for the joystick */ + if (joytype ==JOY_2AXIS) { + new CTextButton(PX(XO+0),PY(YO-1),3*BW,20,"Joystick 1"); + new CTextButton(PX(XO+4),PY(YO-1),3*BW,20,"Joystick 2"); + new CTextButton(PX(XO+8),PY(YO-1),3*BW,20,"Disabled"); + } else if(joytype ==JOY_4AXIS || joytype == JOY_4AXIS_2) { + new CTextButton(PX(XO+0),PY(YO-1),3*BW,20,"Axis 1/2"); + new CTextButton(PX(XO+4),PY(YO-1),3*BW,20,"Axis 3/4"); + new CTextButton(PX(XO+8),PY(YO-1),3*BW,20,"Disabled"); + } else if(joytype == JOY_CH) { + new CTextButton(PX(XO+0),PY(YO-1),3*BW,20,"Axis 1/2"); + new CTextButton(PX(XO+4),PY(YO-1),3*BW,20,"Axis 3/4"); + new CTextButton(PX(XO+8),PY(YO-1),3*BW,20,"Hat/D-pad"); + } else if ( joytype==JOY_FCS) { + new CTextButton(PX(XO+0),PY(YO-1),3*BW,20,"Axis 1/2"); + new CTextButton(PX(XO+4),PY(YO-1),3*BW,20,"Axis 3"); + new CTextButton(PX(XO+8),PY(YO-1),3*BW,20,"Hat/D-pad"); + } else if(joytype == JOY_NONE) { + new CTextButton(PX(XO+0),PY(YO-1),3*BW,20,"Disabled"); + new CTextButton(PX(XO+4),PY(YO-1),3*BW,20,"Disabled"); + new CTextButton(PX(XO+8),PY(YO-1),3*BW,20,"Disabled"); + } + + + /* The modifier buttons */ - AddModButton(PX(0),PY(13),50,20,"Mod1",1); - AddModButton(PX(2),PY(13),50,20,"Mod2",2); - AddModButton(PX(4),PY(13),50,20,"Mod3",3); + AddModButton(PX(0),PY(14),50,20,"Mod1",1); + AddModButton(PX(2),PY(14),50,20,"Mod2",2); + AddModButton(PX(4),PY(14),50,20,"Mod3",3); /* Create Handler buttons */ - Bitu xpos=3;Bitu ypos=10; + Bitu xpos=3;Bitu ypos=11; for (CHandlerEventVector_it hit=handlergroup.begin();hit!=handlergroup.end();hit++) { new CEventButton(PX(xpos*3),PY(ypos),BW*3,BH,(*hit)->ButtonName(),(*hit)); xpos++; @@ -1912,8 +1946,8 @@ static void CreateLayout(void) { } } /* Create some text buttons */ - new CTextButton(PX(6),0,124,20,"Keyboard Layout"); - new CTextButton(PX(17),0,124,20,"Joystick Layout"); +// new CTextButton(PX(6),0,124,20,"Keyboard Layout"); +// new CTextButton(PX(17),0,124,20,"Joystick Layout"); bind_but.action=new CCaptionButton(180,330,0,0); @@ -2083,7 +2117,7 @@ void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char const } static void MAPPER_SaveBinds(void) { - FILE * savefile=fopen(mapper.filename.c_str(),"wb+"); + FILE * savefile=fopen(mapper.filename.c_str(),"wt+"); if (!savefile) { LOG_MSG("Can't open %s for saving the mappings",mapper.filename.c_str()); return; @@ -2105,7 +2139,7 @@ static void MAPPER_SaveBinds(void) { } static bool MAPPER_LoadBinds(void) { - FILE * loadfile=fopen(mapper.filename.c_str(),"rb"); + FILE * loadfile=fopen(mapper.filename.c_str(),"rt"); if (!loadfile) return false; char linein[512]; while (fgets(linein,512,loadfile)) { @@ -2326,11 +2360,17 @@ void MAPPER_Init(void) { if (SDL_GetModState()&KMOD_CAPS) { for (CBindList_it bit=caps_lock_event->bindlist.begin();bit!=caps_lock_event->bindlist.end();bit++) { (*bit)->ActivateBind(32767,true,true); +#if SDL_VERSION_ATLEAST(1, 2, 14) + (*bit)->DeActivateBind(false); +#endif } } if (SDL_GetModState()&KMOD_NUM) { for (CBindList_it bit=num_lock_event->bindlist.begin();bit!=num_lock_event->bindlist.end();bit++) { (*bit)->ActivateBind(32767,true,true); +#if SDL_VERSION_ATLEAST(1, 2, 14) + (*bit)->DeActivateBind(false); +#endif } } } diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 66c6ed6..1188837 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -54,6 +54,7 @@ #include "cross.h" #include "control.h" +#define MAPPERFILE "mapper-" VERSION ".map" //#define DISABLE_JOYSTICK #if C_OPENGL @@ -238,12 +239,9 @@ void GFX_SetTitle(Bit32s cycles,Bits frameskip,bool paused){ if(cycles != -1) internal_cycles = cycles; if(frameskip != -1) internal_frameskip = frameskip; if(CPU_CycleAutoAdjust) { - if (internal_cycles>=100) - sprintf(title,"DOSBox %s, Cpu Cycles: max, Frameskip %2d, Program: %8s",VERSION,internal_frameskip,RunningProgram); - else - sprintf(title,"DOSBox %s, Cpu Cycles: [%3d%%], Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); + sprintf(title,"DOSBox %s, Cpu speed: max %3d%% cycles, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); } else { - sprintf(title,"DOSBox %s, Cpu Cycles: %8d, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); + sprintf(title,"DOSBox %s, Cpu speed: %8d cycles, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); } if(paused) strcat(title," PAUSED"); @@ -1505,13 +1503,16 @@ void Config_Add_SDL() { #else Pbool = sdl_sec->Add_bool("fulldouble",Property::Changeable::Always,false); #endif - Pbool->Set_help("Use double buffering in fullscreen."); + Pbool->Set_help("Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox."); Pstring = sdl_sec->Add_string("fullresolution",Property::Changeable::Always,"original"); - Pstring->Set_help("What resolution to use for fullscreen: original or fixed size (e.g. 1024x768)."); + Pstring->Set_help("What resolution to use for fullscreen: original or fixed size (e.g. 1024x768).\n" + " Using your monitor's native resolution with aspect=true might give the best results.\n" + " If you end up with small window on a large screen, try an output different from surface."); Pstring = sdl_sec->Add_string("windowresolution",Property::Changeable::Always,"original"); - Pstring->Set_help("Scale the window to this size IF the output device supports hardware scaling."); + Pstring->Set_help("Scale the window to this size IF the output device supports hardware scaling.\n" + " (output=surface does not!)"); const char* outputs[] = { "surface", "overlay", @@ -1527,7 +1528,7 @@ void Config_Add_SDL() { Pstring->Set_values(outputs); Pbool = sdl_sec->Add_bool("autolock",Property::Changeable::Always,true); - Pbool->Set_help("Mouse will automatically lock, if you click on the screen."); + Pbool->Set_help("Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock)"); Pint = sdl_sec->Add_int("sensitivity",Property::Changeable::Always,100); Pint->SetMinMax(1,1000); @@ -1538,7 +1539,8 @@ void Config_Add_SDL() { Pmulti = sdl_sec->Add_multi("priority", Property::Changeable::Always, ","); Pmulti->SetValue("higher,normal"); - Pmulti->Set_help("Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. (pause is only valid for the second entry)"); + Pmulti->Set_help("Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized.\n" + " pause is only valid for the second entry."); const char* actt[] = { "lowest", "lower", "normal", "higher", "highest", "pause", 0}; Pstring = Pmulti->GetSection()->Add_string("active",Property::Changeable::Always,"higher"); @@ -1548,8 +1550,8 @@ void Config_Add_SDL() { Pstring = Pmulti->GetSection()->Add_string("inactive",Property::Changeable::Always,"normal"); Pstring->Set_values(inactt); - Pstring = sdl_sec->Add_path("mapperfile",Property::Changeable::Always,"mapper.conf"); - Pstring->Set_help("File used to load/save the key/event mappings from."); + Pstring = sdl_sec->Add_path("mapperfile",Property::Changeable::Always,MAPPERFILE); + Pstring->Set_help("File used to load/save the key/event mappings from. Resetmapper only works with the defaul value."); Pbool = sdl_sec->Add_bool("usescancodes",Property::Changeable::Always,true); Pbool->Set_help("Avoid usage of symkeys, might not work on all operating systems."); @@ -1594,7 +1596,7 @@ static void show_warning(char const * const message) { SDL_BlitSurface(splash_surf, NULL, sdl.surface, NULL); SDL_Flip(sdl.surface); - SDL_Delay(10000); + SDL_Delay(12000); } static void launcheditor() { @@ -1666,7 +1668,7 @@ static void eraseconfigfile() { FILE* f = fopen("dosbox.conf","r"); if(f) { fclose(f); - //show_warning("Warning: dosbox.conf exists in current working directory.\nThis will override the configuration file at runtime.\n"); + show_warning("Warning: dosbox.conf exists in current working directory.\nThis will override the configuration file at runtime.\n"); } std::string path,file; Cross::GetPlatformConfigDir(path); @@ -1679,7 +1681,27 @@ static void eraseconfigfile() { exit(0); } +static void erasemapperfile() { + FILE* g = fopen("dosbox.conf","r"); + if(g) { + fclose(g); + show_warning("Warning: dosbox.conf exists in current working directory.\nKeymapping might not be properly reset.\n" + "Please reset configuration as well and delete the dosbox.conf.\n"); + } + + std::string path,file=MAPPERFILE; + Cross::GetPlatformConfigDir(path); + path += file; + FILE* f = fopen(path.c_str(),"r"); + if(!f) exit(0); + fclose(f); + unlink(path.c_str()); + exit(0); +} + +#ifdef HW_RVL int MountDOSBoxDir(char DriveLetter, const char *path); +#endif //extern void UI_Init(void); int main(int argc, char* argv[]) { @@ -1700,6 +1722,9 @@ int main(int argc, char* argv[]) { if(control->cmdline->FindString("-editconf",editor,false)) launcheditor(); if(control->cmdline->FindString("-opencaptures",editor,true)) launchcaptures(editor); if(control->cmdline->FindExist("-eraseconf")) eraseconfigfile(); + if(control->cmdline->FindExist("-resetconf")) eraseconfigfile(); + if(control->cmdline->FindExist("-erasemapper")) erasemapperfile(); + if(control->cmdline->FindExist("-resetmapper")) erasemapperfile(); /* Can't disable the console with debugger enabled */ #if defined(WIN32) && !(C_DEBUG) @@ -1808,7 +1833,28 @@ int main(int argc, char* argv[]) { /* Parse configuration files */ std::string config_file,config_path; bool parsed_anyconfigfile = false; - //First Parse -conf switches + //First Parse -userconf + if(control->cmdline->FindExist("-userconf",true)){ + config_file.clear(); + Cross::GetPlatformConfigDir(config_path); + Cross::GetPlatformConfigName(config_file); + config_path += config_file; + if(control->ParseConfigFile(config_path.c_str())) parsed_anyconfigfile = true; + if(!parsed_anyconfigfile) { + //Try to create the userlevel configfile. + config_file.clear(); + Cross::CreatePlatformConfigDir(config_path); + Cross::GetPlatformConfigName(config_file); + config_path += config_file; + if(control->PrintConfig(config_path.c_str())) { + LOG_MSG("CONFIG: Generating default configuration.\nWriting it to %s",config_path.c_str()); + //Load them as well. Makes relative paths much easier + if(control->ParseConfigFile(config_path.c_str())) parsed_anyconfigfile = true; + } + } + } + + //Second parse -conf entries while(control->cmdline->FindString("-conf",config_file,true)) if (control->ParseConfigFile(config_file.c_str())) parsed_anyconfigfile = true; diff --git a/src/hardware/dbopl.cpp b/src/hardware/dbopl.cpp index df1c754..5615335 100644 --- a/src/hardware/dbopl.cpp +++ b/src/hardware/dbopl.cpp @@ -619,6 +619,7 @@ Operator::Operator() { currentLevel = ENV_MAX; totalLevel = ENV_MAX; volume = ENV_MAX; + releaseAdd = 0; } /* @@ -1176,9 +1177,7 @@ Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) { void Chip::GenerateBlock2( Bitu total, Bit32s* output ) { while ( total > 0 ) { Bit32u samples = ForwardLFO( total ); - for ( Bitu i = 0; i < samples; i++ ) { - output[i] = 0; - } + memset(output, 0, sizeof(Bit32s) * samples); int count = 0; for( Channel* ch = chan; ch < chan + 9; ) { count++; @@ -1192,10 +1191,7 @@ void Chip::GenerateBlock2( Bitu total, Bit32s* output ) { void Chip::GenerateBlock3( Bitu total, Bit32s* output ) { while ( total > 0 ) { Bit32u samples = ForwardLFO( total ); - for ( Bitu i = 0; i < samples; i++ ) { - output[i * 2 + 0 ] = 0; - output[i * 2 + 1 ] = 0; - } + memset(output, 0, sizeof(Bit32s) * samples *2); int count = 0; for( Channel* ch = chan; ch < chan + 18; ) { count++; diff --git a/src/hardware/gameblaster.cpp b/src/hardware/gameblaster.cpp index 210817c..84a2ee7 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.cpp @@ -80,7 +80,7 @@ struct SAA1099 struct saa1099_noise noise[2]; /* noise generators */ }; -static UINT8 envelope[8][64] = { +static const UINT8 envelope[8][64] = { /* zero amplitude */ { 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, @@ -124,7 +124,7 @@ static UINT8 envelope[8][64] = { }; -static int amplitude_lookup[16] = { +static const int amplitude_lookup[16] = { 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16, 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16, 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16, diff --git a/src/hardware/mixer.cpp b/src/hardware/mixer.cpp index 202f101..555205f 100644 --- a/src/hardware/mixer.cpp +++ b/src/hardware/mixer.cpp @@ -652,6 +652,8 @@ void MIXER_Init(Section* sec) { mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; TIMER_AddTickHandler(MIXER_Mix_NoSound); } else { + if((mixer.freq != obtained.freq) || (mixer.blocksize != obtained.samples)) + LOG_MSG("MIXER:Got different values from SDL: freq %d, blocksize %d",obtained.freq,obtained.samples); mixer.freq=obtained.freq; mixer.blocksize=obtained.samples; mixer.tick_add=(mixer.freq << MIXER_SHIFT)/1000; diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index 0ad028f..e0427e9 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -1469,6 +1469,7 @@ private: IO_WriteHandleObject WriteHandler[0x10]; AutoexecObject autoexecline; MixerObject MixerChan; + OPL_Mode oplmode; /* Support Functions */ void Find_Type_And_Opl(Section_prop* config,SB_TYPES& type, OPL_Mode& opl_mode){ @@ -1497,14 +1498,22 @@ private: else { switch (type) { case SBT_NONE: + opl_mode=OPL_none; + break; case SBT_GB: - opl_mode=OPL_none;break; - case SBT_1:opl_mode=OPL_opl2;break; - case SBT_2:opl_mode=OPL_opl2;break; - case SBT_PRO1:opl_mode=OPL_dualopl2;break; + opl_mode=OPL_cms; + break; + case SBT_1: + case SBT_2: + opl_mode=OPL_opl2; + break; + case SBT_PRO1: + opl_mode=OPL_dualopl2; + break; case SBT_PRO2: case SBT_16: - opl_mode=OPL_opl3;break; + opl_mode=OPL_opl3; + break; } } } @@ -1524,27 +1533,25 @@ public: sb.mixer.enabled=section->Get_bool("sbmixer"); sb.mixer.stereo=false; - OPL_Mode opl_mode = OPL_none; - Find_Type_And_Opl(section,sb.type,opl_mode); - - bool do_cms = (sb.type==SBT_GB)? true:false; - switch (opl_mode) { + Find_Type_And_Opl(section,sb.type,oplmode); + + switch (oplmode) { case OPL_none: WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); break; case OPL_cms: WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); - do_cms = true; + CMS_Init(section); break; case OPL_opl2: - do_cms = true; + CMS_Init(section); + // fall-through case OPL_dualopl2: case OPL_opl3: - OPL_Init(section,opl_mode); + OPL_Init(section,oplmode); break; } - if (do_cms) CMS_Init(section); if (sb.type==SBT_NONE || sb.type==SBT_GB) return; sb.chan=MixerChan.Install(&SBLASTER_CallBack,22050,"SB"); @@ -1588,28 +1595,22 @@ public: } ~SBLASTER() { - Section_prop * section=static_cast(m_configuration); - OPL_Mode opl_mode = OPL_none; - Find_Type_And_Opl(section,sb.type,opl_mode); - - switch (opl_mode) { + switch (oplmode) { case OPL_none: - break; case OPL_cms: - - CMS_ShutDown(m_configuration); + CMS_ShutDown(m_configuration); break; case OPL_opl2: - CMS_ShutDown(m_configuration); + CMS_ShutDown(m_configuration); + // fall-through case OPL_dualopl2: case OPL_opl3: - OPL_ShutDown(m_configuration); + OPL_ShutDown(m_configuration); break; } - if (sb.type==SBT_NONE || sb.type==SBT_GB) return; - DSP_Reset();//Stop everything + DSP_Reset(); // Stop everything } }; //End of SBLASTER class diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 74edb83..c76763d 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -41,6 +41,12 @@ Bit32u Expand16Table[4][16]; Bit32u FillTable[16]; Bit32u ColorTable[16]; +void VGA_SetModeNow(VGAModes mode) { + if (vga.mode == mode) return; + vga.mode=mode; + VGA_SetupHandlers(); + VGA_StartResize(0); +} void VGA_SetMode(VGAModes mode) { @@ -85,8 +91,10 @@ void VGA_DetermineMode(void) { void VGA_StartResize(Bitu delay /*=50*/) { if (!vga.draw.resizing) { vga.draw.resizing=true; + if (vga.mode==M_ERROR) delay = 5; /* Start a resize after delay (default 50 ms) */ - PIC_AddEvent(VGA_SetupDrawing,(float)delay); + if (delay==0) VGA_SetupDrawing(0); + else PIC_AddEvent(VGA_SetupDrawing,(float)delay); } } @@ -167,8 +175,6 @@ void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3) { void VGA_Init(Section* sec) { // Section_prop * section=static_cast(sec); -// vga.screenflip = section->Get_int("screenflip"); - vga.screenflip = 0; vga.draw.resizing=false; vga.mode=M_ERROR; //For first init SVGA_Setup_Driver(); diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index 1f1371b..9f23b50 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -46,7 +46,7 @@ void VGA_ATTR_SetPalette(Bit8u index,Bit8u val) { Bitu read_p3c0(Bitu /*port*/,Bitu /*iolen*/) { // Wcharts, Win 3.11 & 95 SVGA Bitu retval = attr(index) & 0x1f; - if (attr(enabled)) retval |= 0x20; + if (!(attr(disabled) & 0x1)) retval |= 0x20; return retval; } @@ -54,7 +54,8 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) { if (!vga.internal.attrindex) { attr(index)=val & 0x1F; vga.internal.attrindex=true; - attr(enabled)=val & 0x20; + if (val & 0x20) attr(disabled) &= ~1; + else attr(disabled) |= 1; /* 0-4 Address of data register to write to port 3C0h or read from port 3C1h 5 If set screen output is enabled and the palette can not be modified, @@ -69,7 +70,7 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) { case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: - if (!attr(enabled)) VGA_ATTR_SetPalette(attr(index),(Bit8u)val); + if (attr(disabled) & 0x1) VGA_ATTR_SetPalette(attr(index),(Bit8u)val); /* 0-5 Index into the 256 color DAC table. May be modified by 3C0h index 10h and 14h. diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 3edf56c..459e768 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -27,6 +27,10 @@ #include "vga.h" #include "pic.h" +//#undef C_DEBUG +//#define C_DEBUG 1 +//#define LOG(X,Y) LOG_MSG + #define VGA_PARTS 4 typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart, Bitu line); @@ -637,15 +641,13 @@ static void VGA_ProcessSplit() { } static void VGA_DrawSingleLine(Bitu /*blah*/) { - if (vga.attr.enabled) { - Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line ); - RENDER_DrawLine(data); - } else { - // else draw overscan color line - // TODO: black line should be good enough for now - // (DoWhackaDo) + if (GCC_UNLIKELY(vga.attr.disabled)) { + // draw blanked line (DoWhackaDo, Alien Carnage, TV sports Football) memset(TempLine, 0, sizeof(TempLine)); RENDER_DrawLine(TempLine); + } else { + Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line ); + RENDER_DrawLine(data); } vga.draw.address_line++; @@ -657,7 +659,7 @@ static void VGA_DrawSingleLine(Bitu /*blah*/) { if (vga.draw.split_line==vga.draw.lines_done) VGA_ProcessSplit(); if (vga.draw.lines_done < vga.draw.lines_total) { PIC_AddEvent(VGA_DrawSingleLine,(float)vga.draw.delay.htotal); - } else RENDER_EndUpdate(); + } else RENDER_EndUpdate(false); } static void VGA_DrawPart(Bitu lines) { @@ -687,7 +689,7 @@ static void VGA_DrawPart(Bitu lines) { #ifdef VGA_KEEP_CHANGES VGA_ChangesEnd(); #endif - RENDER_EndUpdate(); + RENDER_EndUpdate(false); } } @@ -736,6 +738,11 @@ static void VGA_VertInterrupt(Bitu /*val*/) { } } +static void VGA_Other_VertInterrupt(Bitu val) { + if (val) PIC_ActivateIRQ(5); + else PIC_DeActivateIRQ(5); +} + static void VGA_DisplayStartLatch(Bitu /*val*/) { vga.config.real_start=vga.config.display_start & (vga.vmemwrap-1); vga.draw.bytes_skip = vga.config.bytes_skip; @@ -746,43 +753,40 @@ static void VGA_PanningLatch(Bitu /*val*/) { } static void VGA_VerticalTimer(Bitu /*val*/) { - double error = vga.draw.delay.framestart; vga.draw.delay.framestart = PIC_FullIndex(); - error = vga.draw.delay.framestart - error - vga.draw.delay.vtotal; PIC_AddEvent( VGA_VerticalTimer, (float)vga.draw.delay.vtotal ); - //PIC_AddEvent( VGA_VerticalDisplayEnd, (float)vga.draw.delay.vrstart ); - double flip_offset = vga.screenflip/1000.0 + vga.draw.delay.vrstart; - if(flip_offset > vga.draw.delay.vtotal) { + + switch(machine) { + case MCH_PCJR: + case MCH_TANDY: + // PCJr: Vsync is directly connected to the IRQ controller + // Some earlier Tandy models are said to have a vsync interrupt too + PIC_AddEvent(VGA_Other_VertInterrupt, (float)vga.draw.delay.vrstart, 1); + PIC_AddEvent(VGA_Other_VertInterrupt, (float)vga.draw.delay.vrend, 0); + // fall-through + case MCH_CGA: + case MCH_HERC: + // MC6845-powered graphics: Loading the display start latch happens somewhere + // after vsync off and before first visible scanline, so probably here VGA_DisplayStartLatch(0); - } else PIC_AddEvent( VGA_DisplayStartLatch,(float)flip_offset); - PIC_AddEvent(VGA_PanningLatch,(float)vga.draw.delay.vrend); - - // EGA: 82c435 datasheet: interrupt happens at display end - // VGA: checked with scope - // add a little amount of time to make sure the last drawpart has already fired - if (IS_EGAVGA_ARCH) PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005)); - - if ( GCC_UNLIKELY( vga.draw.parts_left)) { - if (!IS_VGA_ARCH || (svgaCard!=SVGA_None)) { - LOG(LOG_VGAMISC,LOG_NORMAL)( "Parts left: %d", vga.draw.parts_left ); - PIC_RemoveEvents( &VGA_DrawPart ); - RENDER_EndUpdate(); - vga.draw.parts_left = 0; - } + break; + case MCH_VGA: + case MCH_EGA: + PIC_AddEvent(VGA_DisplayStartLatch, (float)vga.draw.delay.vrstart); + PIC_AddEvent(VGA_PanningLatch, (float)vga.draw.delay.vrend); + // EGA: 82c435 datasheet: interrupt happens at display end + // VGA: checked with scope; however disabled by default by jumper on VGA boards + // add a little amount of time to make sure the last drawpart has already fired + PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005)); + break; + default: + E_Exit("This new machine needs implementation in VGA_VerticalTimer too."); + break; } - //Check if we can actually render, else skip the rest + //Check if we can actually render, else skip the rest (frameskip) if (!RENDER_StartUpdate()) return; - if ( GCC_UNLIKELY( vga.draw.lines_done < vga.draw.lines_total)) { - if (IS_VGA_ARCH && (svgaCard==SVGA_None)) { - while(vga.draw.lines_done < vga.draw.lines_total) - VGA_DrawSingleLine(0); - PIC_RemoveEvents(VGA_DrawSingleLine); - } - } - //TODO Maybe check for an active frame on parts_left and clear that first? - vga.draw.parts_left = vga.draw.parts_total; - vga.draw.lines_done = 0; + vga.draw.address_line = vga.config.hlines_skip; if (IS_EGAVGA_ARCH) { vga.draw.split_line = (Bitu)((vga.config.line_compare+1)/vga.draw.lines_scaled); @@ -864,17 +868,38 @@ static void VGA_VerticalTimer(Bitu /*val*/) { #ifdef VGA_KEEP_CHANGES if (startaddr_changed) VGA_ChangesStart(); #endif + + // check if some lines at the top off the screen are blanked float draw_skip = 0.0; if (GCC_UNLIKELY(vga.draw.vblank_skip)) { draw_skip = (float)(vga.draw.delay.htotal * vga.draw.vblank_skip); vga.draw.address += vga.draw.address_add * (vga.draw.vblank_skip/(vga.draw.address_line_total)); } - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip)); - else PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts + draw_skip,vga.draw.parts_lines); - //VGA_DrawPart( vga.draw.parts_lines ); - //PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts,vga.draw.parts_lines); - //PIC_AddEvent(VGA_DrawPart,(float)(vga.draw.delay.parts/2),vga.draw.parts_lines); //Else tearline in Tyrian and second reality + // add the draw event + switch (vga.draw.mode) { + case PART: + if (GCC_UNLIKELY(vga.draw.parts_left)) { + LOG(LOG_VGAMISC,LOG_NORMAL)( "Parts left: %d", vga.draw.parts_left ); + PIC_RemoveEvents(VGA_DrawPart); + RENDER_EndUpdate(true); + } + vga.draw.lines_done = 0; + vga.draw.parts_left = vga.draw.parts_total; + PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts + draw_skip,vga.draw.parts_lines); + break; + case LINE: + if (GCC_UNLIKELY(vga.draw.lines_done < vga.draw.lines_total)) { + LOG(LOG_VGAMISC,LOG_NORMAL)( "Lines left: %d", + vga.draw.lines_total-vga.draw.lines_done); + PIC_RemoveEvents(VGA_DrawSingleLine); + RENDER_EndUpdate(true); + } + vga.draw.lines_done = 0; + PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0 + draw_skip)); + break; + //case EGALINE: + } } void VGA_CheckScanLength(void) { @@ -951,8 +976,25 @@ void VGA_SetupDrawing(Bitu /*val*/) { PIC_RemoveEvents(VGA_DisplayStartLatch); return; } + // set the drawing mode + switch (machine) { + case MCH_CGA: + case MCH_PCJR: + vga.draw.mode = LINE; + break; + case MCH_VGA: + if (svgaCard==SVGA_None) { + vga.draw.mode = LINE; + break; + } + // fall-through + default: + vga.draw.mode = PART; + break; + } + /* Calculate the FPS for this screen */ - float fps; Bitu clock; + double fps; Bitu clock; Bitu htotal, hdend, hbstart, hbend, hrstart, hrend; Bitu vtotal, vdend, vbstart, vbend, vrstart, vrend; Bitu vblank_skip; @@ -1052,17 +1094,13 @@ void VGA_SetupDrawing(Bitu /*val*/) { hbstart = hdend; hbend = htotal; hrstart = vga.other.hsyncp; - hrend = hrstart + (vga.other.syncw & 0xf) ; + hrend = hrstart + vga.other.hsyncw; vga.draw.address_line_total = vga.other.max_scanline + 1; vtotal = vga.draw.address_line_total * (vga.other.vtotal+1)+vga.other.vadjust; vdend = vga.draw.address_line_total * vga.other.vdend; vrstart = vga.draw.address_line_total * vga.other.vsyncp; - vrend = (vga.other.syncw >> 4); - if (!vrend) - vrend = vrstart + 0xf + 1; - else - vrend = vrstart + vrend; + vrend = vrstart + 16; // vsync width is fixed to 16 lines on the MC6845 TODO Tandy vbstart = vdend; vbend = vtotal; vga.draw.double_scan=false; @@ -1090,16 +1128,16 @@ void VGA_SetupDrawing(Bitu /*val*/) { if (!htotal) return; if (!vtotal) return; - fps=(float)clock/(vtotal*htotal); - // The time a complete video frame takes - vga.draw.delay.vtotal = (1000.0 * (double)(vtotal*htotal)) / (double)clock; + // The screen refresh frequency + fps=(double)clock/(vtotal*htotal); // Horizontal total (that's how long a line takes with whistles and bells) vga.draw.delay.htotal = htotal*1000.0/clock; //in milliseconds // Start and End of horizontal blanking vga.draw.delay.hblkstart = hbstart*1000.0/clock; //in milliseconds vga.draw.delay.hblkend = hbend*1000.0/clock; - vga.draw.delay.hrstart = 0; - + // Start and End of horizontal retrace + vga.draw.delay.hrstart = hrstart*1000.0/clock; + vga.draw.delay.hrend = hrend*1000.0/clock; // Start and End of vertical blanking vga.draw.delay.vblkstart = vbstart * vga.draw.delay.htotal; vga.draw.delay.vblkend = vbend * vga.draw.delay.htotal; @@ -1110,48 +1148,39 @@ void VGA_SetupDrawing(Bitu /*val*/) { // Vertical blanking tricks vblank_skip = 0; if (IS_VGA_ARCH) { // others need more investigation - if (vbend > vtotal) { - // blanking wraps to the start of the screen - vblank_skip = vbend&0x7f; - - // on blanking wrap to 0, the first line is not blanked - // this is used by the S3 BIOS and other S3 drivers in some SVGA modes - if((vbend&0x7f)==1) vblank_skip = 0; - - // it might also cut some lines off the bottom - if(vbstart < vdend) { - vdend = vbstart; - } - LOG(LOG_VGA,LOG_WARN)("Blanking wrap to line %d", vblank_skip); - } else if (vbstart==1) { - // blanking is used to cut lines at the start of the screen - vblank_skip = vbend; - LOG(LOG_VGA,LOG_WARN)("Upper %d lines of the screen blanked", vblank_skip); - } else if (vbstart < vdend) { - if(vbend < vdend) { - // the game wants a black bar somewhere on the screen - LOG(LOG_VGA,LOG_WARN)("Unsupported blanking: line %d-%d",vbstart,vbend); - } else { - // blanking is used to cut off some lines from the bottom - vdend = vbstart; + if (vbstart < vtotal) { // There will be no blanking at all otherwise + if (vbend > vtotal) { + // blanking wraps to the start of the screen + vblank_skip = vbend&0x7f; + + // on blanking wrap to 0, the first line is not blanked + // this is used by the S3 BIOS and other S3 drivers in some SVGA modes + if((vbend&0x7f)==1) vblank_skip = 0; + + // it might also cut some lines off the bottom + if(vbstart < vdend) { + vdend = vbstart; + } + LOG(LOG_VGA,LOG_WARN)("Blanking wrap to line %d", vblank_skip); + } else if (vbstart==1) { + // blanking is used to cut lines at the start of the screen + vblank_skip = vbend; + LOG(LOG_VGA,LOG_WARN)("Upper %d lines of the screen blanked", vblank_skip); + } else if (vbstart < vdend) { + if(vbend < vdend) { + // the game wants a black bar somewhere on the screen + LOG(LOG_VGA,LOG_WARN)("Unsupported blanking: line %d-%d",vbstart,vbend); + } else { + // blanking is used to cut off some lines from the bottom + vdend = vbstart; + } } + vdend -= vblank_skip; } - vdend -= vblank_skip; } // Display end vga.draw.delay.vdend = vdend * vga.draw.delay.htotal; -#if C_DEBUG - LOG(LOG_VGA,LOG_NORMAL)("h total %2.5f (%3.2fkHz) blank(%02.5f/%02.5f) retrace(%02.5f/%02.5f)", - vga.draw.delay.htotal,(1.0/vga.draw.delay.htotal), - vga.draw.delay.hblkstart,vga.draw.delay.hblkend, - vga.draw.delay.hrstart,vga.draw.delay.hrend); - LOG(LOG_VGA,LOG_NORMAL)("v total %2.5f (%3.2fHz) blank(%02.5f/%02.5f) retrace(%02.5f/%02.5f)", - vga.draw.delay.vtotal,(1000.0/vga.draw.delay.vtotal), - vga.draw.delay.vblkstart,vga.draw.delay.vblkend, - vga.draw.delay.vrstart,vga.draw.delay.vrend); -#endif - vga.draw.parts_total=VGA_PARTS; /* 6 Horizontal Sync Polarity. Negative if set @@ -1386,6 +1415,7 @@ void VGA_SetupDrawing(Bitu /*val*/) { } doubleheight=true; } + vga.draw.vblank_skip = vblank_skip; if(!(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA))) { //Only check for extra double height in vga modes @@ -1412,21 +1442,44 @@ void VGA_SetupDrawing(Bitu /*val*/) { } // LOG_MSG("ht %d vt %d ratio %f", htotal, vtotal, aspect_ratio ); - if (( width != vga.draw.width) || (height != vga.draw.height) || - (aspect_ratio != vga.draw.aspect_ratio) || - (vga.mode != vga.lastmode)) { - vga.lastmode = vga.mode; + // need to change the vertical timing? + if (fabs(vga.draw.delay.vtotal - 1000.0 / fps) > 0.0001) { + vga.draw.delay.vtotal = 1000.0 / fps; + VGA_KillDrawing(); + PIC_RemoveEvents(VGA_Other_VertInterrupt); PIC_RemoveEvents(VGA_VerticalTimer); PIC_RemoveEvents(VGA_PanningLatch); PIC_RemoveEvents(VGA_DisplayStartLatch); - PIC_RemoveEvents(VGA_DrawPart); - PIC_RemoveEvents(VGA_DrawSingleLine); + VGA_VerticalTimer(0); + } + +#if C_DEBUG + LOG(LOG_VGA,LOG_NORMAL)("h total %2.5f (%3.2fkHz) blank(%02.5f/%02.5f) retrace(%02.5f/%02.5f)", + vga.draw.delay.htotal,(1.0/vga.draw.delay.htotal), + vga.draw.delay.hblkstart,vga.draw.delay.hblkend, + vga.draw.delay.hrstart,vga.draw.delay.hrend); + LOG(LOG_VGA,LOG_NORMAL)("v total %2.5f (%3.2fHz) blank(%02.5f/%02.5f) retrace(%02.5f/%02.5f)", + vga.draw.delay.vtotal,(1000.0/vga.draw.delay.vtotal), + vga.draw.delay.vblkstart,vga.draw.delay.vblkend, + vga.draw.delay.vrstart,vga.draw.delay.vrend); +#endif + + // need to resize the output window? + if ((width != vga.draw.width) || + (height != vga.draw.height) || + (vga.draw.doublewidth != doublewidth) || + (vga.draw.doubleheight != doubleheight) || + (fabs(aspect_ratio - vga.draw.aspect_ratio) > 0.0001) || + (vga.draw.bpp != bpp)) { + + VGA_KillDrawing(); + vga.draw.width = width; vga.draw.height = height; vga.draw.doublewidth = doublewidth; vga.draw.doubleheight = doubleheight; vga.draw.aspect_ratio = aspect_ratio; - vga.draw.vblank_skip = vblank_skip; + vga.draw.bpp = bpp; if (doubleheight) vga.draw.lines_scaled=2; else vga.draw.lines_scaled=1; #if C_DEBUG @@ -1434,14 +1487,14 @@ void VGA_SetupDrawing(Bitu /*val*/) { LOG(LOG_VGA,LOG_NORMAL)("%s width, %s height aspect %f", doublewidth ? "double":"normal",doubleheight ? "double":"normal",aspect_ratio); #endif - RENDER_SetSize(width,height,bpp,fps,aspect_ratio,doublewidth,doubleheight); - vga.draw.delay.framestart = PIC_FullIndex(); - PIC_AddEvent( VGA_VerticalTimer , (float)vga.draw.delay.vtotal ); - vga.draw.lines_done = 0; + RENDER_SetSize(width,height,bpp,(float)fps,aspect_ratio,doublewidth,doubleheight); } } void VGA_KillDrawing(void) { PIC_RemoveEvents(VGA_DrawPart); PIC_RemoveEvents(VGA_DrawSingleLine); + vga.draw.parts_left = 0; + vga.draw.lines_done = ~0; + RENDER_EndUpdate(true); } diff --git a/src/hardware/vga_other.cpp b/src/hardware/vga_other.cpp index 80143d4..710b6c0 100644 --- a/src/hardware/vga_other.cpp +++ b/src/hardware/vga_other.cpp @@ -49,8 +49,10 @@ static void write_crtc_data_other(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { case 0x02: //Horizontal sync position vga.other.hsyncp=(Bit8u)val; break; - case 0x03: //Horizontal and vertical sync width - vga.other.syncw=(Bit8u)val; + case 0x03: //Horizontal sync width + if (machine==MCH_TANDY) vga.other.vsyncw=(Bit8u)(val >> 4); + else vga.other.vsyncw = 16; // The MC6845 has a fixed v-sync width of 16 lines + vga.other.hsyncw=(Bit8u)(val & 0xf); break; case 0x04: //Vertical total if (vga.other.vtotal ^ val) VGA_StartResize(); @@ -116,7 +118,9 @@ static Bitu read_crtc_data_other(Bitu /*port*/,Bitu /*iolen*/) { case 0x02: //Horizontal sync position return vga.other.hsyncp; case 0x03: //Horizontal and vertical sync width - return vga.other.syncw; + if (machine==MCH_TANDY) + return vga.other.hsyncw | (vga.other.vsyncw << 4); + else return vga.other.hsyncw; case 0x04: //Vertical total return vga.other.vtotal; case 0x05: //Vertical display adjust @@ -152,6 +156,7 @@ static Bitu read_crtc_data_other(Bitu /*port*/,Bitu /*iolen*/) { static double hue_offset = 0.0; static Bit8u cga16_val = 0; static void update_cga16_color(void); +static Bit8u herc_pal = 0; static void cga16_color_select(Bit8u val) { cga16_val = val; @@ -278,17 +283,21 @@ static void TANDY_FindMode(void) { } } +void VGA_SetModeNow(VGAModes mode); + static void PCJr_FindMode(void) { if (vga.tandy.mode_control & 0x2) { if (vga.tandy.mode_control & 0x10) { /* bit4 of mode control 1 signals 16 colour graphics mode */ - VGA_SetMode(M_TANDY16); + if (vga.mode==M_TANDY4) VGA_SetModeNow(M_TANDY16); // TODO lowres mode only + else VGA_SetMode(M_TANDY16); } else if (vga.tandy.gfx_control & 0x08) { /* bit3 of mode control 2 signals 2 colour graphics mode */ VGA_SetMode(M_TANDY2); } else { /* otherwise some 4-colour graphics mode */ - VGA_SetMode(M_TANDY4); + if (vga.mode==M_TANDY16) VGA_SetModeNow(M_TANDY4); + else VGA_SetMode(M_TANDY4); } write_color_select(vga.tandy.color_select); } else { @@ -318,6 +327,7 @@ static void write_tandy_reg(Bit8u val) { vga.tandy.mode_control=val; VGA_SetBlinking(val & 0x20); PCJr_FindMode(); + vga.attr.disabled = (val&0x8)? 0: 1; } else { LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); } @@ -359,6 +369,7 @@ static void write_cga(Bitu port,Bitu val,Bitu /*iolen*/) { switch (port) { case 0x3d8: vga.tandy.mode_control=(Bit8u)val; + vga.attr.disabled = (val&0x8)? 0: 1; if (vga.tandy.mode_control & 0x2) { if (vga.tandy.mode_control & 0x10) { if (!(val & 0x4) && machine==MCH_CGA) { @@ -446,6 +457,30 @@ static void write_pcjr(Bitu port,Bitu val,Bitu /*iolen*/) { } } +static void CycleHercPal(bool pressed) { + if (!pressed) return; + if (++herc_pal>2) herc_pal=0; + Herc_Palette(); + VGA_DAC_CombineColor(1,7); +} + +void Herc_Palette(void) { + switch (herc_pal) { + case 0: // White + VGA_DAC_SetEntry(0x7,0x2a,0x2a,0x2a); + VGA_DAC_SetEntry(0xf,0x3f,0x3f,0x3f); + break; + case 1: // Amber + VGA_DAC_SetEntry(0x7,0x34,0x20,0x00); + VGA_DAC_SetEntry(0xf,0x3f,0x34,0x00); + break; + case 2: // Green + VGA_DAC_SetEntry(0x7,0x00,0x26,0x00); + VGA_DAC_SetEntry(0xf,0x00,0x3f,0x00); + break; + } +} + static void write_hercules(Bitu port,Bitu val,Bitu /*iolen*/) { switch (port) { case 0x3b8: { @@ -522,7 +557,7 @@ Bitu read_herc_status(Bitu /*port*/,Bitu /*iolen*/) { void VGA_SetupOther(void) { Bitu i; memset( &vga.tandy, 0, sizeof( vga.tandy )); - vga.attr.enabled = true; + vga.attr.disabled = 0; vga.config.bytes_skip=0; //Initialize values common for most machines, can be overwritten @@ -541,6 +576,7 @@ void VGA_SetupOther(void) { extern Bit8u int10_font_14[256 * 14]; for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_14[i*14],14); vga.draw.font_tables[0]=vga.draw.font_tables[1]=vga.draw.font; + MAPPER_AddHandler(CycleHercPal,MK_f11,0,"hercpal","Herc Pal"); } if (machine==MCH_CGA) { IO_RegisterWriteHandler(0x3d8,write_cga,IO_MB); diff --git a/src/hardware/vga_s3.cpp b/src/hardware/vga_s3.cpp index c656a4d..3d42878 100644 --- a/src/hardware/vga_s3.cpp +++ b/src/hardware/vga_s3.cpp @@ -355,7 +355,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { switch (reg) { case 0x24: /* attribute controller index (read only) */ case 0x26: - return (vga.attr.enabled?0x20:0x00) | (vga.attr.index&0x1f); + return ((vga.attr.disabled & 1)?0x00:0x20) | (vga.attr.index & 0x1f); case 0x2d: /* Extended Chip ID (high byte of PCI device ID) */ return 0x88; case 0x2e: /* New Chip ID (low byte of PCI device ID) */ diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 33a6604..edd400a 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -47,6 +47,8 @@ void write_p3c5(Bitu /*port*/,Bitu val,Bitu iolen) { } else { seq(clocking_mode)=val; } + if (val & 0x20) vga.attr.disabled |= 0x2; + else vga.attr.disabled &= ~0x2; } /* TODO Figure this out :) 0 If set character clocks are 8 dots wide, else 9. diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 4190b8a..a61bfe5 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -826,13 +826,6 @@ void BIOS_ZeroExtendedSize(bool in) { if(other_memsystems < 0) other_memsystems=0; } -#define RAM_REFRESH_DELAY 16.7f - -static void RAMRefresh_Event(Bitu /*val*/) { - PIC_ActivateIRQ(5); - PIC_AddEvent(RAMRefresh_Event,RAM_REFRESH_DELAY); -} - void BIOS_SetupKeyboard(void); void BIOS_SetupDisks(void); @@ -1085,8 +1078,6 @@ public: size_extended=IO_Read(0x71); IO_Write(0x70,0x31); size_extended|=(IO_Read(0x71) << 8); - - if (machine==MCH_PCJR) PIC_AddEvent(RAMRefresh_Event,RAM_REFRESH_DELAY); } ~BIOS(){ /* abort DAC playing */ diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index f4ae47d..baa8dcf 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -124,8 +124,9 @@ bool getSwapRequest(void) { void swapInNextDisk(bool pressed) { if (!pressed) return; - /* Hack/feature: rescan all disks as well */ DriveManager::CycleAllDisks(); + /* Hack/feature: rescan all disks as well */ + LOG_MSG("Diskcaching reset for normal mounted drives."); for(Bitu i=0;iEmptyCache(); } diff --git a/src/ints/bios_keyboard.cpp b/src/ints/bios_keyboard.cpp index 8ad3655..272e69c 100644 --- a/src/ints/bios_keyboard.cpp +++ b/src/ints/bios_keyboard.cpp @@ -246,7 +246,7 @@ static Bitu IRQ1_Handler(void) { flags2&=~(0x40+0x20);//remove numlock/capslock pressed (hack for sdl only reporting states) #endif if (DOS_LayoutKey(scancode,flags1,flags2,flags3)) return CBRET_NONE; -LOG_MSG("key input %d %d %d %d",scancode,flags1,flags2,flags3); +//LOG_MSG("key input %d %d %d %d",scancode,flags1,flags2,flags3); switch (scancode) { /* First the hard ones */ case 0xfa: /* ack. Do nothing for now */ diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 018e994..b5b3abe 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -419,18 +419,24 @@ graphics_chars: LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); reg_al=0x12; break; - case 0x36: /* VGA Refresh control */ + case 0x36: { /* VGA Refresh control */ if (!IS_VGA_ARCH) break; if ((svgaCard==SVGA_S3Trio) && (reg_al>1)) { reg_al=0; break; } - /* - Call disables/enables the vga from outputting video, - don't support it, but fake a success return - */ - reg_al=0x12; + IO_Write(0x3c4,0x1); + Bit8u clocking = IO_Read(0x3c5); + + if (reg_al==0) clocking &= ~0x20; + else clocking |= 0x20; + + IO_Write(0x3c4,0x1); + IO_Write(0x3c5,clocking); + + reg_al=0x12; // success break; + } default: LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); if (machine!=MCH_EGA) reg_al=0; diff --git a/src/ints/int10_char.cpp b/src/ints/int10_char.cpp index a3f7764..672c0bf 100644 --- a/src/ints/int10_char.cpp +++ b/src/ints/int10_char.cpp @@ -236,6 +236,13 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit EGA16_CopyRow(cul,clr,start,start+nlines,base);break; case M_VGA: VGA_CopyRow(cul,clr,start,start+nlines,base);break; + case M_LIN4: + if ((machine==MCH_VGA) && (svgaCard==SVGA_TsengET4K) && + (CurMode->swidth<=800)) { + // the ET4000 BIOS supports text output in 800x600 SVGA + EGA16_CopyRow(cul,clr,start,start+nlines,base);break; + } + // fall-through default: LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type); } @@ -262,6 +269,12 @@ filling: EGA16_FillRow(cul,clr,start,base,attr);break; case M_VGA: VGA_FillRow(cul,clr,start,base,attr);break; + case M_LIN4: + if ((machine==MCH_VGA) && (svgaCard==SVGA_TsengET4K) && + (CurMode->swidth<=800)) { + EGA16_FillRow(cul,clr,start,base,attr);break; + } + // fall-through default: LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type); } diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index b8eec1b..54fdacc 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -475,7 +475,7 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) { //Vertical displayed IO_WriteW(crtc_base,0x06 | (CurMode->vdispend) << 8); //Vertical sync position - IO_WriteW(crtc_base,0x07 | (CurMode->vdispend+1) << 8); + IO_WriteW(crtc_base,0x07 | (CurMode->vdispend + ((CurMode->vtotal - CurMode->vdispend)/2)-1) << 8); //Maximum scanline Bit8u scanline,crtpage; scanline=8; @@ -504,7 +504,7 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) { //Setup the special registers for each machine type Bit8u mode_control_list[0xa+1]={ 0x2c,0x28,0x2d,0x29, //0-3 - 0x2a,0x2e,0x16,0x29, //4-7 + 0x2a,0x2e,0x1e,0x29, //4-7 0x2a,0x2b,0x3b //8-a }; Bit8u mode_control_list_pcjr[0xa+1]={ @@ -517,6 +517,7 @@ bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) { case MCH_HERC: IO_WriteB(0x3b8,0x28); // TEXT mode and blinking characters + Herc_Palette(); VGA_DAC_CombineColor(0,0); VGA_DAC_CombineColor(1,7); diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index 63e0868..0adc4da 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -94,6 +94,13 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { real_writeb(0xb800,off,old); } break; + case M_LIN4: + if ((machine!=MCH_VGA) || (svgaCard!=SVGA_TsengET4K) || + (CurMode->swidth>800)) { + // the ET4000 BIOS supports text output in 800x600 SVGA (Gateway 2) + // putpixel warining? + break; + } case M_EGA: { /* Set the correct bitmask for the pixel position */ diff --git a/src/libs/gui_tk/gui_tk.cpp b/src/libs/gui_tk/gui_tk.cpp index 0ba88eb..03b64a9 100644 --- a/src/libs/gui_tk/gui_tk.cpp +++ b/src/libs/gui_tk/gui_tk.cpp @@ -1704,4 +1704,4 @@ int main(int argc, char *argv[]) } #endif -#endif \ No newline at end of file +#endif diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index f87b874..6c38336 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -213,7 +213,7 @@ bool Property::CheckValue(Value const& in, bool warn){ return true; } } - if(warn) LOG_MSG("\"%s\" is not a valid value for variable: %s.\nIt might now be reset it to default value: %s",in.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); + if(warn) LOG_MSG("\"%s\" is not a valid value for variable: %s.\nIt might now be reset to the default value: %s",in.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); return false; } diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index d49f10a..7d9eecb 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,4 +1,4 @@ -#define VERSION "0.73" +#define VERSION "0.74" /* Define to 1 to enable internal debugger, requires libcurses */ #define C_DEBUG 0 diff --git a/src/platform/wii/FreeTypeGX.cpp b/src/platform/wii/FreeTypeGX.cpp index ca9740e..3cd8616 100644 --- a/src/platform/wii/FreeTypeGX.cpp +++ b/src/platform/wii/FreeTypeGX.cpp @@ -38,6 +38,13 @@ void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize) fontSystem[i] = NULL; } +void DeinitFreeType() +{ + ClearFontData(); + FT_Done_FreeType(ftLibrary); + ftLibrary = NULL; +} + void ChangeFontSize(FT_UInt pixelSize) { FT_Set_Pixel_Sizes(ftFace, 0, pixelSize); @@ -65,25 +72,70 @@ void ClearFontData() wchar_t* charToWideChar(const char* strChar) { - wchar_t *strWChar; - strWChar = new wchar_t[strlen(strChar) + 1]; + wchar_t *strWChar = new(std::nothrow) wchar_t[strlen(strChar) + 1]; + if(!strWChar) + return NULL; - char *tempSrc = (char *)strChar; + int bt = mbstowcs(strWChar, strChar, strlen(strChar)); + if (bt > 0) + { + strWChar[bt] = (wchar_t)'\0'; + return strWChar; + } wchar_t *tempDest = strWChar; - while((*tempDest++ = *tempSrc++)); + while ((*tempDest++ = *strChar++)); return strWChar; } +static uint32_t* convertBufferToRGBA8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { + uint32_t bufferSize = (bufferWidth * bufferHeight) << 2; + uint32_t* dataBufferRGBA8 = (uint32_t *)memalign(32, bufferSize); + memset(dataBufferRGBA8, 0x00, bufferSize); + + uint8_t *src = (uint8_t *)rgbaBuffer; + uint8_t *dst = (uint8_t *)dataBufferRGBA8; + + for(uint32_t block = 0; block < bufferHeight; block += 4) { + for(uint32_t i = 0; i < bufferWidth; i += 4) { + for (uint32_t c = 0; c < 4; c++) { + uint32_t blockWid = (((block + c) * bufferWidth)+i)<<2 ; + + *dst++ = src[blockWid+ 3]; // ar = 0 + *dst++ = src[blockWid+ 0]; + *dst++ = src[blockWid+ 7]; // ar = 1 + *dst++ = src[blockWid+ 4]; + *dst++ = src[blockWid+ 11]; // ar = 2 + *dst++ = src[blockWid+ 8]; + *dst++ = src[blockWid+ 15]; // ar = 3 + *dst++ = src[blockWid+ 12]; + } + for (uint32_t c = 0; c < 4; c++) { + uint32_t blockWid = (((block + c) * bufferWidth)+i)<<2 ; + + *dst++ = src[blockWid+ 1]; // gb = 0 + *dst++ = src[blockWid+ 2]; + *dst++ = src[blockWid+ 5]; // gb = 1 + *dst++ = src[blockWid+ 6]; + *dst++ = src[blockWid+ 9]; // gb = 2 + *dst++ = src[blockWid+ 10]; + *dst++ = src[blockWid+ 13]; // gb = 3 + *dst++ = src[blockWid+ 14]; + } + } + } + DCFlushRange(dataBufferRGBA8, bufferSize); + + return dataBufferRGBA8; +} + /** * Default constructor for the FreeTypeGX class. * - * @param textureFormat Optional format (GX_TF_*) of the texture as defined by the libogc gx.h header file. If not specified default value is GX_TF_RGBA8. * @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1. */ -FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat, uint8_t vertexIndex) +FreeTypeGX::FreeTypeGX(FT_UInt pixelSize, uint8_t vertexIndex) { - this->textureFormat = textureFormat; this->setVertexFormat(vertexIndex); this->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE); this->ftPointSize = pixelSize; @@ -195,67 +247,15 @@ void FreeTypeGX::unloadFont() this->fontData.clear(); } -/** - * Adjusts the texture data buffer to necessary width for a given texture format. - * - * This routine determines adjusts the given texture width into the required width to hold the necessary texture data for proper alignment. - * - * @param textureWidth The initial guess for the texture width. - * @param textureFormat The texture format to which the data is to be converted. - * @return The correctly adjusted texture width. - */ -uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat) +uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth) { - uint16_t alignment; - - switch(textureFormat) - { - case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */ - case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */ - case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */ - alignment = 8; - break; - - case GX_TF_IA8: /* 4x4 Tiles - 8-bit Intensity, 8-bit Alpha */ - case GX_TF_RGB565: /* 4x4 Tiles - RGB565 Format */ - case GX_TF_RGB5A3: /* 4x4 Tiles - RGB5A3 Format */ - case GX_TF_RGBA8: /* 4x4 Tiles - RGBA8 Dual Cache Line Format */ - default: - alignment = 4; - break; - } + uint16_t alignment = 4; return textureWidth % alignment == 0 ? textureWidth : alignment + textureWidth - (textureWidth % alignment); } -/** - * Adjusts the texture data buffer to necessary height for a given texture format. - * - * This routine determines adjusts the given texture height into the required height to hold the necessary texture data for proper alignment. - * - * @param textureHeight The initial guess for the texture height. - * @param textureFormat The texture format to which the data is to be converted. - * @return The correctly adjusted texture height. - */ -uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat) +uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight) { - uint16_t alignment; - - switch(textureFormat) - { - case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */ - alignment = 8; - break; - - case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */ - case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */ - case GX_TF_IA8: /* 4x4 Tiles - 8-bit Intensity, 8-bit Alpha */ - case GX_TF_RGB565: /* 4x4 Tiles - RGB565 Format */ - case GX_TF_RGB5A3: /* 4x4 Tiles - RGB5A3 Format */ - case GX_TF_RGBA8: /* 4x4 Tiles - RGBA8 Dual Cache Line Format */ - default: - alignment = 4; - break; - } + uint16_t alignment = 4; return textureHeight % alignment == 0 ? textureHeight : alignment + textureHeight - (textureHeight % alignment); } @@ -280,8 +280,8 @@ ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) if(ftSlot->format == FT_GLYPH_FORMAT_BITMAP) { FT_Bitmap *glyphBitmap = &ftSlot->bitmap; - textureWidth = adjustTextureWidth(glyphBitmap->width, this->textureFormat); - textureHeight = adjustTextureHeight(glyphBitmap->rows, this->textureFormat); + textureWidth = adjustTextureWidth(glyphBitmap->width); + textureHeight = adjustTextureHeight(glyphBitmap->rows); this->fontData[charCode] = (ftgxCharData){ ftSlot->bitmap_left, @@ -346,32 +346,7 @@ void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) glyphData[imagePosY * charData->textureWidth + imagePosX] = 0x00000000 | (pixel << 24) | (pixel << 16) | (pixel << 8) | pixel; } } - - switch(this->textureFormat) - { - case GX_TF_I4: - charData->glyphDataTexture = Metaphrasis::convertBufferToI4(glyphData, charData->textureWidth, charData->textureHeight); - break; - case GX_TF_I8: - charData->glyphDataTexture = Metaphrasis::convertBufferToI8(glyphData, charData->textureWidth, charData->textureHeight); - break; - case GX_TF_IA4: - charData->glyphDataTexture = Metaphrasis::convertBufferToIA4(glyphData, charData->textureWidth, charData->textureHeight); - break; - case GX_TF_IA8: - charData->glyphDataTexture = Metaphrasis::convertBufferToIA8(glyphData, charData->textureWidth, charData->textureHeight); - break; - case GX_TF_RGB565: - charData->glyphDataTexture = Metaphrasis::convertBufferToRGB565(glyphData, charData->textureWidth, charData->textureHeight); - break; - case GX_TF_RGB5A3: - charData->glyphDataTexture = Metaphrasis::convertBufferToRGB5A3(glyphData, charData->textureWidth, charData->textureHeight); - break; - case GX_TF_RGBA8: - default: - charData->glyphDataTexture = Metaphrasis::convertBufferToRGBA8(glyphData, charData->textureWidth, charData->textureHeight); - break; - } + charData->glyphDataTexture = convertBufferToRGBA8(glyphData, charData->textureWidth, charData->textureHeight); free(glyphData); } @@ -485,7 +460,7 @@ uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color x_pos += pairDelta.x >> 6; } - GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, this->textureFormat, GX_CLAMP, GX_CLAMP, GX_FALSE); + GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE); this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX + x_offset, y - glyphData->renderOffsetY + y_offset, color); x_pos += glyphData->glyphAdvanceX; @@ -538,10 +513,10 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text) std::map::iterator thisEnd =this->fontData.end(); - for (uint32_t i = 0; i < strLength; ++i){ - + for (uint32_t i = 0; i < strLength; ++i) + { ftgxCharData* glyphData = NULL; - if( this->fontData.find(text[i]) != thisEnd) + if(this->fontData.find(text[i]) != thisEnd) { glyphData = &this->fontData[text[i]]; } @@ -554,7 +529,7 @@ uint16_t FreeTypeGX::getWidth(wchar_t *text) { if(this->ftKerningEnabled && (i > 0)) { - FT_Get_Kerning( ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta ); + FT_Get_Kerning(ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); strWidth += pairDelta.x >> 6; } strWidth += glyphData->glyphAdvanceX; diff --git a/src/platform/wii/FreeTypeGX.h b/src/platform/wii/FreeTypeGX.h index 2b428fc..b5910f1 100644 --- a/src/platform/wii/FreeTypeGX.h +++ b/src/platform/wii/FreeTypeGX.h @@ -2,7 +2,7 @@ * FreeTypeGX is a wrapper class for libFreeType which renders a compiled * FreeType parsable font into a GX texture for Wii homebrew development. * Copyright (C) 2008 Armin Tamzarian - * Modified by Tantric, 2009 + * Modified by Tantric, 2009-2010 * * This file is part of FreeTypeGX. * @@ -20,134 +20,6 @@ * along with FreeTypeGX. If not, see . */ -/** \mainpage FreeTypeGX - * - * \section sec_intro Introduction - * - * FreeTypeGX is a wrapper class for libFreeType which renders a compiled FreeType parsable font into a GX texture for Wii homebrew development. - *
- * FreeTypeGX is written in C++ and makes use of a selectable pre-buffered or buffer-on-demand methodology to allow fast and efficient printing of text to the EFB. - *

- * This library was developed in-full by Armin Tamzarian with the support of developers in \#wiibrew on EFnet. - * - * \section sec_installation_source Installation (Source Code) - * - * -# Ensure that you have the libFreeType Wii library installed in your development environment with the library added to your Makefile where appropriate. - * -# Ensure that you have the Metaphrasis library installed in your development environment with the library added to your Makefile where appropriate. - * -# Extract the FreeTypeGX archive. - * -# Copy the contents of the src directory into your project's development path. - * -# Include the FreeTypeGX header file in your code using syntax such as the following: - * \code - * #include "FreeTypeGX.h" - * \endcode - * - * \section sec_installation_library Installation (Library) - * - * -# Ensure that you have the libFreeType Wii library installed in your development environment with the library added to your Makefile where appropriate. - * -# Ensure that you have the Metaphrasis library installed in your development environment with the library added to your Makefile where appropriate. - * -# Extract the FreeTypeGX archive. - * -# Copy the contents of the lib directory into your devKitPro/libogc directory. - * -# Include the FreeTypeGX header file in your code using syntax such as the following: - * \code - * #include "FreeTypeGX.h" - * \endcode - * - * \section sec_freetypegx_prerequisites FreeTypeGX Prerequisites - * - * Before you begin using FreeTypeGX in your project you must ensure that the desired font in compiled into your project. For this example I will assume you are building your project with a Makefile using devKitPro evironment and are attempting to include a font whose filename is rursus_compact_mono.ttf. - * - * -# Copy the font into a directory which will be processed by the project's Makefile. If you are unsure about where you should place your font just copy the it into your project's source directory. - * \n\n - * -# Modify the Makefile to convert the font into an object file: - * \code - * %.ttf.o : %.ttf - * @echo $(notdir $<) - * $(bin2o) - * \endcode - * \n - * -# Include the font object's generated header file in your source code: - * \code - * #include "rursus_compact_mono_ttf.h" - * \endcode - * This header file defines the two variables that you will need for use within your project: - * \code - * extern const u8 rursus_compact_mono_ttf[]; A pointer to the font buffer within the compiled project. - * extern const u32 rursus_compact_mono_ttf_size; The size of the font's buffer in bytes. - * \endcode - * - * \section sec_freetypegx_usage FreeTypeGX Usage - * - * -# Within the file you included the FreeTypeGX.h header create an instance object of the FreeTypeGX class: - * \code - * FreeTypeGX *freeTypeGX = new FreeTypeGX(); - * \endcode - * Alternately you can specify a texture format to which you would like to render the font characters. Note that the default value for this parameter is GX_TF_RGBA8. - * \code - * FreeTypeGX *freeTypeGX = new FreeTypeGX(GX_TF_RGB565); - * \endcode - * Furthermore, you can also specify a vertex format index to avoid conflicts with concurrent libraries or other systems. Note that the default value for this parameter is GX_VTXFMT1. - * \code - * FreeTypeGX *freeTypeGX = new FreeTypeGX(GX_TF_RGB565, GX_VTXFMT1); - * \endcode - * \n - * Currently supported textures are: - * \li GX_TF_I4 - * \li GX_TF_I8 - * \li GX_TF_IA4 - * \li GX_TF_IA8 - * \li GX_TF_RGB565 - * \li GX_TF_RGB5A3 - * \li GX_TF_RGBA8 - * - * \n - * -# Using the allocated FreeTypeGX instance object call the loadFont function to load the font from the compiled buffer and specify the desired point size. Note that this function can be called multiple times to load a new: - * \code - * freeTypeGX->loadFont(rursus_compact_mono_ttf, rursus_compact_mono_ttf_size, 64); - * \endcode - * Alternately you can specify a flag which will load and cache all available font glyphs immidiately. Note that on large font sets enabling this feature could take a significant amount of time. - * \code - * freeTypeGX->loadFont(rursus_compact_mono_ttf, rursus_compact_mono_ttf_size, 64, true); - * \endcode - * \n - * -# If necessary you can enable compatibility modes with concurrent libraries or systems. For more information on this feature see the documentation for setCompatibilityMode: - * \code - * freeTypeGX->setCompatibilityMode(FTGX_COMPATIBILITY_GRRLIB); - * \endcode - * -# Using the allocated FreeTypeGX instance object call the drawText function to print a string at the specified screen X and Y coordinates to the current EFB: - * \code - * freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!")); - * \endcode - * Alternately you can specify a GXColor object you would like to apply to the printed characters: - * \code - * freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"), - * (GXColor){0xff, 0xee, 0xaa, 0xff}); - * \endcode - * Furthermore you can also specify a group of styling parameters which will modify the positioning or style of the text: - * \code - * freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"), - * (GXColor){0xff, 0xee, 0xaa, 0xff}, - * FTGX_JUSTIFY_CENTER | FTGX_ALIGN_BOTTOM | FTGX_STYLE_UNDERLINE); - * \endcode - * \n - * Currently style parameters are: - * \li FTGX_JUSTIFY_LEFT - * \li FTGX_JUSTIFY_CENTER - * \li FTGX_JUSTIFY_RIGHT - * \li FTGX_ALIGN_TOP - * \li FTGX_ALIGN_MIDDLE - * \li FTGX_ALIGN_BOTTOM - * \li FTGX_STYLE_UNDERLINE - * \li FTGX_STYLE_STRIKE - * - * \section sec_license License - * - * FreeTypeGX is distributed under the GNU Lesser General Public License. - * - * \section sec_contact Contact - * - * If you have any suggestions, questions, or comments regarding this library feel free to e-mail me at tamzarian1989 [at] gmail [dawt] com. - */ - #ifndef FREETYPEGX_H_ #define FREETYPEGX_H_ @@ -155,7 +27,6 @@ #include #include FT_FREETYPE_H #include FT_BITMAP_H -#include "Metaphrasis.h" #include #include @@ -236,6 +107,7 @@ typedef struct ftgxDataOffset_ ftgxDataOffset; const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */ void InitFreeType(uint8_t* fontBuffer, FT_Long bufferSize); +void DeinitFreeType(); void ChangeFontSize(FT_UInt pixelSize); wchar_t* charToWideChar(const char* p); void ClearFontData(); @@ -254,14 +126,12 @@ class FreeTypeGX { private: FT_UInt ftPointSize; /**< Requested size of the rendered font. */ bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ - - uint8_t textureFormat; /**< Defined texture format of the target EFB. */ uint8_t vertexIndex; /**< Vertex format descriptor index. */ uint32_t compatibilityMode; /**< Compatibility mode for default tev operations and vertex descriptors. */ std::map fontData; /**< Map which holds the glyph data structures for the corresponding characters. */ - static uint16_t adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat); - static uint16_t adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat); + static uint16_t adjustTextureWidth(uint16_t textureWidth); + static uint16_t adjustTextureHeight(uint16_t textureHeight); static int16_t getStyleOffsetWidth(uint16_t width, uint16_t format); static int16_t getStyleOffsetHeight(ftgxDataOffset *offset, uint16_t format); @@ -278,7 +148,7 @@ class FreeTypeGX { void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color); public: - FreeTypeGX(FT_UInt pixelSize, uint8_t textureFormat = GX_TF_RGBA8, uint8_t vertexIndex = GX_VTXFMT1); + FreeTypeGX(FT_UInt pixelSize, uint8_t vertexIndex = GX_VTXFMT1); ~FreeTypeGX(); void setVertexFormat(uint8_t vertexIndex); diff --git a/src/platform/wii/Metaphrasis.cpp b/src/platform/wii/Metaphrasis.cpp deleted file mode 100644 index 0ead124..0000000 --- a/src/platform/wii/Metaphrasis.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Metaphrasis is a static conversion class for transforming RGBA image - * buffers into verious GX texture formats for Wii homebrew development. - * Copyright (C) 2008 Armin Tamzarian - * - * This file is part of Metaphrasis. - * - * Metaphrasis is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Metaphrasis is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Metaphrasis. If not, see . - */ - -#include "Metaphrasis.h" - -/** - * Default constructor for the Metaphrasis class. - */ - -Metaphrasis::Metaphrasis() { -} - -/** - * Default destructor for the Metaphrasis class. - */ - -Metaphrasis::~Metaphrasis() { -} - -/** - * Convert the specified RGBA data buffer into the I4 texture format - * - * This routine converts the RGBA data buffer into the I4 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToI4(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = bufferWidth * bufferHeight >> 1; - uint32_t* dataBufferI4 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferI4, 0x00, bufferSize); - - uint32_t *src = (uint32_t *)rgbaBuffer; - uint8_t *dst = (uint8_t *)dataBufferI4; - - for(uint32_t y = 0; y < bufferHeight; y += 8) { - for(uint32_t x = 0; x < bufferWidth; x += 8) { - for(uint32_t rows = 0; rows < 8; rows++) { - *dst++ = (src[((y + rows) * bufferWidth) + (x + 0)] & 0xf0) | ((src[((y + rows) * bufferWidth) + (x + 1)] & 0xf0) >> 4); - *dst++ = (src[((y + rows) * bufferWidth) + (x + 2)] & 0xf0) | ((src[((y + rows) * bufferWidth) + (x + 3)] & 0xf0) >> 4); - *dst++ = (src[((y + rows) * bufferWidth) + (x + 4)] & 0xf0) | ((src[((y + rows) * bufferWidth) + (x + 5)] & 0xf0) >> 4); - *dst++ = (src[((y + rows) * bufferWidth) + (x + 5)] & 0xf0) | ((src[((y + rows) * bufferWidth) + (x + 7)] & 0xf0) >> 4); - } - } - } - DCFlushRange(dataBufferI4, bufferSize); - - return dataBufferI4; -} - -/** - * Convert the specified RGBA data buffer into the I8 texture format - * - * This routine converts the RGBA data buffer into the I8 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToI8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = bufferWidth * bufferHeight; - uint32_t* dataBufferI8 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferI8, 0x00, bufferSize); - - uint32_t *src = (uint32_t *)rgbaBuffer; - uint8_t *dst = (uint8_t *)dataBufferI8; - - for(uint32_t rows = 0; rows < 4; rows++) { - for(uint32_t y = 0; y < bufferHeight; y += 4) { - uint32_t bufWid = ((y + rows) * bufferWidth); - for(uint32_t x = 0; x < bufferWidth; x += 8) { - - *dst++ = src[bufWid + (x + 0)] & 0xff; - *dst++ = src[bufWid + (x + 1)] & 0xff; - *dst++ = src[bufWid + (x + 2)] & 0xff; - *dst++ = src[bufWid + (x + 3)] & 0xff; - *dst++ = src[bufWid + (x + 4)] & 0xff; - *dst++ = src[bufWid + (x + 5)] & 0xff; - *dst++ = src[bufWid + (x + 6)] & 0xff; - *dst++ = src[bufWid + (x + 7)] & 0xff; - } - } - } - DCFlushRange(dataBufferI8, bufferSize); - - return dataBufferI8; -} - -/** - * Downsample the specified RGBA value data buffer to an IA4 value. - * - * This routine downsamples the given RGBA data value into the IA4 texture data format. - * - * @param rgba A 32-bit RGBA value to convert to the IA4 format. - * @return The IA4 value of the given RGBA value. - */ - -uint8_t Metaphrasis::convertRGBAToIA4(uint32_t rgba) { - uint8_t i = (rgba >> 8) & 0xf0; - uint8_t a = (rgba ) & 0xff; - return i | (a >> 4); -} - -/** - * Convert the specified RGBA data buffer into the IA4 texture format - * - * This routine converts the RGBA data buffer into the IA4 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToIA4(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = bufferWidth * bufferHeight; - uint32_t* dataBufferIA4 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferIA4, 0x00, bufferSize); - - uint32_t *src = (uint32_t *)rgbaBuffer; - uint8_t *dst = (uint8_t *)dataBufferIA4; - - for(uint32_t y = 0; y < bufferHeight; y += 4) { - for(uint32_t x = 0; x < bufferWidth; x += 8) { - for(uint32_t rows = 0; rows < 4; rows++) { - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 0)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 1)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 2)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 3)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 4)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 5)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 6)]); - *dst++ = Metaphrasis::convertRGBAToIA4(src[((y + rows) * bufferWidth) + (x + 7)]); - } - } - } - DCFlushRange(dataBufferIA4, bufferSize); - - return dataBufferIA4; -} - -/** - * Downsample the specified RGBA value data buffer to an IA8 value. - * - * This routine downsamples the given RGBA data value into the IA8 texture data format. - * - * @param rgba A 32-bit RGBA value to convert to the IA8 format. - * @return The IA8 value of the given RGBA value. - */ - -uint16_t Metaphrasis::convertRGBAToIA8(uint32_t rgba) { - return (((rgba >> 8) & 0xff) << 8) | ((rgba ) & 0xff); -} - -/** - * Convert the specified RGBA data buffer into the IA8 texture format - * - * This routine converts the RGBA data buffer into the IA8 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToIA8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = (bufferWidth * bufferHeight) << 1; - uint32_t* dataBufferIA8 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferIA8, 0x00, bufferSize); - - uint32_t *src = (uint32_t *)rgbaBuffer; - uint16_t *dst = (uint16_t *)dataBufferIA8; - - for(uint32_t rows = 0; rows < 4; ++rows) { - for(uint32_t y = 0; y < bufferHeight; y += 4) { - uint32_t bufWid = ((y + rows) * bufferWidth); - for(uint32_t x = 0; x < bufferWidth; x += 4) { - - *dst++ = Metaphrasis::convertRGBAToIA8(src[bufWid + (x + 0)]); - *dst++ = Metaphrasis::convertRGBAToIA8(src[bufWid + (x + 1)]); - *dst++ = Metaphrasis::convertRGBAToIA8(src[bufWid + (x + 2)]); - *dst++ = Metaphrasis::convertRGBAToIA8(src[bufWid + (x + 3)]); - } - } - } - DCFlushRange(dataBufferIA8, bufferSize); - - return dataBufferIA8; -} - -/** - * Convert the specified RGBA data buffer into the RGBA8 texture format - * - * This routine converts the RGBA data buffer into the RGBA8 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToRGBA8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = (bufferWidth * bufferHeight) << 2; - uint32_t* dataBufferRGBA8 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferRGBA8, 0x00, bufferSize); - - uint8_t *src = (uint8_t *)rgbaBuffer; - uint8_t *dst = (uint8_t *)dataBufferRGBA8; - - for(uint32_t block = 0; block < bufferHeight; block += 4) { - for(uint32_t i = 0; i < bufferWidth; i += 4) { - for (uint32_t c = 0; c < 4; c++) { - uint32_t blockWid = (((block + c) * bufferWidth)+i)<<2 ; - - *dst++ = src[blockWid+ 3]; // ar = 0 - *dst++ = src[blockWid+ 0]; - *dst++ = src[blockWid+ 7]; // ar = 1 - *dst++ = src[blockWid+ 4]; - *dst++ = src[blockWid+ 11]; // ar = 2 - *dst++ = src[blockWid+ 8]; - *dst++ = src[blockWid+ 15]; // ar = 3 - *dst++ = src[blockWid+ 12]; - } - for (uint32_t c = 0; c < 4; c++) { - uint32_t blockWid = (((block + c) * bufferWidth)+i)<<2 ; - - *dst++ = src[blockWid+ 1]; // gb = 0 - *dst++ = src[blockWid+ 2]; - *dst++ = src[blockWid+ 5]; // gb = 1 - *dst++ = src[blockWid+ 6]; - *dst++ = src[blockWid+ 9]; // gb = 2 - *dst++ = src[blockWid+ 10]; - *dst++ = src[blockWid+ 13]; // gb = 3 - *dst++ = src[blockWid+ 14]; - } - } - } - DCFlushRange(dataBufferRGBA8, bufferSize); - - return dataBufferRGBA8; -} - -/** - * Downsample the specified RGBA value data buffer to an RGB565 value. - * - * This routine downsamples the given RGBA data value into the RGB565 texture data format. - * Attribution for this routine is given fully to NoNameNo of GRRLIB Wii library. - * - * @param rgba A 32-bit RGBA value to convert to the RGB565 format. - * @return The RGB565 value of the given RGBA value. - */ - -uint16_t Metaphrasis::convertRGBAToRGB565(uint32_t rgba) { - uint32_t rA = ((rgba >> 24) & 0xff); - uint32_t gA = ((rgba >> 16) & 0xff); - uint32_t bA = ((rgba >> 8) & 0xff); - - uint32_t r = ((rA<<5) - rA) / 255; - uint32_t g = ((gA<<6) - gA) / 255; - uint32_t b = ((bA<<5) - bA) / 255; - - return (((r << 6) | g ) << 5 ) | b; -} - -/** - * Convert the specified RGBA data buffer into the RGB565 texture format - * - * This routine converts the RGBA data buffer into the RGB565 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToRGB565(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = (bufferWidth * bufferHeight) << 1; - uint32_t* dataBufferRGB565 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferRGB565, 0x00, bufferSize); - - uint32_t *src = (uint32_t *)rgbaBuffer; - uint16_t *dst = (uint16_t *)dataBufferRGB565; - - for(uint32_t rows = 0; rows < 4; rows++) { - for(uint32_t y = 0; y < bufferHeight; y += 4) { - uint32_t bufWid = ((y + rows) * bufferWidth); - for(uint32_t x = 0; x < bufferWidth; x += 4) { - *dst++ = Metaphrasis::convertRGBAToRGB565(src[bufWid + (x + 0)]); - *dst++ = Metaphrasis::convertRGBAToRGB565(src[bufWid + (x + 1)]); - *dst++ = Metaphrasis::convertRGBAToRGB565(src[bufWid + (x + 2)]); - *dst++ = Metaphrasis::convertRGBAToRGB565(src[bufWid + (x + 3)]); - } - } - } - DCFlushRange(dataBufferRGB565, bufferSize); - - return dataBufferRGB565; -} - -/** - * Downsample the specified RGBA value data buffer to an RGB5A3 value. - * - * This routine downsamples the given RGBA data value into the RGB5A3 texture data format. - * Attribution for this routine is given fully to WiiGator via the TehSkeen forum. - * - * @param rgba A 32-bit RGBA value to convert to the RGB5A3 format. - * @return The RGB5A3 value of the given RGBA value. - */ - -uint16_t Metaphrasis::convertRGBAToRGB5A3(uint32_t rgba) { - uint32_t r = (rgba >> 24) & 0xff; - uint32_t g = (rgba >> 16) & 0xff; - uint32_t b = (rgba >> 8) & 0xff; - uint32_t a = (rgba ) & 0xff; - uint16_t color; - - // No predictive misses, faster shifting - if (a > 0xe0) { - r >>= 3; - g >>= 3; - b >>= 3; - - color = (r << 10) | (g << 5) | b; - color |= 0x8000; - return color; - } - - r >>= 4; - g >>= 4; - b >>= 4; - a >>= 5; - color = (a << 12) | (r << 8) | (g << 4) | b; - return color; -} - -/** - * Convert the specified RGBA data buffer into the RGB5A3 texture format - * - * This routine converts the RGBA data buffer into the RGB5A3 texture format and returns a pointer to the converted buffer. - * - * @param rgbaBuffer Buffer containing the temporarily rendered RGBA data. - * @param bufferWidth Pixel width of the data buffer. - * @param bufferHeight Pixel height of the data buffer. - * @return A pointer to the allocated buffer. - */ - -uint32_t* Metaphrasis::convertBufferToRGB5A3(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight) { - uint32_t bufferSize = (bufferWidth * bufferHeight) << 1; - uint32_t* dataBufferRGB5A3 = (uint32_t *)memalign(32, bufferSize); - memset(dataBufferRGB5A3, 0x00, bufferSize); - - uint32_t *src = (uint32_t *)rgbaBuffer; - uint16_t *dst = (uint16_t *)dataBufferRGB5A3; - - for(uint32_t rows = 0; rows < 4; rows++) { - for(uint32_t y = 0; y < bufferHeight; y += 4) { - uint32_t bufWid = ((y + rows) * bufferWidth); - for(uint32_t x = 0; x < bufferWidth; x += 4) { - *dst++ = Metaphrasis::convertRGBAToRGB5A3(src[bufWid + (x + 0)]); - *dst++ = Metaphrasis::convertRGBAToRGB5A3(src[bufWid + (x + 1)]); - *dst++ = Metaphrasis::convertRGBAToRGB5A3(src[bufWid + (x + 2)]); - *dst++ = Metaphrasis::convertRGBAToRGB5A3(src[bufWid + (x + 3)]); - } - } - } - DCFlushRange(dataBufferRGB5A3, bufferSize); - - return dataBufferRGB5A3; -} diff --git a/src/platform/wii/Metaphrasis.h b/src/platform/wii/Metaphrasis.h deleted file mode 100644 index 4ca8871..0000000 --- a/src/platform/wii/Metaphrasis.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Metaphrasis is a static conversion class for transforming RGBA image - * buffers into verious GX texture formats for Wii homebrew development. - * Copyright (C) 2008 Armin Tamzarian - * - * This file is part of Metaphrasis. - * - * Metaphrasis is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Metaphrasis is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Metaphrasis. If not, see . - */ - -/** \mainpage Metaphrasis - * - * \section sec_intro Introduction - * - * Metaphrasis is a static conversion class for transforming RGBA image buffers into verious GX texture formats for Wii homebrew development. - *
- * Metaphrasis is written in C++ and makes use of a community standard and newly developed algorithms for conversion of 32-bit RGBA data buffers into various GX texture formats common to both the Gamecube and Wii platforms. - *

- * This library was developed in-full by Armin Tamzarian with the support of developers in \#wiibrew on EFnet, Chaosteil of libwiisprite, and DrTwox of GRRLIB. - * - * \section sec_installation_source Installation (Source Code) - * - * -# Extract the Metaphrasis archive. - * -# Copy the contents of the src directory into your project's development path. - * -# Include the Metaphrasis header file in your code using syntax such as the following: - * \code - * #include "Metaphrasis.h" - * \endcode - * - * \section sec_installation_library Installation (Library) - * - * -# Extract the Metaphrasis archive. - * -# Copy the contents of the lib directory into your devKitPro/libogc directory. - * -# Include the Metaphrasis header file in your code using syntax such as the following: - * \code - * #include "Metaphrasis.h" - * \endcode - * - * \section sec_usage Usage - * - * -# Create a buffer full of 32-bit RGBA values noting both the pixel height and width of the buffer. - * -# Call one of the many conversion routines from within your code. (Note: All methods within the Metaphrasis class are static and thus no class instance need be allocated) - * \code - * uint32_t* rgba8Buffer = Metaphrasis::convertBufferToRGBA8(rgbaBuffer, bufferWidth, bufferHeight); - * \endcode - * -# Free your temporary RGBA value buffer if you no longer need said values. - * - * Currently supported conversion routines are as follows: - * \li convertBufferToI4 - * \li convertBufferToI8 - * \li convertBufferToIA4 - * \li convertBufferToIA8 - * \li convertBufferToRGBA8 - * \li convertBufferToRGB565 - * \li convertBufferToRGB5A3 - * - * \section sec_license License - * - * Metaphrasis is distributed under the GNU Lesser General Public License. - * - * \section sec_contact Contact - * - * If you have any suggestions, questions, or comments regarding this library feel free to e-mail me at tamzarian1989 [at] gmail [dawt] com. - */ - -#ifndef METAPHRASIS_H_ -#define METAPHRASIS_H_ - -#include -#include -#include -#include - -/*! \class Metaphrasis - * \brief A static conversion class for transforming RGBA image buffers into verious GX texture formats for - * Wii homebrew development. - * \author Armin Tamzarian - * \version 0.1.0 - * - * Metaphrasis is a static conversion class for transforming RGBA image buffers into verious GX texture formats for - * Wii homebrew development. Metaphrasis is written in C++ and makes use of a community standard and newly developed - * algorithms for conversion of 32-bit RGBA data buffers into various GX texture formats common to both the Gamecube - * and Wii platforms. - */ -class Metaphrasis { - public: - Metaphrasis(); - virtual ~Metaphrasis(); - - static uint32_t* convertBufferToI4(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - static uint32_t* convertBufferToI8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - static uint32_t* convertBufferToIA4(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - static uint32_t* convertBufferToIA8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - static uint32_t* convertBufferToRGBA8(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - static uint32_t* convertBufferToRGB565(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - static uint32_t* convertBufferToRGB5A3(uint32_t* rgbaBuffer, uint16_t bufferWidth, uint16_t bufferHeight); - - static uint8_t convertRGBAToIA4(uint32_t rgba); - static uint16_t convertRGBAToIA8(uint32_t rgba); - static uint16_t convertRGBAToRGB565(uint32_t rgba); - static uint16_t convertRGBAToRGB5A3(uint32_t rgba); - -}; - -#endif /*METAPHRASIS_H_*/ diff --git a/src/platform/wii/config.h b/src/platform/wii/config.h index 1c617c5..182e946 100644 --- a/src/platform/wii/config.h +++ b/src/platform/wii/config.h @@ -1,4 +1,4 @@ -#define VERSION "0.73" +#define VERSION "0.74" /* Define to 1 to enable internal debugger, requires libcurses */ #define C_DEBUG 0 diff --git a/src/platform/wii/filelist.h b/src/platform/wii/filelist.h index 2e51274..d62edde 100644 --- a/src/platform/wii/filelist.h +++ b/src/platform/wii/filelist.h @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii Home Menu - * Tantric 2009 + * Tantric 2009-2010 * * filelist.h * diff --git a/src/platform/wii/input.cpp b/src/platform/wii/input.cpp index ee014ef..15355ff 100644 --- a/src/platform/wii/input.cpp +++ b/src/platform/wii/input.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii Home Menu - * Tantric 2009 + * Tantric 2009-2010 * * input.cpp * diff --git a/src/platform/wii/input.h b/src/platform/wii/input.h index 6aab52f..594b41c 100644 --- a/src/platform/wii/input.h +++ b/src/platform/wii/input.h @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii Home Menu - * Tantric 2009 + * Tantric 2009-2010 * * input.h * diff --git a/src/platform/wii/libwiigui/gui.h b/src/platform/wii/libwiigui/gui.h index 8aa8b70..53412ff 100644 --- a/src/platform/wii/libwiigui/gui.h +++ b/src/platform/wii/libwiigui/gui.h @@ -51,8 +51,9 @@ extern FreeTypeGX *fontSystem[]; -#define SCROLL_INITIAL_DELAY 20 -#define SCROLL_LOOP_DELAY 3 +#define SCROLL_DELAY_INITIAL 200000 +#define SCROLL_DELAY_LOOP 30000 +#define SCROLL_DELAY_DECREASE 300 #define MAX_KEYBOARD_DISPLAY 32 typedef void (*UpdateCallback)(void * e); @@ -190,11 +191,19 @@ class GuiTrigger //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately //!\param gcbtns GameCube controller trigger button(s) void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns); - //!Get X/Y value from Wii Joystick (classic, nunchuk) input - //!\param right Controller stick (left = 0, right = 1) + //!Get X or Y value from Wii Joystick (classic, nunchuk) input + //!\param stick Controller stick (left = 0, right = 1) //!\param axis Controller stick axis (x-axis = 0, y-axis = 1) //!\return Stick value - s8 WPAD_Stick(u8 right, int axis); + s8 WPAD_Stick(u8 stick, int axis); + //!Get X value from Wii Joystick (classic, nunchuk) input + //!\param stick Controller stick (left = 0, right = 1) + //!\return Stick value + s8 WPAD_StickX(u8 stick); + //!Get Y value from Wii Joystick (classic, nunchuk) input + //!\param stick Controller stick (left = 0, right = 1) + //!\return Stick value + s8 WPAD_StickY(u8 stick); //!Move menu selection left (via pad/joystick). Allows scroll delay and button overriding //!\return true if selection should be moved left, false otherwise bool Left(); @@ -208,11 +217,11 @@ class GuiTrigger //!\return true if selection should be moved down, false otherwise bool Down(); - u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS) - s32 chan; //!< Trigger controller channel (0-3, -1 for all) - WPADData * wpad; //!< Wii controller trigger WPADData wpaddata; //!< Wii controller trigger data PADData pad; //!< GameCube controller trigger data + WPADData * wpad; //!< Wii controller trigger + s32 chan; //!< Trigger controller channel (0-3, -1 for all) + u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS) }; extern GuiTrigger userInput[4]; @@ -307,12 +316,28 @@ class GuiElement //!Considers alpha, alphaDyn, and the parent element's GetAlpha() value //!\return alpha int GetAlpha(); - //!Sets the element's scale + //!Sets the element's x and y scale //!\param s scale (1 is 100%) void SetScale(float s); + //!Sets the element's x scale + //!\param s scale (1 is 100%) + void SetScaleX(float s); + //!Sets the element's y scale + //!\param s scale (1 is 100%) + void SetScaleY(float s); + //!Sets the element's x and y scale, using the provided max width/height + //!\param w Maximum width + //!\param h Maximum height + void SetScale(int w, int h); //!Gets the element's current scale //!Considers scale, scaleDyn, and the parent element's GetScale() value float GetScale(); + //!Gets the element's current x scale + //!Considers scale, scaleDyn, and the parent element's GetScale() value + float GetScaleX(); + //!Gets the element's current y scale + //!Considers scale, scaleDyn, and the parent element's GetScale() value + float GetScaleY(); //!Set a new GuiTrigger for the element //!\param t Pointer to GuiTrigger void SetTrigger(GuiTrigger * t); @@ -378,13 +403,19 @@ class GuiElement //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) virtual void SetAlignment(int hor, int vert); + //!Called when the language has changed, to obtain new text values for all text elements + virtual void ResetText(); //!Called constantly to allow the element to respond to the current input data //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD virtual void Update(GuiTrigger * t); //!Called constantly to redraw the element virtual void Draw(); + //!Called constantly to redraw the element's tooltip + virtual void DrawTooltip(); protected: - bool visible; //!< Visibility of the element. If false, Draw() is skipped + GuiTrigger * trigger[3]; //!< GuiTriggers (input actions) that this element responds to + UpdateCallback updateCB; //!< Callback function to call when this element is updated + GuiElement * parentElement; //!< Parent element int focus; //!< Element focus (-1 = focus disabled, 0 = not focused, 1 = focused) int width; //!< Element width int height; //!< Element height @@ -397,10 +428,10 @@ class GuiElement int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects) int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects) int alpha; //!< Element alpha value (0-255) - f32 scale; //!< Element scale (1 = 100%) int alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects) + f32 xscale; //!< Element X scale (1 = 100%) + f32 yscale; //!< Element Y scale (1 = 100%) f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects) - bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event int effects; //!< Currently enabled effect(s). 0 when no effects are enabled int effectAmount; //!< Effect amount. Used by different effects for different purposes int effectTarget; //!< Effect target amount. Used by different effects for different purposes @@ -414,9 +445,8 @@ class GuiElement bool selectable; //!< Whether or not this element selectable (can change to SELECTED state) bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state) bool holdable; //!< Whether or not this element is holdable (can change to HELD state) - GuiTrigger * trigger[2]; //!< GuiTriggers (input actions) that this element responds to - GuiElement * parentElement; //!< Parent element - UpdateCallback updateCB; //!< Callback function to call when this element is updated + bool visible; //!< Visibility of the element. If false, Draw() is skipped + bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event }; //!Allows GuiElements to be grouped together into a "window" @@ -443,6 +473,10 @@ class GuiWindow : public GuiElement void Remove(GuiElement* e); //!Removes all GuiElements void RemoveAll(); + //!Looks for the specified GuiElement + //!\param e The GuiElement to find + //!\return true if found, false otherwise + bool Find(GuiElement* e); //!Returns the GuiElement at the specified index //!\param index The index of the element //!\return A pointer to the element at the index, NULL on error (eg: out of bounds) @@ -480,8 +514,12 @@ class GuiWindow : public GuiElement //!Moves the selected element to the element above or below //!\param d Direction to move (-1 = up, 1 = down) void MoveSelectionVert(int d); + //!Resets the text for all contained elements + void ResetText(); //!Draws all the elements in this GuiWindow void Draw(); + //!Draws all of the tooltips in this GuiWindow + void DrawTooltip(); //!Updates the window and all elements contains within //!Allows the GuiWindow and all elements to respond to the input data specified //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD @@ -497,7 +535,9 @@ class GuiImageData //!Constructor //!Converts the image data to RGBA8 - expects PNG format //!\param i Image data - GuiImageData(const u8 * i); + //!\param w Max image width (0 = not set) + //!\param h Max image height (0 = not set) + GuiImageData(const u8 * i, int w=0, int h=0); //!Destructor ~GuiImageData(); //!Gets a pointer to the image data @@ -600,6 +640,11 @@ class GuiText : public GuiElement //!Sets the text of the GuiText element //!\param t Text void SetText(const char * t); + //!Sets the text of the GuiText element + //!\param t UTF-8 Text + void SetWText(wchar_t * t); + //!Gets the translated text length of the GuiText element + int GetLength(); //!Sets up preset values to be used by GuiText(t) //!Useful when printing multiple text elements, all with the same attributes set //!\param sz Font size @@ -615,6 +660,8 @@ class GuiText : public GuiElement //!Sets the maximum width of the drawn texture image //!\param w Maximum width void SetMaxWidth(int w); + //!Gets the width of the text when rendered + int GetTextWidth(); //!Enables/disables text scrolling //!\param s Scrolling on/off void SetScroll(int s); @@ -632,21 +679,50 @@ class GuiText : public GuiElement //!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE) //!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE) void SetAlignment(int hor, int vert); + //!Updates the text to the selected language + void ResetText(); //!Constantly called to draw the text void Draw(); protected: - char * origText; //!< Original text data - wchar_t* text; //!< Unicode text value + GXColor color; //!< Font color + wchar_t* text; //!< Translated Unicode text value + wchar_t *textDyn[20]; //!< Text value, if max width, scrolling, or wrapping enabled + int textDynNum; //!< Number of text lines + char * origText; //!< Original text data (English) int size; //!< Font size int maxWidth; //!< Maximum width of the generated text object (for text wrapping) - bool wrap; //!< Wrapping toggle - wchar_t* textDyn; //!< Wrapped text value int textScroll; //!< Scrolling toggle int textScrollPos; //!< Current starting index of text string for scrolling int textScrollInitialDelay; //!< Delay to wait before starting to scroll int textScrollDelay; //!< Scrolling speed u16 style; //!< FreeTypeGX style attributes - GXColor color; //!< Font color + bool wrap; //!< Wrapping toggle +}; + +//!Display, manage, and manipulate tooltips in the GUI +class GuiTooltip : public GuiElement +{ + public: + //!Constructor + //!\param t Text + GuiTooltip(const char *t); + //!Destructor + ~GuiTooltip(); + //!Gets the element's current scale + float GetScale(); + //!Sets the text of the GuiTooltip element + //!\param t Text + void SetText(const char * t); + //!Constantly called to draw the GuiTooltip + void DrawTooltip(); + + time_t time1, time2; //!< Tooltip times + + protected: + GuiImage leftImage; //!< Tooltip left image + GuiImage tileImage; //!< Tooltip tile image + GuiImage rightImage; //!< Tooltip right image + GuiText *text; //!< Tooltip text }; //!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional) @@ -656,7 +732,7 @@ class GuiButton : public GuiElement //!Constructor //!\param w Width //!\param h Height - GuiButton(int w, int h); + GuiButton(int w = 0, int h = 0); //!Destructor ~GuiButton(); //!Sets the button's image @@ -708,8 +784,15 @@ class GuiButton : public GuiElement //!Sets the sound to play on click //!\param s Pointer to GuiSound object void SetSoundClick(GuiSound * s); + //!Sets the tooltip for the button + //!\param t Tooltip + void SetTooltip(GuiTooltip * t); //!Constantly called to draw the GuiButton void Draw(); + //!Constantly called to draw the GuiButton's tooltip + void DrawTooltip(); + //!Resets the text for all contained elements + void ResetText(); //!Constantly called to allow the GuiButton to respond to updated input data //!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD void Update(GuiTrigger * t); @@ -729,10 +812,11 @@ class GuiButton : public GuiElement GuiSound * soundOver; //!< Sound to play for STATE_SELECTED GuiSound * soundHold; //!< Sound to play for STATE_HELD GuiSound * soundClick; //!< Sound to play for STATE_CLICKED + GuiTooltip * tooltip; //!< Tooltip to display on over }; typedef struct _keytype { - char ch, chShift; + unsigned char ch, chShift; } Key; //!On-screen keyboard @@ -745,11 +829,18 @@ class GuiKeyboard : public GuiWindow char kbtextstr[256]; protected: u32 kbtextmaxlen; - Key keys[4][11]; int shift; int caps; GuiText * kbText; GuiImage * keyTextboxImg; + GuiText * keyEscText; + GuiImage * keyEscImg; + GuiImage * keyEscOverImg; + GuiButton * keyEsc; + GuiText * keyEnterText; + GuiImage * keyEnterImg; + GuiImage * keyEnterOverImg; + GuiButton * keyEnter; GuiText * keyCapsText; GuiImage * keyCapsImg; GuiImage * keyCapsOverImg; @@ -765,10 +856,10 @@ class GuiKeyboard : public GuiWindow GuiImage * keySpaceImg; GuiImage * keySpaceOverImg; GuiButton * keySpace; - GuiButton * keyBtn[4][11]; - GuiImage * keyImg[4][11]; - GuiImage * keyImgOver[4][11]; - GuiText * keyTxt[4][11]; + GuiButton * keyBtn[5][12]; + GuiImage * keyImg[5][12]; + GuiImage * keyImgOver[5][12]; + GuiText * keyTxt[5][12]; GuiImageData * keyTextbox; GuiImageData * key; GuiImageData * keyOver; @@ -779,6 +870,8 @@ class GuiKeyboard : public GuiWindow GuiSound * keySoundOver; GuiSound * keySoundClick; GuiTrigger * trigA; + GuiTrigger * trigB; + Key keys[5][12]; // two chars = less space than one pointer }; #endif diff --git a/src/platform/wii/libwiigui/gui_button.cpp b/src/platform/wii/libwiigui/gui_button.cpp index 93890ce..4feb0ce 100644 --- a/src/platform/wii/libwiigui/gui_button.cpp +++ b/src/platform/wii/libwiigui/gui_button.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_button.cpp * @@ -37,6 +37,7 @@ GuiButton::GuiButton(int w, int h) soundOver = NULL; soundHold = NULL; soundClick = NULL; + tooltip = NULL; selectable = true; holdable = false; clickable = true; @@ -121,6 +122,12 @@ void GuiButton::SetSoundClick(GuiSound * snd) { soundClick = snd; } +void GuiButton::SetTooltip(GuiTooltip* t) +{ + tooltip = t; + if(t) + tooltip->SetParent(this); +} /** * Draw the button on screen @@ -130,28 +137,72 @@ void GuiButton::Draw() if(!this->IsVisible()) return; - // draw image - if((state == STATE_SELECTED || state == STATE_HELD) && imageOver) - imageOver->Draw(); - else if(image) - image->Draw(); - // draw icon - if((state == STATE_SELECTED || state == STATE_HELD) && iconOver) - iconOver->Draw(); - else if(icon) - icon->Draw(); - // draw text - for(int i=0; i<3; i++) + if(state == STATE_SELECTED || state == STATE_HELD) { - if((state == STATE_SELECTED || state == STATE_HELD) && labelOver[i]) - labelOver[i]->Draw(); - else if(label[i]) - label[i]->Draw(); + if(imageOver) + imageOver->Draw(); + else if(image) // draw image + image->Draw(); + + if(iconOver) + iconOver->Draw(); + else if(icon) // draw icon + icon->Draw(); + + // draw text + if(labelOver[0]) + labelOver[0]->Draw(); + else if(label[0]) + label[0]->Draw(); + + if(labelOver[1]) + labelOver[1]->Draw(); + else if(label[1]) + label[1]->Draw(); + + if(labelOver[2]) + labelOver[2]->Draw(); + else if(label[2]) + label[2]->Draw(); + } + else + { + if(image) // draw image + image->Draw(); + if(icon) // draw icon + icon->Draw(); + + // draw text + if(label[0]) + label[0]->Draw(); + if(label[1]) + label[1]->Draw(); + if(label[2]) + label[2]->Draw(); } this->UpdateEffects(); } +void GuiButton::DrawTooltip() +{ + if(tooltip) + tooltip->DrawTooltip(); +} + +void GuiButton::ResetText() +{ + for(int i=0; i<3; i++) + { + if(label[i]) + label[i]->ResetText(); + if(labelOver[i]) + labelOver[i]->ResetText(); + } + if(tooltip) + tooltip->ResetText(); +} + void GuiButton::Update(GuiTrigger * t) { if(state == STATE_CLICKED || state == STATE_DISABLED || !t) @@ -204,7 +255,7 @@ void GuiButton::Update(GuiTrigger * t) if(this->IsClickable()) { s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig; - for(int i=0; i<2; i++) + for(int i=0; i<3; i++) { if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan)) { @@ -254,7 +305,7 @@ void GuiButton::Update(GuiTrigger * t) bool held = false; s32 wm_btns, wm_btns_h, wm_btns_trig, cc_btns, cc_btns_h, cc_btns_trig; - for(int i=0; i<2; i++) + for(int i=0; i<3; i++) { if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan)) { diff --git a/src/platform/wii/libwiigui/gui_element.cpp b/src/platform/wii/libwiigui/gui_element.cpp index 5bb2c88..40ee90e 100644 --- a/src/platform/wii/libwiigui/gui_element.cpp +++ b/src/platform/wii/libwiigui/gui_element.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_element.cpp * @@ -24,11 +24,13 @@ GuiElement::GuiElement() width = 0; height = 0; alpha = 255; - scale = 1; + xscale = 1; + yscale = 1; state = STATE_DEFAULT; stateChan = -1; trigger[0] = NULL; trigger[1] = NULL; + trigger[2] = NULL; parentElement = NULL; rumble = true; selectable = false; @@ -91,12 +93,13 @@ int GuiElement::GetLeft() x = pLeft; break; case ALIGN_CENTRE: - x = pLeft + (pWidth/2) - (width/2); + x = pLeft + pWidth/2.0 - (width*xscale)/2.0; break; case ALIGN_RIGHT: - x = pLeft + pWidth - width; + x = pLeft + pWidth - width*xscale; break; } + x += (width*(xscale - 1))/2.0; // correct offset for scaled images return x + xoffset; } @@ -121,12 +124,13 @@ int GuiElement::GetTop() y = pTop; break; case ALIGN_MIDDLE: - y = pTop + (pHeight/2) - (height/2); + y = pTop + pHeight/2.0 - (height*yscale)/2.0; break; case ALIGN_BOTTOM: - y = pTop + pHeight - height; + y = pTop + pHeight - height*yscale; break; } + y += (height*(yscale - 1))/2.0; // correct offset for scaled images return y + yoffset; } @@ -204,27 +208,49 @@ void GuiElement::SetAlpha(int a) int GuiElement::GetAlpha() { - int a; + int a = alpha; if(alphaDyn >= 0) a = alphaDyn; - else - a = alpha; if(parentElement) - a *= parentElement->GetAlpha()/255.0; + a *= float(parentElement->GetAlpha())/255.0f; return a; } void GuiElement::SetScale(float s) { - scale = s; + xscale = s; + yscale = s; +} + +void GuiElement::SetScaleX(float s) +{ + xscale = s; +} + +void GuiElement::SetScaleY(float s) +{ + yscale = s; +} + +void GuiElement::SetScale(int mw, int mh) +{ + xscale = 1.0f; + if(width > mw || height > mh) + { + if(width/(height*1.0) > mw/(mh*1.0)) + xscale = mw/(width*1.0); + else + xscale = mh/(height*1.0); + } + yscale = xscale; } float GuiElement::GetScale() { - float s = scale * scaleDyn; + float s = xscale * scaleDyn; if(parentElement) s *= parentElement->GetScale(); @@ -232,6 +258,26 @@ float GuiElement::GetScale() return s; } +float GuiElement::GetScaleX() +{ + float s = xscale * scaleDyn; + + if(parentElement) + s *= parentElement->GetScale(); + + return s; +} + +float GuiElement::GetScaleY() +{ + float s = yscale * scaleDyn; + + if(parentElement) + s *= parentElement->GetScaleY(); + + return s; +} + int GuiElement::GetState() { return state; @@ -314,7 +360,9 @@ void GuiElement::SetTrigger(GuiTrigger * t) trigger[0] = t; else if(!trigger[1]) trigger[1] = t; - else // both were assigned, so we'll just overwrite the first one + else if(!trigger[2]) + trigger[2] = t; + else // all were assigned, so we'll just overwrite the first one trigger[0] = t; } @@ -352,13 +400,12 @@ void GuiElement::SetEffect(int eff, int amount, int target) else if(eff & EFFECT_SLIDE_RIGHT) xoffsetDyn = screenwidth; } - if(eff & EFFECT_FADE && amount > 0) + if(eff & EFFECT_FADE) { - alphaDyn = 0; - } - else if(eff & EFFECT_FADE && amount < 0) - { - alphaDyn = alpha; + if(amount > 0) + alphaDyn = 0; + else if(amount < 0) + alphaDyn = alpha; } effects |= eff; @@ -474,12 +521,13 @@ void GuiElement::UpdateEffects() } if(effects & EFFECT_SCALE) { - scaleDyn += effectAmount/100.0; + scaleDyn += f32(effectAmount)*0.01f; + f32 effTar100 = f32(effectTarget)*0.01f; - if((effectAmount < 0 && scaleDyn <= effectTarget/100.0) - || (effectAmount > 0 && scaleDyn >= effectTarget/100.0)) + if((effectAmount < 0 && scaleDyn <= effTar100) + || (effectAmount > 0 && scaleDyn >= effTar100)) { - scaleDyn = effectTarget/100.0; + scaleDyn = effTar100; effects = 0; // shut off effect } } @@ -513,17 +561,22 @@ int GuiElement::GetSelected() return -1; } -/** - * Draw an element on screen. - */ +void GuiElement::ResetText() +{ +} + void GuiElement::Draw() { } +void GuiElement::DrawTooltip() +{ +} + bool GuiElement::IsInside(int x, int y) { - if(x > this->GetLeft() && x < (this->GetLeft()+width) - && y > this->GetTop() && y < (this->GetTop()+height)) + if(unsigned(x - this->GetLeft()) < unsigned(width) + && unsigned(y - this->GetTop()) < unsigned(height)) return true; return false; } diff --git a/src/platform/wii/libwiigui/gui_image.cpp b/src/platform/wii/libwiigui/gui_image.cpp index 6f15f48..adc2828 100644 --- a/src/platform/wii/libwiigui/gui_image.cpp +++ b/src/platform/wii/libwiigui/gui_image.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_image.cpp * @@ -53,7 +53,7 @@ GuiImage::GuiImage(u8 * img, int w, int h) GuiImage::GuiImage(int w, int h, GXColor c) { - image = (u8 *)memalign (32, w * h * 4); + image = (u8 *)memalign (32, w * h << 2); width = w; height = h; imageangle = 0; @@ -66,14 +66,14 @@ GuiImage::GuiImage(int w, int h, GXColor c) int x, y; - for(y=0; y < h; y++) + for(y=0; y < h; ++y) { - for(x=0; x < w; x++) + for(x=0; x < w; ++x) { this->SetPixel(x, y, c); } } - int len = w*h*4; + int len = w * h << 2; if(len%32) len += (32-len%32); DCFlushRange(image, len); } @@ -157,21 +157,24 @@ void GuiImage::SetStripe(int s) void GuiImage::ColorStripe(int shift) { - int x, y; GXColor color; + int x, y=0; int alt = 0; + + int thisHeight = this->GetHeight(); + int thisWidth = this->GetWidth(); - for(y=0; y < this->GetHeight(); y++) + for(; y < thisHeight; ++y) { if(y % 3 == 0) alt ^= 1; - for(x=0; x < this->GetWidth(); x++) + if(alt) { - color = GetPixel(x, y); - - if(alt) + for(x=0; x < thisWidth; ++x) { + color = GetPixel(x, y); + if(color.r < 255-shift) color.r += shift; else @@ -186,9 +189,15 @@ void GuiImage::ColorStripe(int shift) color.b = 255; color.a = 255; + SetPixel(x, y, color); } - else + } + else + { + for(x=0; x < thisWidth; ++x) { + color = GetPixel(x, y); + if(color.r > shift) color.r -= shift; else @@ -203,8 +212,8 @@ void GuiImage::ColorStripe(int shift) color.b = 0; color.a = 255; + SetPixel(x, y, color); } - SetPixel(x, y, color); } } } @@ -217,26 +226,30 @@ void GuiImage::Draw() if(!image || !this->IsVisible() || tile == 0) return; - float currScale = this->GetScale(); + float currScaleX = this->GetScaleX(); + float currScaleY = this->GetScaleY(); int currLeft = this->GetLeft(); + int thisTop = this->GetTop(); if(tile > 0) { - for(int i=0; iGetTop(), width, height, image, imageangle, currScale, currScale, this->GetAlpha()); + int alpha = this->GetAlpha(); + for(int i=0; iGetTop(), width, height, image, imageangle, currScale, currScale, this->GetAlpha()); + Menu_DrawImg(currLeft, thisTop, width, height, image, imageangle, currScaleX, currScaleY, this->GetAlpha()); } if(stripe > 0) - for(int y=0; y < this->GetHeight(); y+=6) - Menu_DrawRectangle(currLeft,this->GetTop()+y,this->GetWidth(),3,(GXColor){0, 0, 0, stripe},1); - + { + int thisHeight = this->GetHeight(); + int thisWidth = this->GetWidth(); + for(int y=0; y < thisHeight; y+=6) + Menu_DrawRectangle(currLeft,thisTop+y,thisWidth,3,(GXColor){0, 0, 0, stripe},1); + } this->UpdateEffects(); } diff --git a/src/platform/wii/libwiigui/gui_imagedata.cpp b/src/platform/wii/libwiigui/gui_imagedata.cpp index fb6ef21..3fc22e9 100644 --- a/src/platform/wii/libwiigui/gui_imagedata.cpp +++ b/src/platform/wii/libwiigui/gui_imagedata.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_imagedata.cpp * @@ -13,47 +13,14 @@ /** * Constructor for the GuiImageData class. */ -GuiImageData::GuiImageData(const u8 * i) +GuiImageData::GuiImageData(const u8 * i, int maxw, int maxh) { data = NULL; width = 0; height = 0; if(i) - { - PNGUPROP imgProp; - IMGCTX ctx = PNGU_SelectImageFromBuffer(i); - - if(!ctx) - return; - - int res = PNGU_GetImageProperties(ctx, &imgProp); - - if(res == PNGU_OK) - { - int len = imgProp.imgWidth * imgProp.imgHeight * 4; - if(len%32) len += (32-len%32); - data = (u8 *)memalign (32, len); - - if(data) - { - res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255); - - if(res == PNGU_OK) - { - width = imgProp.imgWidth; - height = imgProp.imgHeight; - DCFlushRange(data, len); - } - else - { - free(data); - data = NULL; - } - } - } - PNGU_ReleaseImageContext (ctx); - } + data = DecodePNG(i, &width, &height, maxw, maxh); } /** diff --git a/src/platform/wii/libwiigui/gui_keyboard.cpp b/src/platform/wii/libwiigui/gui_keyboard.cpp index 6b30c96..b3d26c8 100644 --- a/src/platform/wii/libwiigui/gui_keyboard.cpp +++ b/src/platform/wii/libwiigui/gui_keyboard.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_keyboard.cpp * @@ -9,21 +9,52 @@ ***************************************************************************/ #include "gui.h" +#include + +using namespace std; static char tmptxt[MAX_KEYBOARD_DISPLAY]; -static char * GetDisplayText(char * t) +static void str_replace(string &str, char *search, const char *replace) { - if(!t) - return NULL; + int searchLen = strlen(search); + int replaceLen = strlen(replace); - int len = strlen(t); + string::size_type pos=0; - if(len < MAX_KEYBOARD_DISPLAY) + while ((pos=str.find(search, pos)) != string::npos) + { + str.erase(pos, searchLen); + str.insert(pos, replace); + pos += replaceLen; + } +} + +static char * GetDisplayText(char * t, int max) +{ + if(!t || t[0] == 0) return t; - strncpy(tmptxt, &t[len-MAX_KEYBOARD_DISPLAY], MAX_KEYBOARD_DISPLAY); - tmptxt[MAX_KEYBOARD_DISPLAY-1] = 0; + string tempStr(t); + char txt[2] = { 0, 0 }; + txt[0] = 13; str_replace(tempStr, txt, ""); + txt[0] = 27; str_replace(tempStr, txt, ""); + txt[0] = 14; str_replace(tempStr, txt, ""); + txt[0] = 15; str_replace(tempStr, txt, ""); + txt[0] = 16; str_replace(tempStr, txt, ""); + txt[0] = 17; str_replace(tempStr, txt, ""); + txt[0] = 18; str_replace(tempStr, txt, ""); + txt[0] = 19; str_replace(tempStr, txt, ""); + txt[0] = 20; str_replace(tempStr, txt, ""); + txt[0] = 21; str_replace(tempStr, txt, ""); + txt[0] = 22; str_replace(tempStr, txt, ""); + txt[0] = 23; str_replace(tempStr, txt, ""); + txt[0] = 24; str_replace(tempStr, txt, ""); + txt[0] = 25; str_replace(tempStr, txt, ""); + + int s = tempStr.length()-MAX_KEYBOARD_DISPLAY; + if(s < 0) s = 0; + snprintf(tmptxt, MAX_KEYBOARD_DISPLAY, "%s", &(tempStr.c_str()[s])); return &tmptxt[0]; } @@ -33,8 +64,8 @@ static char * GetDisplayText(char * t) GuiKeyboard::GuiKeyboard(char * t, u32 max) { - width = 540; - height = 400; + width = 610; + height = 440; shift = 0; caps = 0; selectable = true; @@ -45,8 +76,23 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) kbtextstr[max] = 0; kbtextmaxlen = max; - Key thekeys[4][11] = { + Key thekeys[5][12] = { { + {14,0}, // F1 + {15,0}, // F2 + {16,0}, // F3 + {17,0}, // F4 + {18,0}, // F5 + {19,0}, // F6 + {20,0}, // F7 + {21,0}, // F8 + {22,0}, // F9 + {23,0}, // F10 + {24,0}, // F11 + {25,0}, // F12 + }, + { + {'`','~'}, {'1','!'}, {'2','@'}, {'3','#'}, @@ -57,7 +103,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) {'8','*'}, {'9','('}, {'0',')'}, - {'\0','\0'} + {'-','_'} }, { {'q','Q'}, @@ -70,7 +116,8 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) {'i','I'}, {'o','O'}, {'p','P'}, - {'-','_'} + {'[','{'}, + {']','}'} }, { {'a','A'}, @@ -83,7 +130,8 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) {'k','K'}, {'l','L'}, {';',':'}, - {'\'','"'} + {'\'','"'}, + {'\\','|'} }, { @@ -97,6 +145,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) {',','<'}, {'.','>'}, {'/','?'}, + {'\0','\0'}, {'\0','\0'} } }; @@ -105,12 +154,12 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyTextbox = new GuiImageData(keyboard_textbox_png); keyTextboxImg = new GuiImage(keyTextbox); keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - keyTextboxImg->SetPosition(0, 0); + keyTextboxImg->SetPosition(0, 20); this->Append(keyTextboxImg); - kbText = new GuiText(GetDisplayText(kbtextstr), 22, (GXColor){0, 0, 0, 0xff}); + kbText = new GuiText(GetDisplayText(kbtextstr, max), 22, (GXColor){0, 0, 0, 0xff}); kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - kbText->SetPosition(0, 13); + kbText->SetPosition(0, 33); this->Append(kbText); key = new GuiImageData(keyboard_key_png); @@ -124,6 +173,38 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM); trigA = new GuiTrigger; trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trigB = new GuiTrigger; + trigB->SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + int yoff = 80; + + keyEscImg = new GuiImage(keyMedium); + keyEscOverImg = new GuiImage(keyMediumOver); + keyEscText = new GuiText("Esc", 22, (GXColor){0, 0, 0, 0xff}); + keyEsc = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyEsc->SetImage(keyEscImg); + keyEsc->SetImageOver(keyEscOverImg); + keyEsc->SetLabel(keyEscText); + keyEsc->SetSoundOver(keySoundOver); + keyEsc->SetSoundClick(keySoundClick); + keyEsc->SetTrigger(trigA); + keyEsc->SetPosition(0, yoff); + keyEsc->SetEffectGrow(); + this->Append(keyEsc); + + keyEnterImg = new GuiImage(keyMedium); + keyEnterOverImg = new GuiImage(keyMediumOver); + keyEnterText = new GuiText("Enter", 22, (GXColor){0, 0, 0, 0xff}); + keyEnter = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight()); + keyEnter->SetImage(keyEnterImg); + keyEnter->SetImageOver(keyEnterOverImg); + keyEnter->SetLabel(keyEnterText); + keyEnter->SetSoundOver(keySoundOver); + keyEnter->SetSoundClick(keySoundClick); + keyEnter->SetTrigger(trigA); + keyEnter->SetPosition(12*42+18, 4*42+yoff); + keyEnter->SetEffectGrow(); + this->Append(keyEnter); keyBackImg = new GuiImage(keyMedium); keyBackOverImg = new GuiImage(keyMediumOver); @@ -135,7 +216,8 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyBack->SetSoundOver(keySoundOver); keyBack->SetSoundClick(keySoundClick); keyBack->SetTrigger(trigA); - keyBack->SetPosition(10*42+40, 0*42+80); + keyBack->SetTrigger(trigB); + keyBack->SetPosition(11*42+40, 1*42+yoff); keyBack->SetEffectGrow(); this->Append(keyBack); @@ -149,7 +231,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyCaps->SetSoundOver(keySoundOver); keyCaps->SetSoundClick(keySoundClick); keyCaps->SetTrigger(trigA); - keyCaps->SetPosition(0, 2*42+80); + keyCaps->SetPosition(0, 3*42+yoff); keyCaps->SetEffectGrow(); this->Append(keyCaps); @@ -163,7 +245,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyShift->SetSoundOver(keySoundOver); keyShift->SetSoundClick(keySoundClick); keyShift->SetTrigger(trigA); - keyShift->SetPosition(21, 3*42+80); + keyShift->SetPosition(21, 4*42+yoff); keyShift->SetEffectGrow(); this->Append(keyShift); @@ -175,23 +257,41 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keySpace->SetSoundOver(keySoundOver); keySpace->SetSoundClick(keySoundClick); keySpace->SetTrigger(trigA); - keySpace->SetPosition(0, 4*42+80); + keySpace->SetPosition(0, 5*42+yoff); keySpace->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); keySpace->SetEffectGrow(); this->Append(keySpace); char txt[2] = { 0, 0 }; - for(int i=0; i<4; i++) + for(int i=0; i<5; i++) { - for(int j=0; j<11; j++) + for(int j=0; j<12; j++) { if(keys[i][j].ch != '\0') { txt[0] = keys[i][j].ch; keyImg[i][j] = new GuiImage(key); keyImgOver[i][j] = new GuiImage(keyOver); - keyTxt[i][j] = new GuiText(txt, 22, (GXColor){0, 0, 0, 0xff}); + switch(keys[i][j].ch) + { + case 14: keyTxt[i][j] = new GuiText("F1", 22, (GXColor){0, 0, 0, 0xff}); break; + case 15: keyTxt[i][j] = new GuiText("F2", 22, (GXColor){0, 0, 0, 0xff}); break; + case 16: keyTxt[i][j] = new GuiText("F3", 22, (GXColor){0, 0, 0, 0xff}); break; + case 17: keyTxt[i][j] = new GuiText("F4", 22, (GXColor){0, 0, 0, 0xff}); break; + case 18: keyTxt[i][j] = new GuiText("F5", 22, (GXColor){0, 0, 0, 0xff}); break; + case 19: keyTxt[i][j] = new GuiText("F6", 22, (GXColor){0, 0, 0, 0xff}); break; + case 20: keyTxt[i][j] = new GuiText("F7", 22, (GXColor){0, 0, 0, 0xff}); break; + case 21: keyTxt[i][j] = new GuiText("F8", 22, (GXColor){0, 0, 0, 0xff}); break; + case 22: keyTxt[i][j] = new GuiText("F9", 22, (GXColor){0, 0, 0, 0xff}); break; + case 23: keyTxt[i][j] = new GuiText("F10", 22, (GXColor){0, 0, 0, 0xff}); break; + case 24: keyTxt[i][j] = new GuiText("F11", 22, (GXColor){0, 0, 0, 0xff}); break; + case 25: keyTxt[i][j] = new GuiText("F12", 22, (GXColor){0, 0, 0, 0xff}); break; + + default: + keyTxt[i][j] = new GuiText(txt, 22, (GXColor){0, 0, 0, 0xff}); + break; + } keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); keyTxt[i][j]->SetPosition(0, -10); keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight()); @@ -201,7 +301,16 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyBtn[i][j]->SetSoundClick(keySoundClick); keyBtn[i][j]->SetTrigger(trigA); keyBtn[i][j]->SetLabel(keyTxt[i][j]); - keyBtn[i][j]->SetPosition(j*42+21*i+40, i*42+80); + + int stagger; + switch(i) + { + case 0: stagger = 42; break; + case 1: stagger = -42; break; + default: stagger = 21*(i-1); break; + } + + keyBtn[i][j]->SetPosition(j*42+stagger+40, i*42+yoff); keyBtn[i][j]->SetEffectGrow(); this->Append(keyBtn[i][j]); } @@ -217,6 +326,14 @@ GuiKeyboard::~GuiKeyboard() delete kbText; delete keyTextbox; delete keyTextboxImg; + delete keyEscText; + delete keyEscImg; + delete keyEscOverImg; + delete keyEsc; + delete keyEnterText; + delete keyEnterImg; + delete keyEnterOverImg; + delete keyEnter; delete keyCapsText; delete keyCapsImg; delete keyCapsOverImg; @@ -242,9 +359,9 @@ GuiKeyboard::~GuiKeyboard() delete keySoundClick; delete trigA; - for(int i=0; i<4; i++) + for(int i=0; i<5; i++) { - for(int j=0; j<11; j++) + for(int j=0; j<12; j++) { if(keys[i][j].ch != '\0') { @@ -270,19 +387,37 @@ void GuiKeyboard::Update(GuiTrigger * t) bool update = false; - if(keySpace->GetState() == STATE_CLICKED) + if(keyEsc->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) < kbtextmaxlen) + { + kbtextstr[strlen(kbtextstr)] = 27; // Esc key code + kbText->SetText(GetDisplayText(kbtextstr, kbtextmaxlen)); + } + keyEsc->SetState(STATE_SELECTED, t->chan); + } + else if(keyEnter->GetState() == STATE_CLICKED) + { + if(strlen(kbtextstr) < kbtextmaxlen) + { + kbtextstr[strlen(kbtextstr)] = 13; // Enter key code + kbText->SetText(GetDisplayText(kbtextstr, kbtextmaxlen)); + } + keyEnter->SetState(STATE_SELECTED, t->chan); + } + else if(keySpace->GetState() == STATE_CLICKED) { if(strlen(kbtextstr) < kbtextmaxlen) { kbtextstr[strlen(kbtextstr)] = ' '; - kbText->SetText(kbtextstr); + kbText->SetText(GetDisplayText(kbtextstr, kbtextmaxlen)); } keySpace->SetState(STATE_SELECTED, t->chan); } else if(keyBack->GetState() == STATE_CLICKED) { kbtextstr[strlen(kbtextstr)-1] = 0; - kbText->SetText(GetDisplayText(kbtextstr)); + kbText->SetText(GetDisplayText(kbtextstr, kbtextmaxlen)); keyBack->SetState(STATE_SELECTED, t->chan); } else if(keyShift->GetState() == STATE_CLICKED) @@ -302,13 +437,13 @@ void GuiKeyboard::Update(GuiTrigger * t) startloop: - for(int i=0; i<4; i++) + for(int i=0; i<5; i++) { - for(int j=0; j<11; j++) + for(int j=0; j<12; j++) { if(keys[i][j].ch != '\0') { - if(update) + if(update && keys[i][j].ch > 31) { if(shift || caps) txt[0] = keys[i][j].chShift; @@ -331,7 +466,7 @@ void GuiKeyboard::Update(GuiTrigger * t) kbtextstr[strlen(kbtextstr)] = keys[i][j].ch; } } - kbText->SetText(GetDisplayText(kbtextstr)); + kbText->SetText(GetDisplayText(kbtextstr, kbtextmaxlen)); keyBtn[i][j]->SetState(STATE_SELECTED, t->chan); if(shift) diff --git a/src/platform/wii/libwiigui/gui_sound.cpp b/src/platform/wii/libwiigui/gui_sound.cpp index a272274..8a718c7 100644 --- a/src/platform/wii/libwiigui/gui_sound.cpp +++ b/src/platform/wii/libwiigui/gui_sound.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_sound.cpp * diff --git a/src/platform/wii/libwiigui/gui_text.cpp b/src/platform/wii/libwiigui/gui_text.cpp index ac43d21..842ba43 100644 --- a/src/platform/wii/libwiigui/gui_text.cpp +++ b/src/platform/wii/libwiigui/gui_text.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_text.cpp * @@ -10,13 +10,13 @@ #include "gui.h" +static GXColor presetColor = (GXColor){255, 255, 255, 255}; static int currentSize = 0; static int presetSize = 0; static int presetMaxWidth = 0; static int presetAlignmentHor = 0; static int presetAlignmentVert = 0; static u16 presetStyle = 0; -static GXColor presetColor = (GXColor){255, 255, 255, 255}; #define TEXT_SCROLL_DELAY 8 #define TEXT_SCROLL_INITIAL_DELAY 6 @@ -34,7 +34,7 @@ GuiText::GuiText(const char * t, int s, GXColor c) style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE; maxWidth = 0; wrap = false; - textDyn = NULL; + textDynNum = 0; textScroll = SCROLL_NONE; textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; @@ -48,6 +48,9 @@ GuiText::GuiText(const char * t, int s, GXColor c) origText = strdup(t); text = charToWideChar(t); } + + for(int i=0; i < 20; i++) + textDyn[i] = NULL; } /** @@ -63,7 +66,7 @@ GuiText::GuiText(const char * t) style = presetStyle; maxWidth = presetMaxWidth; wrap = false; - textDyn = NULL; + textDynNum = 0; textScroll = SCROLL_NONE; textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; @@ -77,6 +80,9 @@ GuiText::GuiText(const char * t) origText = strdup(t); text = charToWideChar(t); } + + for(int i=0; i < 20; i++) + textDyn[i] = NULL; } /** @@ -88,8 +94,13 @@ GuiText::~GuiText() free(origText); if(text) delete[] text; - if(textDyn) - delete[] textDyn; + + if(textDynNum > 0) + { + for(int i=0; i < textDynNum; i++) + if(textDyn[i]) + delete[] textDyn[i]; + } } void GuiText::SetText(const char * t) @@ -98,12 +109,17 @@ void GuiText::SetText(const char * t) free(origText); if(text) delete[] text; - if(textDyn) - delete[] textDyn; + + if(textDynNum > 0) + { + for(int i=0; i < textDynNum; i++) + if(textDyn[i]) + delete[] textDyn[i]; + } origText = NULL; text = NULL; - textDyn = NULL; + textDynNum = 0; textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; @@ -114,6 +130,38 @@ void GuiText::SetText(const char * t) } } +void GuiText::SetWText(wchar_t * t) +{ + if(origText) + free(origText); + if(text) + delete[] text; + + if(textDynNum > 0) + { + for(int i=0; i < textDynNum; i++) + if(textDyn[i]) + delete[] textDyn[i]; + } + + origText = NULL; + text = NULL; + textDynNum = 0; + textScrollPos = 0; + textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; + + if(t) + text = wcsdup(t); +} + +int GuiText::GetLength() +{ + if(!text) + return 0; + + return wcslen(text); +} + void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v) { presetSize = sz; @@ -132,12 +180,51 @@ void GuiText::SetFontSize(int s) void GuiText::SetMaxWidth(int width) { maxWidth = width; + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; +} + +int GuiText::GetTextWidth() +{ + if(!text) + return 0; + + if(currentSize != size) + { + ChangeFontSize(size); + + if(!fontSystem[size]) + fontSystem[size] = new FreeTypeGX(size); + + currentSize = size; + } + return fontSystem[size]->getWidth(text); } void GuiText::SetWrap(bool w, int width) { wrap = w; maxWidth = width; + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; } void GuiText::SetScroll(int s) @@ -145,11 +232,17 @@ void GuiText::SetScroll(int s) if(textScroll == s) return; - if(textDyn) + for(int i=0; i < textDynNum; i++) { - delete[] textDyn; - textDyn = NULL; + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } } + + textDynNum = 0; + textScroll = s; textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; @@ -200,6 +293,28 @@ void GuiText::SetAlignment(int hor, int vert) alignmentVert = vert; } +void GuiText::ResetText() +{ + if(!origText) + return; + if(text) + delete[] text; + + text = charToWideChar(origText); + + for(int i=0; i < textDynNum; i++) + { + if(textDyn[i]) + { + delete[] textDyn[i]; + textDyn[i] = NULL; + } + } + + textDynNum = 0; + currentSize = 0; +} + /** * Draw the text on screen */ @@ -227,122 +342,138 @@ void GuiText::Draw() currentSize = newSize; } - if(maxWidth > 0) + if(maxWidth == 0) { - char * tmpText = strdup(origText); - u8 maxChar = (maxWidth*2.0) / newSize; + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); + this->UpdateEffects(); + return; + } - if(!textDyn) + u32 textlen = wcslen(text); + + if(wrap) + { + if(textDynNum == 0) { - if(strlen(tmpText) > maxChar) - tmpText[maxChar] = 0; - textDyn = charToWideChar(tmpText); + u32 n = 0, ch = 0; + int linenum = 0; + int lastSpace = -1; + int lastSpaceIndex = -1; + + while(ch < textlen && linenum < 20) + { + if(n == 0) + textDyn[linenum] = new wchar_t[textlen + 1]; + + textDyn[linenum][n] = text[ch]; + textDyn[linenum][n+1] = 0; + + if(text[ch] == ' ' || ch == textlen-1) + { + if(fontSystem[currentSize]->getWidth(textDyn[linenum]) > maxWidth) + { + if(lastSpace >= 0) + { + textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after + ch = lastSpace; // go backwards to the last space + lastSpace = -1; // we have used this space + lastSpaceIndex = -1; + } + ++linenum; + n = -1; + } + else if(ch == textlen-1) + { + ++linenum; + } + } + if(text[ch] == ' ' && n >= 0) + { + lastSpace = ch; + lastSpaceIndex = n; + } + ++ch; + ++n; + } + textDynNum = linenum; + } + + int lineheight = newSize + 6; + int voffset = 0; + + if(alignmentVert == ALIGN_MIDDLE) + voffset = (lineheight >> 1) * (1-textDynNum); + + int left = this->GetLeft(); + int top = this->GetTop() + voffset; + + for(int i=0; i < textDynNum; ++i) + fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style); + } + else + { + if(textDynNum == 0) + { + textDynNum = 1; + textDyn[0] = wcsdup(text); + int len = wcslen(textDyn[0]); + + while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + textDyn[0][--len] = 0; } if(textScroll == SCROLL_HORIZONTAL) { - int textlen = strlen(origText); - - if(textlen > maxChar && (FrameTimer % textScrollDelay == 0)) + if(fontSystem[currentSize]->getWidth(text) > maxWidth && (FrameTimer % textScrollDelay == 0)) { if(textScrollInitialDelay) { - textScrollInitialDelay--; + --textScrollInitialDelay; } else { - textScrollPos++; - if(textScrollPos > textlen-1) + ++textScrollPos; + if((u32)textScrollPos > textlen-1) { textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; } - strncpy(tmpText, &origText[textScrollPos], maxChar-1); - tmpText[maxChar-1] = 0; + wcscpy(textDyn[0], &text[textScrollPos]); + u32 dynlen = wcslen(textDyn[0]); - int dynlen = strlen(tmpText); - - if(dynlen+2 < maxChar) + if(dynlen+2 < textlen) { - tmpText[dynlen] = ' '; - tmpText[dynlen+1] = ' '; - strncat(&tmpText[dynlen+2], origText, maxChar - dynlen - 2); + textDyn[0][dynlen] = ' '; + textDyn[0][dynlen+1] = ' '; + textDyn[0][dynlen+2] = 0; + dynlen += 2; } - if(textDyn) delete[] textDyn; - textDyn = charToWideChar(tmpText); - } - } - if(textDyn) - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style); - } - else if(wrap) - { - int lineheight = newSize + 6; - int txtlen = wcslen(text); - int i = 0; - int ch = 0; - int linenum = 0; - int lastSpace = -1; - int lastSpaceIndex = -1; - wchar_t * textrow[20]; - while(ch < txtlen) - { - if(i == 0) - textrow[linenum] = new wchar_t[txtlen + 1]; - - textrow[linenum][i] = text[ch]; - textrow[linenum][i+1] = 0; - - if(text[ch] == ' ' || ch == txtlen-1) - { - if(wcslen(textrow[linenum]) >= maxChar) + if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) { - if(lastSpace >= 0) + while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + textDyn[0][--dynlen] = 0; + } + else + { + int i = 0; + + while(fontSystem[currentSize]->getWidth(textDyn[0]) < maxWidth && dynlen+1 < textlen) { - textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after - ch = lastSpace; // go backwards to the last space - lastSpace = -1; // we have used this space - lastSpaceIndex = -1; + textDyn[0][dynlen] = text[i++]; + textDyn[0][++dynlen] = 0; } - linenum++; - i = -1; - } - else if(ch == txtlen-1) - { - linenum++; + + if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth) + textDyn[0][dynlen-2] = 0; + else + textDyn[0][dynlen-1] = 0; } } - if(text[ch] == ' ' && i >= 0) - { - lastSpace = ch; - lastSpaceIndex = i; - } - ch++; - i++; - } - - int voffset = 0; - - if(alignmentVert == ALIGN_MIDDLE) - voffset = -(lineheight*linenum)/2 + lineheight/2; - - for(i=0; i < linenum; i++) - { - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, textrow[i], c, style); - delete[] textrow[i]; } } - else - { - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style); - } - free(tmpText); - } - else - { - fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); + fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style); } this->UpdateEffects(); } diff --git a/src/platform/wii/libwiigui/gui_trigger.cpp b/src/platform/wii/libwiigui/gui_trigger.cpp index 94293cf..d4f98c6 100644 --- a/src/platform/wii/libwiigui/gui_trigger.cpp +++ b/src/platform/wii/libwiigui/gui_trigger.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_trigger.cpp * @@ -9,8 +9,12 @@ ***************************************************************************/ #include "gui.h" +#include +#include -static int scrollDelay = 0; +static u64 prev[4]; +static u64 now[4]; +static u32 delay[4]; /** * Constructor for the GuiTrigger class. @@ -87,7 +91,7 @@ void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns) * Get X/Y value from Wii Joystick (classic, nunchuk) input ***************************************************************************/ -s8 GuiTrigger::WPAD_Stick(u8 right, int axis) +s8 GuiTrigger::WPAD_Stick(u8 stick, int axis) { float mag = 0.0; float ang = 0.0; @@ -96,7 +100,7 @@ s8 GuiTrigger::WPAD_Stick(u8 right, int axis) { case WPAD_EXP_NUNCHUK: case WPAD_EXP_GUITARHERO3: - if (right == 0) + if (stick == 0) { mag = wpad->exp.nunchuk.js.mag; ang = wpad->exp.nunchuk.js.ang; @@ -104,7 +108,7 @@ s8 GuiTrigger::WPAD_Stick(u8 right, int axis) break; case WPAD_EXP_CLASSIC: - if (right == 0) + if (stick == 0) { mag = wpad->exp.classic.ljs.mag; ang = wpad->exp.classic.ljs.ang; @@ -133,6 +137,16 @@ s8 GuiTrigger::WPAD_Stick(u8 right, int axis) return (s8)(val * 128.0f); } +s8 GuiTrigger::WPAD_StickX(u8 stick) +{ + return WPAD_Stick(stick, 0); +} + +s8 GuiTrigger::WPAD_StickY(u8 stick) +{ + return WPAD_Stick(stick, 1); +} + bool GuiTrigger::Left() { u32 wiibtn = WPAD_BUTTON_LEFT; @@ -140,24 +154,28 @@ bool GuiTrigger::Left() if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) || (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT || pad.stickX < -PADCAL - || WPAD_Stick(0,0) < -PADCAL) + || WPAD_StickX(0) < -PADCAL) { if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) || pad.btns_d & PAD_BUTTON_LEFT) { - scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay return true; } - else if(scrollDelay == 0) + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) { - scrollDelay = SCROLL_LOOP_DELAY; + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; return true; } - else - { - if(scrollDelay > 0) - scrollDelay--; - } } return false; } @@ -169,24 +187,28 @@ bool GuiTrigger::Right() if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT) || (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT || pad.stickX > PADCAL - || WPAD_Stick(0,0) > PADCAL) + || WPAD_StickX(0) > PADCAL) { if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT) || pad.btns_d & PAD_BUTTON_RIGHT) { - scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay return true; } - else if(scrollDelay == 0) + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) { - scrollDelay = SCROLL_LOOP_DELAY; + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; return true; } - else - { - if(scrollDelay > 0) - scrollDelay--; - } } return false; } @@ -198,24 +220,28 @@ bool GuiTrigger::Up() if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP) || (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP || pad.stickY > PADCAL - || WPAD_Stick(0,1) > PADCAL) + || WPAD_StickY(0) > PADCAL) { if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP) || pad.btns_d & PAD_BUTTON_UP) { - scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay return true; } - else if(scrollDelay == 0) + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) { - scrollDelay = SCROLL_LOOP_DELAY; + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; return true; } - else - { - if(scrollDelay > 0) - scrollDelay--; - } } return false; } @@ -227,24 +253,28 @@ bool GuiTrigger::Down() if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN) || (pad.btns_d | pad.btns_h) & PAD_BUTTON_DOWN || pad.stickY < -PADCAL - || WPAD_Stick(0,1) < -PADCAL) + || WPAD_StickY(0) < -PADCAL) { if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN) || pad.btns_d & PAD_BUTTON_DOWN) { - scrollDelay = SCROLL_INITIAL_DELAY; // reset scroll delay. + prev[chan] = gettime(); + delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay return true; } - else if(scrollDelay == 0) + + now[chan] = gettime(); + + if(diff_usec(prev[chan], now[chan]) > delay[chan]) { - scrollDelay = SCROLL_LOOP_DELAY; + prev[chan] = now[chan]; + + if(delay[chan] == SCROLL_DELAY_INITIAL) + delay[chan] = SCROLL_DELAY_LOOP; + else if(delay[chan] > SCROLL_DELAY_DECREASE) + delay[chan] -= SCROLL_DELAY_DECREASE; return true; } - else - { - if(scrollDelay > 0) - scrollDelay--; - } } return false; } diff --git a/src/platform/wii/libwiigui/gui_window.cpp b/src/platform/wii/libwiigui/gui_window.cpp index d4d5e4b..b589c1c 100644 --- a/src/platform/wii/libwiigui/gui_window.cpp +++ b/src/platform/wii/libwiigui/gui_window.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * libwiigui * - * Tantric 2009 + * Tantric 2009-2010 * * gui_window.cpp * @@ -53,7 +53,8 @@ void GuiWindow::Remove(GuiElement* e) if (e == NULL) return; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { if(e == _elements.at(i)) { @@ -68,6 +69,18 @@ void GuiWindow::RemoveAll() _elements.clear(); } +bool GuiWindow::Find(GuiElement* e) +{ + if (e == NULL) + return false; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) + if(e == _elements.at(i)) + return true; + return false; +} + GuiElement* GuiWindow::GetGuiElementAt(u32 index) const { if (index >= _elements.size()) @@ -85,7 +98,8 @@ void GuiWindow::Draw() if(_elements.size() == 0 || !this->IsVisible()) return; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { _elements.at(i)->Draw(); } catch (const std::exception& e) { } @@ -97,12 +111,26 @@ void GuiWindow::Draw() Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1); } +void GuiWindow::DrawTooltip() +{ + if(_elements.size() == 0 || !this->IsVisible()) + return; + + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; i++) + { + try { _elements.at(i)->DrawTooltip(); } + catch (const std::exception& e) { } + } +} + void GuiWindow::ResetState() { if(state != STATE_DISABLED) state = STATE_DEFAULT; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { _elements.at(i)->ResetState(); } catch (const std::exception& e) { } @@ -113,7 +141,8 @@ void GuiWindow::SetState(int s) { state = s; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { _elements.at(i)->SetState(s); } catch (const std::exception& e) { } @@ -124,7 +153,8 @@ void GuiWindow::SetVisible(bool v) { visible = v; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { _elements.at(i)->SetVisible(v); } catch (const std::exception& e) { } @@ -146,7 +176,8 @@ void GuiWindow::ChangeFocus(GuiElement* e) if(parentElement) return; // this is only intended for the main window - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { if(e == _elements.at(i)) _elements.at(i)->SetFocus(1); @@ -162,10 +193,12 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) int found = -1; int newfocus = -1; - u8 i; + int i; + + int elemSize = _elements.size(); // look for currently in focus element - for (i = 0; i < _elements.size(); i++) + for (i = 0; i < elemSize; ++i) { try { @@ -181,7 +214,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) // element with focus not found, try to give focus if(found == -1) { - for (i = 0; i < _elements.size(); i++) + for (i = 0; i < elemSize; ++i) { try { @@ -198,7 +231,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) else if(t->wpad->btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B) || t->pad.btns_d & PAD_BUTTON_B) { - for (i = found; i < _elements.size(); i++) + for (i = found; i < elemSize; ++i) { try { @@ -215,7 +248,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) if(newfocus == -1) { - for (i = 0; i < found; i++) + for (i = 0; i < found; ++i) { try { @@ -236,13 +269,14 @@ int GuiWindow::GetSelected() { // find selected element int found = -1; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { if(_elements.at(i)->GetState() == STATE_SELECTED) { - found = i; + found = int(i); break; } } @@ -258,7 +292,8 @@ void GuiWindow::MoveSelectionHor(int dir) int found = -1; u16 left = 0; u16 top = 0; - u8 i = 0; + u32 i; + u32 elemSize = _elements.size(); int selected = this->GetSelected(); @@ -268,8 +303,9 @@ void GuiWindow::MoveSelectionHor(int dir) top = _elements.at(selected)->GetTop(); } + // look for a button on the same row, to the left/right - for (i = 0; i < _elements.size(); i++) + for (i = 0; i < elemSize; ++i) { try { @@ -278,9 +314,9 @@ void GuiWindow::MoveSelectionHor(int dir) if(_elements.at(i)->GetLeft()*dir > left*dir && _elements.at(i)->GetTop() == top) { if(found == -1) - found = i; + found = int(i); else if(_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir) - found = i; // this is a better match + found = int(i); // this is a better match } } } @@ -290,7 +326,7 @@ void GuiWindow::MoveSelectionHor(int dir) goto matchfound; // match still not found, let's try the first button in the next row - for (i = 0; i < _elements.size(); i++) + for (i = 0; i < elemSize; ++i) { try { @@ -327,7 +363,6 @@ void GuiWindow::MoveSelectionVert(int dir) int found = -1; u16 left = 0; u16 top = 0; - u8 i = 0; int selected = this->GetSelected(); @@ -338,7 +373,8 @@ void GuiWindow::MoveSelectionVert(int dir) } // look for a button above/below, with the least horizontal difference - for (i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { @@ -373,12 +409,23 @@ void GuiWindow::MoveSelectionVert(int dir) } } +void GuiWindow::ResetText() +{ + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; i++) + { + try { _elements.at(i)->ResetText(); } + catch (const std::exception& e) { } + } +} + void GuiWindow::Update(GuiTrigger * t) { if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) return; - for (u8 i = 0; i < _elements.size(); i++) + u32 elemSize = _elements.size(); + for (u32 i = 0; i < elemSize; ++i) { try { _elements.at(i)->Update(t); } catch (const std::exception& e) { } diff --git a/src/platform/wii/menu.cpp b/src/platform/wii/menu.cpp index 1e24c3c..617f81c 100644 --- a/src/platform/wii/menu.cpp +++ b/src/platform/wii/menu.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii Home Menu - * Tantric 2009 + * Tantric 2009-2010 * * menu.cpp * @@ -20,7 +20,7 @@ #include "wiihardware.h" #define THREAD_SLEEP 100 -#define APPVERSION "1.2" +#define APPVERSION "1.3" static GuiImageData * pointer[4]; static GuiWindow * mainWindow = NULL; @@ -70,7 +70,7 @@ static void * UpdateGUI (void *arg) if(ExitRequested) { - for(i = 0; i < 255; i += 15) + for(i = 0; i <= 255; i += 15) { mainWindow->Draw(); Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, i},1); diff --git a/src/platform/wii/oggplayer.c b/src/platform/wii/oggplayer.c index 689160d..3f7de9a 100644 --- a/src/platform/wii/oggplayer.c +++ b/src/platform/wii/oggplayer.c @@ -1,39 +1,44 @@ /* Copyright (c) 2008 Francisco Muñoz 'Hermes' All rights reserved. - + Proper (standard) vorbis usage by Tantric, 2009 Threading modifications/corrections by Tantric, 2009 - Redistribution and use in source and binary forms, with or without modification, are - permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - - The names of the contributors may not be used to endorse or promote products derived - from this software without specific prior written permission. + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - The names of the contributors may not be used to endorse or promote products + derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef NO_SOUND -#include "oggplayer.h" +#include +#include +#include #include #include #include +#include "oggplayer.h" + /* functions to read the Ogg file from memory */ static struct @@ -46,14 +51,13 @@ static struct static int f_read(void * punt, int bytes, int blocks, int *f) { int b; - int c; + int c = 0; int d; if (bytes * blocks <= 0) return 0; - blocks = bytes * blocks; - c = 0; + blocks *= bytes; while (blocks > 0) { @@ -61,9 +65,9 @@ static int f_read(void * punt, int bytes, int blocks, int *f) if (b > 4096) b = 4096; - if (*f >= 0x666 && *f <= 0x669) + d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) { - d = (*f) - 0x666; if (file[d].size == 0) return -1; if ((file[d].pos + b) > file[d].size) @@ -91,11 +95,12 @@ static int f_seek(int *f, ogg_int64_t offset, int mode) { if(f==NULL) return(-1); - int k, d; + int k; mode &= 3; - if (*f >= 0x666 && *f <= 0x669) + + int d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) { - d = (*f) - 0x666; k = 0; if (file[d].size == 0) @@ -116,7 +121,7 @@ static int f_seek(int *f, ogg_int64_t offset, int mode) else file[d].pos = offset; } - if (mode == 1) + else if (mode == 1) { if ((file[d].pos + offset) >= file[d].size) { @@ -131,7 +136,7 @@ static int f_seek(int *f, ogg_int64_t offset, int mode) else file[d].pos += offset; } - if (mode == 2) + else if (mode == 2) { if ((file[d].size + offset) >= file[d].size) @@ -161,10 +166,9 @@ static int f_seek(int *f, ogg_int64_t offset, int mode) static int f_close(int *f) { - int d; - if (*f >= 0x666 && *f <= 0x669) + int d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) { - d = (*f) - 0x666; file[d].size = 0; file[d].pos = 0; if (file[d].mem) @@ -180,11 +184,11 @@ static int f_close(int *f) static long f_tell(int *f) { - int k, d; + int k; - if (*f >= 0x666 && *f <= 0x669) + int d = (*f) - 0x666; + if((unsigned)(d) <= (0x669 - 0x666)) { - d = (*f) - 0x666; k = file[d].pos; } else @@ -200,8 +204,15 @@ static int mem_open(char * ogg, int size) if (one) { one = 0; - for (n = 0; n < 4; n++) - file[n].size = 0; + + file[0].size = 0; + file[1].size = 0; + file[2].size = 0; + file[3].size = 0; + file[0].mem = ogg; + file[0].size = size; + file[0].pos = 0; + return (0x666); } for (n = 0; n < 4; n++) @@ -219,7 +230,7 @@ static int mem_open(char * ogg, int size) static int mem_close(int fd) { - if (fd >= 0x666 && fd <= 0x669) // it is a memory file descriptor? + if((unsigned)((fd) - 0x666) <= (0x669 - 0x666)) // it is a memory file descriptor? { fd -= 0x666; file[fd].size = 0; @@ -348,8 +359,7 @@ static void * ogg_player_thread(private_data_ogg * priv) priv[0].seek_time = -1; } - ret - = ov_read( + ret = ov_read( &priv[0].vf, (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx], MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section); @@ -440,11 +450,11 @@ void StopOgg() } } -int PlayOgg(char * buf, int buflen, int time_pos, int mode) +int PlayOgg(const void *buffer, s32 len, int time_pos, int mode) { StopOgg(); - private_ogg.fd = mem_open(buf, buflen); + private_ogg.fd = mem_open((char *)buffer, len); if (private_ogg.fd < 0) { @@ -508,8 +518,7 @@ int StatusOgg() return 255; // EOF else if (private_ogg.flag & 128) return 2; // paused - else - return 1; // running + return 1; // running } void SetVolumeOgg(int volume) @@ -522,10 +531,8 @@ s32 GetTimeOgg() { int ret; if (ogg_thread_running == 0 || private_ogg.fd < 0) - return 0; + return -1; ret = ((s32) ov_time_tell(&private_ogg.vf)); - if (ret < 0) - ret = 0; return ret; } diff --git a/src/platform/wii/oggplayer.h b/src/platform/wii/oggplayer.h index 58b29af..c505040 100644 --- a/src/platform/wii/oggplayer.h +++ b/src/platform/wii/oggplayer.h @@ -5,37 +5,32 @@ Proper (standard) vorbis usage by Tantric, 2009 Threading modifications/corrections by Tantric, 2009 - Redistribution and use in source and binary forms, with or without modification, are - permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - - The names of the contributors may not be used to endorse or promote products derived - from this software without specific prior written permission. + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - The names of the contributors may not be used to endorse or promote products + derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NO_SOUND - #ifndef __OGGPLAYER_H__ #define __OGGPLAYER_H__ -#include -#include -#include - #ifdef __cplusplus extern "C" { @@ -49,129 +44,69 @@ extern "C" #define OGG_STATUS_PAUSED 2 #define OGG_STATUS_EOF 255 -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* Player OGG functions */ -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* int PlayOgg(int fd, int time_pos, int mode); - - Play an Ogg file. This file can be loaded from memory (mem_open(void *ogg, int size_ogg)) or from device with open("device:file.ogg",O_RDONLY,0); - - NOTE: The file is closed by the player when you call PlayOgg(), StopOgg() or if it fail. - - -- Params --- - - fd: file descriptor from open() or mem_open() - - time_pos: initial time position in the file (in milliseconds). For example, use 30000 to advance 30 seconds - - mode: Use OGG_ONE_TIME or OGG_INFINITE_TIME. When you use OGG_ONE_TIME the sound stops and StatusOgg() return OGG_STATUS_EOF - - return: 0- Ok, -1 Error - - */ - -int PlayOgg(char * buf, int buflen, int time_pos, int mode); - -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* void StopOgg(); - - Stop an Ogg file. - - NOTE: The file is closed and the player thread is released - - -- Params --- - - - */ +/**************************************************************************** + * PlayOgg + * + * Creates a thread that starts playing from the specific Ogg buffer + * buffer - pointer to the start of the Ogg data + * len - length of Ogg file + * time_pos - initial time position at which to start playback + * mode - playback mode (OGG_ONE_TIME or OGG_INFINITE_TIME) + * returns: -1 on error, 0 on success + ***************************************************************************/ +int PlayOgg(const void *buffer, s32 len, int time_pos, int mode); +/**************************************************************************** + * StopOgg + * + * Stops playback. The player thread is shut down. + ***************************************************************************/ void StopOgg(); -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* void PauseOgg(int pause); - - Pause an Ogg file. - - -- Params --- - - pause: 0 -> continue, 1-> pause - - */ - +/**************************************************************************** + * PauseOgg + * + * Pauses playback. 0 -> continue, 1-> pause + ***************************************************************************/ void PauseOgg(int pause); -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* int StatusOgg(); - - Return the Ogg status - - -- Params --- - - - return: OGG_STATUS_RUNNING - OGG_STATUS_ERR -> not initialized? - OGG_STATUS_PAUSED - OGG_STATUS_EOF -> player stopped by End Of File - - */ - +/**************************************************************************** + * StatusOgg + * + * Returns the Ogg player's status + * returns: + * OGG_STATUS_RUNNING + * OGG_STATUS_ERR -> not initialized + * OGG_STATUS_PAUSED + * OGG_STATUS_EOF -> player stopped by End Of File + ***************************************************************************/ int StatusOgg(); -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* void SetVolumeOgg(int volume); - - Set the Ogg playing volume. - NOTE: it change the volume of voice 0 (used for the Ogg player) - - -- Params --- - - volume: 0 to 255 (max) - - */ - +/**************************************************************************** + * SetVolumeOgg + * + * Sets the Ogg playback volume (0 to 255 (max)) + ***************************************************************************/ void SetVolumeOgg(int volume); -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* s32 GetTimeOgg(); - - Return the Ogg time from the starts of the file - - -- Params --- - - return: 0 -> Ok or error condition (you must ignore this value) - >0 -> time in milliseconds from the starts - - */ - +/**************************************************************************** + * GetTimeOgg + * + * Gets current Ogg position + * returns -1 on error, or the time in milliseconds from the start + ***************************************************************************/ s32 GetTimeOgg(); -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -/* void SetTimeOgg(s32 time_pos); - - Set the time position - - NOTE: The file is closed by the player when you call PlayOgg(), StopOgg() or if it fail. - - -- Params --- - - time_pos: time position in the file (in milliseconds). For example, use 30000 to advance 30 seconds - - */ - +/**************************************************************************** + * SetTimeOgg + * + * Sets the time position + * time_pos: time position (in milliseconds) to advance + ***************************************************************************/ void SetTimeOgg(s32 time_pos); -/*------------------------------------------------------------------------------------------------------------------------------------------------------*/ - #ifdef __cplusplus } #endif #endif - -#endif diff --git a/src/platform/wii/pngu.c b/src/platform/wii/pngu.c index c223c8d..57408f5 100644 --- a/src/platform/wii/pngu.c +++ b/src/platform/wii/pngu.c @@ -1,31 +1,41 @@ /******************************************************************************************** - -PNGU Version : 0.2a - -Coder : frontier - -More info : http://frontier-dev.net - -Modified by Tantric, 2009 - +* +* PNGU +* +* Original author: frontier (http://frontier-dev.net) +* Modified by Tantric, 2009-2010 +* ********************************************************************************************/ + #include #include +#include #include "pngu.h" -#include "png.h" +#include // Constants -#define PNGU_SOURCE_BUFFER 1 -#define PNGU_SOURCE_DEVICE 2 +#define PNGU_SOURCE_BUFFER 1 +#define PNGU_SOURCE_DEVICE 2 -// Prototypes of helper functions -int pngu_info (IMGCTX ctx); -int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha); -void pngu_free_info (IMGCTX ctx); -void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length); -void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length); -void pngu_flush_data_to_buffer (png_structp png_ptr); -int pngu_clamp (int value, int min, int max); +// Return codes +#define PNGU_OK 0 +#define PNGU_ODD_WIDTH 1 +#define PNGU_ODD_STRIDE 2 +#define PNGU_INVALID_WIDTH_OR_HEIGHT 3 +#define PNGU_FILE_IS_NOT_PNG 4 +#define PNGU_UNSUPPORTED_COLOR_TYPE 5 +#define PNGU_NO_FILE_SELECTED 6 +#define PNGU_CANT_OPEN_FILE 7 +#define PNGU_CANT_READ_FILE 8 +#define PNGU_LIB_ERROR 9 + +// Color types +#define PNGU_COLOR_TYPE_GRAY 1 +#define PNGU_COLOR_TYPE_GRAY_ALPHA 2 +#define PNGU_COLOR_TYPE_PALETTE 3 +#define PNGU_COLOR_TYPE_RGB 4 +#define PNGU_COLOR_TYPE_RGB_ALPHA 5 +#define PNGU_COLOR_TYPE_UNKNOWN 6 // PNGU Image context struct struct _IMGCTX @@ -47,950 +57,44 @@ struct _IMGCTX png_bytep img_data; }; -// PNGU Implementation // +// PNGU Implementation -IMGCTX PNGU_SelectImageFromBuffer (const void *buffer) +static void pngu_free_info (IMGCTX ctx) { - IMGCTX ctx = NULL; - - if (!buffer) - return NULL; - - ctx = malloc (sizeof (struct _IMGCTX)); - if (!ctx) - return NULL; - - ctx->buffer = (void *) buffer; - ctx->source = PNGU_SOURCE_BUFFER; - ctx->cursor = 0; - ctx->filename = NULL; - ctx->propRead = 0; - ctx->infoRead = 0; - - return ctx; -} - -IMGCTX PNGU_SelectImageFromDevice (const char *filename) -{ - IMGCTX ctx = NULL; - - if (!filename) - return NULL; - - ctx = malloc (sizeof (struct _IMGCTX)); - if (!ctx) - return NULL; - - ctx->buffer = NULL; - ctx->source = PNGU_SOURCE_DEVICE; - ctx->cursor = 0; - - ctx->filename = malloc (strlen (filename) + 1); - if (!ctx->filename) - { - free (ctx); - return NULL; - } - strcpy(ctx->filename, filename); - - ctx->propRead = 0; - ctx->infoRead = 0; - - return ctx; -} - -void PNGU_ReleaseImageContext (IMGCTX ctx) -{ - if (!ctx) - return; - - if (ctx->filename) - free (ctx->filename); - - if ((ctx->propRead) && (ctx->prop.trans)) - free (ctx->prop.trans); - - pngu_free_info (ctx); - free (ctx); -} - -int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop) -{ - int res; - - if (!ctx->propRead) - { - res = pngu_info (ctx); - if (res != PNGU_OK) - return res; - } - - *imgprop = ctx->prop; - return PNGU_OK; -} - -int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) -{ - int result; - PNGU_u32 x, y, buffWidth; - - // width needs to be divisible by two - if (width % 2) - return PNGU_ODD_WIDTH; - - // stride needs to be divisible by two - if (stride % 2) - return PNGU_ODD_STRIDE; - - result = pngu_decode (ctx, width, height, 1); - if (result != PNGU_OK) - return result; - - // Copy image to the output buffer - buffWidth = (width + stride) >> 1; - PNGU_u32 wid2 = width >>1; - for (y = 0; y < height; y++) - { - for (x = 0; x < wid2; x++) - { - PNGU_u32 x6 = x*6; - ((PNGU_u32 *)buffer)[y*buffWidth+x] = PNGU_RGB8_TO_YCbYCr (*(ctx->row_pointers[y]+x6), *(ctx->row_pointers[y]+x6+1), *(ctx->row_pointers[y]+x6+2), - *(ctx->row_pointers[y]+x6+3), *(ctx->row_pointers[y]+x6+4), *(ctx->row_pointers[y]+x6+5)); - } - } - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) -{ - int result; - PNGU_u32 x, y, buffWidth; - - result = pngu_decode (ctx, width, height, 1); - if (result != PNGU_OK) - return result; - - buffWidth = width + stride; - - // Copy image to the output buffer - for (y = 0; y < height; y++) - for (x = 0; x < width; x++) - ((PNGU_u16 *)buffer)[y*buffWidth+x] = - (((PNGU_u16) (ctx->row_pointers[y][x*3] & 0xF8)) << 8) | - (((PNGU_u16) (ctx->row_pointers[y][x*3+1] & 0xFC)) << 3) | - (((PNGU_u16) (ctx->row_pointers[y][x*3+2] & 0xF8)) >> 3); - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha) -{ - int result; - PNGU_u32 x, y, buffWidth; - - result = pngu_decode (ctx, width, height, 0); - if (result != PNGU_OK) - return result; - - buffWidth = width + stride; - - // Check is source image has an alpha channel - if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) ) - { - // Alpha channel present, copy image to the output buffer - for (y = 0; y < height; y++) - memcpy (buffer + (y * buffWidth << 2), ctx->row_pointers[y], width<<2); - } - else - { - // No alpha channel present, copy image to the output buffer - for (y = 0; y < height; y++) - for (x = 0; x < width; x++) - ((PNGU_u32 *)buffer)[y*buffWidth+x] = - (((PNGU_u32) ctx->row_pointers[y][x*3]) << 24) | - (((PNGU_u32) ctx->row_pointers[y][x*3+1]) << 16) | - (((PNGU_u32) ctx->row_pointers[y][x*3+2]) << 8) | - ((PNGU_u32) default_alpha); - } - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer) -{ - PNGU_u32 x, y; - - // width and height need to be divisible by four - if ((width % 4) || (height % 4)) - return PNGU_INVALID_WIDTH_OR_HEIGHT; - - int result = pngu_decode (ctx, width, height, 1); - if (result != PNGU_OK) - return result; - - // Copy image to the output buffer - PNGU_u32 qwidth = width >> 2; - PNGU_u32 qheight = height >> 2; - - for (y = 0; y < qheight; y++) - for (x = 0; x < qwidth; x++) - { - PNGU_u32 y4 = y << 2; - PNGU_u32 x12 = x * 12; - int blockbase = (y * qwidth + x) << 2; - - PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12)); - PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase] = - (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) | - (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) | - (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) | - (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3))); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+1] = - (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) | - (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) | - (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) | - (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3))); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+2] = - (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) | - (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) | - (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) | - (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3))); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+3] = - (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) | - (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) | - (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) | - (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3))); - } - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha) -{ - int result; - PNGU_u32 x, y, qwidth, qheight; - PNGU_u64 alphaMask; - - // width and height need to be divisible by four - if ((width % 4) || (height % 4)) - return PNGU_INVALID_WIDTH_OR_HEIGHT; - - result = pngu_decode (ctx, width, height, 0); - if (result != PNGU_OK) - return result; - - // Init some vars - qwidth = width >> 2; - qheight = height >> 2; - - // Check is source image has an alpha channel - if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) ) - { - // Alpha channel present, copy image to the output buffer - for (y = 0; y < qheight; y++) - for (x = 0; x < qwidth; x++) - { - int blockbase = (y * qwidth + x) << 2; - - PNGU_u32 y4 = y << 2; - PNGU_u32 x16 = x << 4; - - PNGU_u64 tmp; - - PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16)); - PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16+8)); - - // If first pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444 - if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL) - tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5); - else - tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4); - - // If second pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444 - if ((fieldA & 0xE0ULL) == 0xE0ULL) - tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21); - else - tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20); - - // If third pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444 - if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL) - tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27); - else - tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28); - - // If fourth pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444 - if ((fieldB & 0xE0ULL) == 0xE0ULL) - tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11); - else - tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12); - ((PNGU_u64 *) buffer)[blockbase] = tmp; - - fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16)); - fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16+8)); - if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4); - - if ((fieldA & 0xE0ULL) == 0xE0ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20); - - if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28); - - if ((fieldB & 0xE0ULL) == 0xE0ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12); - ((PNGU_u64 *) buffer)[blockbase+1] = tmp; - - fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16)); - fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16+8)); - if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4); - - if ((fieldA & 0xE0ULL) == 0xE0ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20); - - if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28); - - if ((fieldB & 0xE0ULL) == 0xE0ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12); - ((PNGU_u64 *) buffer)[blockbase+2] = tmp; - - fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16)); - fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16+8)); - if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4); - - if ((fieldA & 0xE0ULL) == 0xE0ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20); - - if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28); - - if ((fieldB & 0xE0ULL) == 0xE0ULL) - // Opaque pixel, so set MSB to 1 and encode colors in RGB555 - tmp |= 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11); - else - // Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444 - tmp |= ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12); - - ((PNGU_u64 *) buffer)[blockbase+3] = tmp; - } - } - else - { - // No alpha channel present, copy image to the output buffer - default_alpha = (default_alpha >> 5); - if (default_alpha == 7) - { - // The user wants an opaque texture, so set MSB to 1 and encode colors in RGB555 - alphaMask = 0x8000800080008000ULL; - - for (y = 0; y < qheight; y++) - for (x = 0; x < qwidth; x++) - { - int blockbase = (y * qwidth + x) << 2; - - PNGU_u32 y4 = y << 2; - PNGU_u32 x12 = x * 12; - - PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12)); - PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase] = - alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) | - ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) | - ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) | - ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+1] = - alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) | - ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) | - ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) | - ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+2] = - alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) | - ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) | - ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) | - ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+3] = - alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) | - ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) | - ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) | - ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3); - } - } - else - { - // The user wants a translucid texture, so set MSB to 0 and encode colors in ARGB3444 - default_alpha = (default_alpha << 4); - alphaMask = (((PNGU_u64) default_alpha) << 56) | (((PNGU_u64) default_alpha) << 40) | - (((PNGU_u64) default_alpha) << 24) | (((PNGU_u64) default_alpha) << 8); - - for (y = 0; y < qheight; y++) - for (x = 0; x < qwidth; x++) - { - int blockbase = (y * qwidth + x) << 2; - - PNGU_u32 y4 = y << 2; - PNGU_u32 x12 = x * 12; - - PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12)); - PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase] = - alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) | - ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) | - ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) | - ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+1] = - alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) | - ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) | - ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) | - ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+2] = - alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) | - ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) | - ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) | - ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+3] = - alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) | - ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) | - ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) | - ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4); - } - } - } - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha) -{ - int result; - PNGU_u32 x, y, qwidth, qheight; - PNGU_u64 alphaMask; - - // width and height need to be divisible by four - if ((width % 4) || (height % 4)) - return PNGU_INVALID_WIDTH_OR_HEIGHT; - - result = pngu_decode (ctx, width, height, 0); - if (result != PNGU_OK) - return result; - - // Init some variables - qwidth = width >> 2; - qheight = height >> 2; - - // Check is source image has an alpha channel - if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) ) - { - // Alpha channel present, copy image to the output buffer - for (y = 0; y < qheight; y++) - for (x = 0; x < qwidth; x++) - { - int blockbase = (y * qwidth + x) << 3; - - PNGU_u32 y4 = y << 2; - PNGU_u32 x16 = x << 4; - - PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16)); - PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16+8)); - ((PNGU_u64 *) buffer)[blockbase] = - ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) | - ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) | - ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) | - ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24); - ((PNGU_u64 *) buffer)[blockbase+4] = - ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) | - ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8); - - fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16)); - fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16+8)); - ((PNGU_u64 *) buffer)[blockbase+1] = - ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) | - ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) | - ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) | - ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24); - ((PNGU_u64 *) buffer)[blockbase+5] = - ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) | - ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8); - - fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16)); - fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16+8)); - ((PNGU_u64 *) buffer)[blockbase+2] = - ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) | - ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) | - ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) | - ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24); - ((PNGU_u64 *) buffer)[blockbase+6] = - ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) | - ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8); - - fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16)); - fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16+8)); - ((PNGU_u64 *) buffer)[blockbase+3] = - ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) | - ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) | - ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) | - ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24); - ((PNGU_u64 *) buffer)[blockbase+7] = - ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) | - ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8); - } - } - else - { - // No alpha channel present, copy image to the output buffer - alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) | - (((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8); - - for (y = 0; y < qheight; y++) - for (x = 0; x < qwidth; x++) - { - int blockbase = (y * qwidth + x) << 3; - - PNGU_u32 y4 = y << 2; - PNGU_u32 x12 = x * 12; - - PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12)); - PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase] = - (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) | - ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask); - ((PNGU_u64 *) buffer)[blockbase+4] = - (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) | - ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL)); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+1] = - (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) | - ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask); - ((PNGU_u64 *) buffer)[blockbase+5] = - (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) | - ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL)); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+2] = - (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) | - ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask); - ((PNGU_u64 *) buffer)[blockbase+6] = - (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) | - ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL)); - - field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12)); - field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8)); - ((PNGU_u64 *) buffer)[blockbase+3] = - (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) | - ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask); - ((PNGU_u64 *) buffer)[blockbase+7] = - (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) | - ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL)); - } - } - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - // Success - return PNGU_OK; -} - -int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) -{ - png_uint_32 rowbytes; - PNGU_u32 x, y, buffWidth; - - // Erase from the context any readed info - pngu_free_info (ctx); - ctx->propRead = 0; - - // Check if the user has selected a file to write the image - if (ctx->source == PNGU_SOURCE_BUFFER); - - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Open file - if (!(ctx->fd = fopen (ctx->filename, "wb"))) - return PNGU_CANT_OPEN_FILE; - } - - else - return PNGU_NO_FILE_SELECTED; - - // Allocation of libpng structs - ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!(ctx->png_ptr)) + if (ctx->infoRead) { if (ctx->source == PNGU_SOURCE_DEVICE) fclose (ctx->fd); - return PNGU_LIB_ERROR; + + png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL); + + ctx->infoRead = 0; } - - ctx->info_ptr = png_create_info_struct (ctx->png_ptr); - if (!(ctx->info_ptr)) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - if (ctx->source == PNGU_SOURCE_BUFFER) - { - // Installation of our custom data writer function - ctx->cursor = 0; - png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer); - } - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Default data writer uses function fwrite, so it needs to use our FILE* - png_init_io (ctx->png_ptr, ctx->fd); - } - - // Setup output file properties - png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - // Allocate memory to store the image in RGB format - rowbytes = width * 3; - if (rowbytes % 4) - rowbytes = ((rowbytes >> 2) + 1) << 2; - - ctx->img_data = malloc (rowbytes * height); - if (!ctx->img_data) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - ctx->row_pointers = malloc (sizeof (png_bytep) * height); - if (!ctx->row_pointers) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - // Encode YCbYCr image into RGB8 format - buffWidth = (width + stride) >> 1; - PNGU_u32 wid2 = width >> 1; - for (y = 0; y < height; y++) - { - ctx->row_pointers[y] = ctx->img_data + (y * rowbytes); - - for (x = 0; x < wid2; ++x) - { - PNGU_u32 x6 = x*6; - PNGU_YCbYCr_TO_RGB8 ( ((PNGU_u32 *)buffer)[y*buffWidth+x], - ((PNGU_u8 *) ctx->row_pointers[y]+x6), ((PNGU_u8 *) ctx->row_pointers[y]+x6+1), - ((PNGU_u8 *) ctx->row_pointers[y]+x6+2), ((PNGU_u8 *) ctx->row_pointers[y]+x6+3), - ((PNGU_u8 *) ctx->row_pointers[y]+x6+4), ((PNGU_u8 *) ctx->row_pointers[y]+x6+5) ); - } - } - - // Tell libpng where is our image data - png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers); - - // Write file header and image data - png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - // Tell libpng we have no more data to write - png_write_end (ctx->png_ptr, (png_infop) NULL); - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr)); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - - // Success - return PNGU_OK; } -int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) +// Custom data provider function used for reading from memory buffers. +static void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length) { - png_uint_32 rowbytes; - PNGU_u32 y; - - // Erase from the context any readed info - pngu_free_info (ctx); - ctx->propRead = 0; - - // Check if the user has selected a file to write the image - if (ctx->source == PNGU_SOURCE_BUFFER); - - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Open file - if (!(ctx->fd = fopen (ctx->filename, "wb"))) - return PNGU_CANT_OPEN_FILE; - } - - else - return PNGU_NO_FILE_SELECTED; - - // Allocation of libpng structs - ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!(ctx->png_ptr)) - { - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - ctx->info_ptr = png_create_info_struct (ctx->png_ptr); - if (!(ctx->info_ptr)) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - if (ctx->source == PNGU_SOURCE_BUFFER) - { - // Installation of our custom data writer function - ctx->cursor = 0; - png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer); - } - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Default data writer uses function fwrite, so it needs to use our FILE* - png_init_io (ctx->png_ptr, ctx->fd); - } - - // Setup output file properties - png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - // Allocate memory to store the image in RGB format - rowbytes = width * 3; - if (rowbytes % 4) - rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary - - ctx->img_data = malloc(rowbytes * height); - memset(ctx->img_data, 0, rowbytes * height); - - if (!ctx->img_data) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - ctx->row_pointers = malloc (sizeof (png_bytep) * height); - memset(ctx->row_pointers, 0, sizeof (png_bytep) * height); - - if (!ctx->row_pointers) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - for (y = 0; y < height; ++y) - { - ctx->row_pointers[y] = buffer + (y * rowbytes); - } - - // Tell libpng where is our image data - png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers); - - // Write file header and image data - png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - // Tell libpng we have no more data to write - png_write_end (ctx->png_ptr, (png_infop) NULL); - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr)); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - - // Success - return ctx->cursor; + IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); + memcpy (data, ctx->buffer + ctx->cursor, length); + ctx->cursor += length; } -int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) +// Custom data writer function used for writing to memory buffers. +static void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length) { - int res; - PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy; - - unsigned char * ptr = (unsigned char*)buffer; - unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3); - memset(tmpbuffer, 0, width*height*3); - png_uint_32 offset; - - for(y=0; y < height; y++) - { - tmpy1 = y * 640*3; - tmpy2 = y%4 << 2; - tmpyWid = (((y >> 2)<<4)*width); - - for(x=0; x < width; x++) - { - offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1); - tmpxy = x * 3 + tmpy1; - - tmpbuffer[tmpxy ] = ptr[offset+1]; // R - tmpbuffer[tmpxy+1] = ptr[offset+32]; // G - tmpbuffer[tmpxy+2] = ptr[offset+33]; // B - } - } - - res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride); - free(tmpbuffer); - return res; + IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); + memcpy (ctx->buffer + ctx->cursor, data, length); + ctx->cursor += length; } -// This function is taken from a libogc example -PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2) +// Custom data flusher function used for writing to memory buffers. +static void pngu_flush_data_to_buffer (png_structp png_ptr) { - PNGU_u32 y1, cb1, cr1, y2, cb2, cr2, cb, cr; - - y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000; - cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000; - cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000; - - y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000; - cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000; - cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000; - - cb = (cb1 + cb2) >> 1; - cr = (cr1 + cr2) >> 1; - - return (PNGU_u32) ((y1 << 24) | (cb << 16) | (y2 << 8) | cr); + // Nothing to do here } -void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2) -{ - PNGU_u8 *val = (PNGU_u8 *) &ycbycr; - - float val1 = (float)((int)(val[1]) - 128); - float val3 = (float)((int)(val[3]) - 128); - - int r = (int)(1.371f * val3); - int g = (int)(- 0.698f * val3 - 0.336f * val1); - int b = (int)(1.732f * val1); - - *r1 = pngu_clamp (val[0] + r, 0, 255); - *g1 = pngu_clamp (val[0] + g, 0, 255); - *b1 = pngu_clamp (val[0] + b, 0, 255); - - *r2 = pngu_clamp (val[2] + r, 0, 255); - *g2 = pngu_clamp (val[2] + g, 0, 255); - *b2 = pngu_clamp (val[2] + b, 0, 255); -} - - -int pngu_info (IMGCTX ctx) +static int pngu_info (IMGCTX ctx) { png_byte magic[8]; png_uint_32 width; @@ -1190,7 +294,7 @@ int pngu_info (IMGCTX ctx) return PNGU_OK; } -int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha) +static int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha) { png_uint_32 rowbytes; png_uint_32 i, propImgHeight; @@ -1265,53 +369,346 @@ int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlph return PNGU_OK; } - -void pngu_free_info (IMGCTX ctx) +static inline PNGU_u32 coordsRGBA8(PNGU_u32 x, PNGU_u32 y, PNGU_u32 w) { - if (ctx->infoRead) + return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1; +} + +static u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, int * dstWidth, int * dstHeight, int maxWidth, int maxHeight) +{ + PNGU_u8 default_alpha = 255; + u8 *dst; + int x, y, x2, y2, offset; + int xRatio = 0, yRatio = 0; + png_byte *pixel; + + if (pngu_decode (ctx, width, height, 0) != PNGU_OK) + return NULL; + + int newWidth = width; + int newHeight = height; + + if((maxWidth > 0 && width > maxWidth) || (maxHeight > 0 && height > maxHeight)) + { + float ratio = (float)width/(float)height; + + newWidth = maxWidth; + newHeight = maxWidth/ratio; + + if(newHeight > maxHeight) + { + newWidth = maxHeight*ratio; + newHeight = maxHeight; + } + xRatio = (int)((width<<16)/newWidth)+1; + yRatio = (int)((height<<16)/newHeight)+1; + } + + int padWidth = newWidth; + int padHeight = newHeight; + if(padWidth%4) padWidth += (4-padWidth%4); + if(padHeight%4) padHeight += (4-padHeight%4); + + int len = (padWidth * padHeight) << 2; + if(len%32) len += (32-len%32); + + dst = memalign (32, len); + + if(!dst) + return NULL; + + for (y = 0; y < padHeight; y++) + { + for (x = 0; x < padWidth; x++) + { + offset = coordsRGBA8(x, y, padWidth); + + if(y >= newHeight || x >= newWidth) + { + dst[offset] = 0; + dst[offset+1] = 255; + dst[offset+32] = 255; + dst[offset+33] = 255; + } + else + { + if(xRatio > 0) + { + x2 = ((x*xRatio)>>16); + y2 = ((y*yRatio)>>16); + } + + if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA || + ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) + { + if(xRatio > 0) + pixel = &(ctx->row_pointers[y2][x2*4]); + else + pixel = &(ctx->row_pointers[y][x*4]); + + dst[offset] = pixel[3]; // Alpha + dst[offset+1] = pixel[0]; // Red + dst[offset+32] = pixel[1]; // Green + dst[offset+33] = pixel[2]; // Blue + } + else + { + if(xRatio > 0) + pixel = &(ctx->row_pointers[y2][x2*3]); + else + pixel = &(ctx->row_pointers[y][x*3]); + + dst[offset] = default_alpha; // Alpha + dst[offset+1] = pixel[0]; // Red + dst[offset+32] = pixel[1]; // Green + dst[offset+33] = pixel[2]; // Blue + } + } + } + } + + // Free resources + free (ctx->img_data); + free (ctx->row_pointers); + + *dstWidth = padWidth; + *dstHeight = padHeight; + DCFlushRange(dst, len); + return dst; +} + +IMGCTX PNGU_SelectImageFromBuffer (const void *buffer) +{ + IMGCTX ctx = NULL; + + if (!buffer) + return NULL; + + ctx = malloc (sizeof (struct _IMGCTX)); + if (!ctx) + return NULL; + + ctx->buffer = (void *) buffer; + ctx->source = PNGU_SOURCE_BUFFER; + ctx->cursor = 0; + ctx->filename = NULL; + ctx->propRead = 0; + ctx->infoRead = 0; + + return ctx; +} + +IMGCTX PNGU_SelectImageFromDevice (const char *filename) +{ + IMGCTX ctx = NULL; + + if (!filename) + return NULL; + + ctx = malloc (sizeof (struct _IMGCTX)); + if (!ctx) + return NULL; + + ctx->buffer = NULL; + ctx->source = PNGU_SOURCE_DEVICE; + ctx->cursor = 0; + + ctx->filename = malloc (strlen (filename) + 1); + if (!ctx->filename) + { + free (ctx); + return NULL; + } + strcpy(ctx->filename, filename); + + ctx->propRead = 0; + ctx->infoRead = 0; + + return ctx; +} + +void PNGU_ReleaseImageContext (IMGCTX ctx) +{ + if (!ctx) + return; + + if (ctx->filename) + free (ctx->filename); + + if ((ctx->propRead) && (ctx->prop.trans)) + free (ctx->prop.trans); + + pngu_free_info (ctx); + free (ctx); +} + +int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop) +{ + int res; + + if (!ctx->propRead) + { + res = pngu_info (ctx); + if (res != PNGU_OK) + return res; + } + + *imgprop = ctx->prop; + return PNGU_OK; +} + +PNGU_u8 * DecodePNG(const PNGU_u8 *src, int * width, int * height, int maxwidth, int maxheight) +{ + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromBuffer(src); + u8 *dst = NULL; + + if(!ctx) + return NULL; + + if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK) + dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, width, height, maxwidth, maxheight); + + PNGU_ReleaseImageContext (ctx); + return dst; +} + +int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) +{ + png_uint_32 rowbytes; + PNGU_u32 y; + + // Erase from the context any readed info + pngu_free_info (ctx); + ctx->propRead = 0; + + // Check if the user has selected a file to write the image + if (ctx->source == PNGU_SOURCE_BUFFER); + + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Open file + if (!(ctx->fd = fopen (ctx->filename, "wb"))) + return PNGU_CANT_OPEN_FILE; + } + + else + return PNGU_NO_FILE_SELECTED; + + // Allocation of libpng structs + ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!(ctx->png_ptr)) { if (ctx->source == PNGU_SOURCE_DEVICE) fclose (ctx->fd); - - png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL); - - ctx->infoRead = 0; + return PNGU_LIB_ERROR; } + + ctx->info_ptr = png_create_info_struct (ctx->png_ptr); + if (!(ctx->info_ptr)) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + if (ctx->source == PNGU_SOURCE_BUFFER) + { + // Installation of our custom data writer function + ctx->cursor = 0; + png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer); + } + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Default data writer uses function fwrite, so it needs to use our FILE* + png_init_io (ctx->png_ptr, ctx->fd); + } + + // Setup output file properties + png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // Allocate memory to store the image in RGB format + rowbytes = width * 3; + if (rowbytes % 4) + rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary + + ctx->img_data = malloc(rowbytes * height); + memset(ctx->img_data, 0, rowbytes * height); + + if (!ctx->img_data) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + ctx->row_pointers = malloc (sizeof (png_bytep) * height); + memset(ctx->row_pointers, 0, sizeof (png_bytep) * height); + + if (!ctx->row_pointers) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + for (y = 0; y < height; ++y) + { + ctx->row_pointers[y] = buffer + (y * rowbytes); + } + + // Tell libpng where is our image data + png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers); + + // Write file header and image data + png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + // Tell libpng we have no more data to write + png_write_end (ctx->png_ptr, (png_infop) NULL); + + // Free resources + free (ctx->img_data); + free (ctx->row_pointers); + png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr)); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + + // Success + return ctx->cursor; } - -// Custom data provider function used for reading from memory buffers. -void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length) +int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride) { - IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); - memcpy (data, ctx->buffer + ctx->cursor, length); - ctx->cursor += length; -} - - -// Custom data writer function used for writing to memory buffers. -void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length) -{ - IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); - memcpy (ctx->buffer + ctx->cursor, data, length); - ctx->cursor += length; -} - - -// Custom data flusher function used for writing to memory buffers. -void pngu_flush_data_to_buffer (png_structp png_ptr) -{ - // Nothing to do here -} - - -// Function used in YCbYCr to RGB decoding -int pngu_clamp (int value, int min, int max) -{ - if (value < min) - value = min; - else if (value > max) - value = max; - - return value; + int res; + PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy; + + unsigned char * ptr = (unsigned char*)buffer; + unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3); + memset(tmpbuffer, 0, width*height*3); + png_uint_32 offset; + + for(y=0; y < height; y++) + { + tmpy1 = y * 640*3; + tmpy2 = y%4 << 2; + tmpyWid = (((y >> 2)<<4)*width); + + for(x=0; x < width; x++) + { + offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1); + tmpxy = x * 3 + tmpy1; + + tmpbuffer[tmpxy ] = ptr[offset+1]; // R + tmpbuffer[tmpxy+1] = ptr[offset+32]; // G + tmpbuffer[tmpxy+2] = ptr[offset+33]; // B + } + } + + res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride); + free(tmpbuffer); + return res; } diff --git a/src/platform/wii/pngu.h b/src/platform/wii/pngu.h index 064cd80..8024b96 100644 --- a/src/platform/wii/pngu.h +++ b/src/platform/wii/pngu.h @@ -1,38 +1,15 @@ /******************************************************************************************** - -PNGU Version : 0.2a - -Coder : frontier - -More info : http://frontier-dev.net - -Modified by Tantric, 2009 - +* +* PNGU +* +* Original author: frontier (http://frontier-dev.net) +* Modified by Tantric, 2009-2010 +* ********************************************************************************************/ + #ifndef __PNGU__ #define __PNGU__ -// Return codes -#define PNGU_OK 0 -#define PNGU_ODD_WIDTH 1 -#define PNGU_ODD_STRIDE 2 -#define PNGU_INVALID_WIDTH_OR_HEIGHT 3 -#define PNGU_FILE_IS_NOT_PNG 4 -#define PNGU_UNSUPPORTED_COLOR_TYPE 5 -#define PNGU_NO_FILE_SELECTED 6 -#define PNGU_CANT_OPEN_FILE 7 -#define PNGU_CANT_READ_FILE 8 -#define PNGU_LIB_ERROR 9 - -// Color types -#define PNGU_COLOR_TYPE_GRAY 1 -#define PNGU_COLOR_TYPE_GRAY_ALPHA 2 -#define PNGU_COLOR_TYPE_PALETTE 3 -#define PNGU_COLOR_TYPE_RGB 4 -#define PNGU_COLOR_TYPE_RGB_ALPHA 5 -#define PNGU_COLOR_TYPE_UNKNOWN 6 - - #ifdef __cplusplus extern "C" { #endif @@ -66,28 +43,8 @@ typedef struct struct _IMGCTX; typedef struct _IMGCTX *IMGCTX; - /**************************************************************************** -* Pixel conversion * -****************************************************************************/ - -// Macro to convert RGB8 values to RGB565 -#define PNGU_RGB8_TO_RGB565(r,g,b) ( ((((PNGU_u16) r) & 0xF8U) << 8) | ((((PNGU_u16) g) & 0xFCU) << 3) | (((PNGU_u16) b) >> 3) ) - -// Macro to convert RGBA8 values to RGB5A3 -#define PNGU_RGB8_TO_RGB5A3(r,g,b,a) (PNGU_u16) (((a & 0xE0U) == 0xE0U) ? \ - (0x8000U | ((((PNGU_u16) r) & 0xF8U) << 7) | ((((PNGU_u16) g) & 0xF8U) << 2) | (((PNGU_u16) b) >> 3)) : \ - (((((PNGU_u16) a) & 0xE0U) << 7) | ((((PNGU_u16) r) & 0xF0U) << 4) | (((PNGU_u16) g) & 0xF0U) | ((((PNGU_u16) b) & 0xF0U) >> 4))) - -// Function to convert two RGB8 values to YCbYCr -PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2); - -// Function to convert an YCbYCr to two RGB8 values. -void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2); - - -/**************************************************************************** -* Image context handling * +* Image context handling * ****************************************************************************/ // Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing. @@ -99,78 +56,23 @@ IMGCTX PNGU_SelectImageFromDevice (const char *filename); // Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX. void PNGU_ReleaseImageContext (IMGCTX ctx); - /**************************************************************************** -* Miscelaneous * +* Miscellaneous * ****************************************************************************/ // Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors. int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties); - /**************************************************************************** -* Image conversion * +* Image conversion * ****************************************************************************/ -// Expands selected image into an YCbYCr buffer. You need to specify context, image dimensions, -// destination address and stride in pixels (stride = buffer width - image width). -int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride); - -// Macro for decoding an image inside a buffer at given coordinates. -#define PNGU_DECODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \ - \ - PNGU_DecodeToYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \ - (coordX) * 2, (bufferWidth) - (imgWidth)) - -// Expands selected image into a linear RGB565 buffer. You need to specify context, image dimensions, -// destination address and stride in pixels (stride = buffer width - image width). -int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride); - -// Macro for decoding an image inside a buffer at given coordinates. -#define PNGU_DECODE_TO_COORDS_RGB565(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \ - \ - PNGU_DecodeToRGB565 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \ - (coordX) * 2, (bufferWidth) - (imgWidth)) - -// Expands selected image into a linear RGBA8 buffer. You need to specify context, image dimensions, -// destination address, stride in pixels and default alpha value, which is used if the source image -// doesn't have an alpha channel. -int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha); - -// Macro for decoding an image inside a buffer at given coordinates. -#define PNGU_DECODE_TO_COORDS_RGBA8(ctx,coordX,coordY,imgWidth,imgHeight,default_alpha,bufferWidth,bufferHeight,buffer) \ - \ - PNGU_DecodeToRGBA8 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \ - (coordX) * 2, (bufferWidth) - (imgWidth), default_alpha) - -// Expands selected image into a 4x4 tiled RGB565 buffer. You need to specify context, image dimensions -// and destination address. -int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer); - -// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions, -// destination address and default alpha value, which is used if the source image doesn't have an alpha channel. -int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha); - -// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions, -// destination address and default alpha value, which is used if the source image doesn't have an alpha channel. -int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha); - -// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to -// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width). -int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride); - +PNGU_u8 * DecodePNG(const PNGU_u8 *src, int *width, int *height, int maxwidth, int maxheight); int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride); int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride); -// Macro for encoding an image stored into an YCbYCr buffer at given coordinates. -#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \ - \ - PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \ - (coordX) * 2, (bufferWidth) - (imgWidth)) - #ifdef __cplusplus } #endif #endif - diff --git a/src/platform/wii/wiihardware.cpp b/src/platform/wii/wiihardware.cpp index 2feed71..05bc271 100644 --- a/src/platform/wii/wiihardware.cpp +++ b/src/platform/wii/wiihardware.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii - * Tantric 2009 + * Tantric 2009-2010 ***************************************************************************/ #include @@ -111,14 +111,19 @@ static void * PressKeys (void *arg) MAPPER_CheckEvent(&event); usleep(600); } + + // hack to allow mappings of SDL keys > 127 + int keyoffset = 0; + if(dosboxCommand[i] >= 14 && dosboxCommand[i] <= 25) + keyoffset = 268; // F1-F12 (282-293) event.type = SDL_KEYDOWN; - event.key.keysym.sym = (SDLKey)dosboxCommand[i]; + event.key.keysym.sym = (SDLKey)((int)dosboxCommand[i]+keyoffset); MAPPER_CheckEvent(&event); usleep(600); event.type = SDL_KEYUP; - event.key.keysym.sym = (SDLKey)dosboxCommand[i]; + event.key.keysym.sym = (SDLKey)((int)dosboxCommand[i]+keyoffset); MAPPER_CheckEvent(&event); usleep(600); @@ -130,17 +135,6 @@ static void * PressKeys (void *arg) usleep(600); } } - - event.type = SDL_KEYDOWN; - event.key.keysym.sym = SDLK_RETURN; - MAPPER_CheckEvent(&event); - usleep(600); - - event.type = SDL_KEYUP; - event.key.keysym.sym = SDLK_RETURN; - MAPPER_CheckEvent(&event); - usleep(600); - dosboxCommand[0] = 0; } return NULL; diff --git a/src/platform/wii/wiihardware.h b/src/platform/wii/wiihardware.h index 736147d..c2c88d6 100644 --- a/src/platform/wii/wiihardware.h +++ b/src/platform/wii/wiihardware.h @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii - * Tantric 2009 + * Tantric 2009-2010 ***************************************************************************/ #ifndef WIIHARDWARE_H diff --git a/src/platform/wii/wiivideo.cpp b/src/platform/wii/wiivideo.cpp index 0113f6d..8975402 100644 --- a/src/platform/wii/wiivideo.cpp +++ b/src/platform/wii/wiivideo.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii Home Menu - * Tantric 2009 + * Tantric 2009-2010 * * video.cpp * diff --git a/src/platform/wii/wiivideo.h b/src/platform/wii/wiivideo.h index cc96c5c..bfef6a4 100644 --- a/src/platform/wii/wiivideo.h +++ b/src/platform/wii/wiivideo.h @@ -1,6 +1,6 @@ /**************************************************************************** * DOSBox Wii Home Menu - * Tantric 2009 + * Tantric 2009-2010 * * wiivideo.h * diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index ec67763..1fe2c16 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -305,6 +305,7 @@ void DOS_Shell::Run(void) { WriteOut(MSG_Get("SHELL_STARTUP_DEBUG")); #endif if (machine == MCH_CGA) WriteOut(MSG_Get("SHELL_STARTUP_CGA")); + if (machine == MCH_HERC) WriteOut(MSG_Get("SHELL_STARTUP_HERC")); WriteOut(MSG_Get("SHELL_STARTUP_END")); if (cmd->FindString("/INIT",line,true)) { @@ -503,7 +504,7 @@ void SHELL_Init() { "| For a short introduction for new users type: \033[33mINTRO\033[37m |\n" "| For supported shell commands type: \033[33mHELP\033[37m |\n" "| |\n" - "| If you want more speed, try \033[31mctrl-F8\033[37m and \033[31mctrl-F12\033[37m. |\n" + "| To adjust the emulated CPU speed, use \033[31mctrl-F11\033[37m and \033[31mctrl-F12\033[37m. |\n" "| To activate the keymapper \033[31mctrl-F1\033[37m. |\n" "| For more information read the \033[36mREADME\033[37m file in the DOSBox directory. |\n" "| |\n" @@ -512,6 +513,9 @@ void SHELL_Init() { "| Use \033[31m(alt-)F11\033[37m to change the colours when in this mode. |\n" "| |\n" ); + MSG_Add("SHELL_STARTUP_HERC","\xBA Use \033[31mF11\033[37m to cycle through white, amber, and green monochrome color. \xBA\n" + "\xBA \xBA\n" + ); MSG_Add("SHELL_STARTUP_DEBUG", "| Press \033[31malt-Pause\033[37m to enter the debugger or start the exe with \033[33mDEBUG\033[37m. |\n" "| |\n" @@ -535,7 +539,7 @@ void SHELL_Init() { "\xBA For a short introduction for new users type: \033[33mINTRO\033[37m \xBA\n" "\xBA For supported shell commands type: \033[33mHELP\033[37m \xBA\n" "\xBA \xBA\n" - "\xBA If you want more speed, try \033[31mctrl-F8\033[37m and \033[31mctrl-F12\033[37m. \xBA\n" + "\xBA To adjust the emulated CPU speed, use \033[31mctrl-F11\033[37m and \033[31mctrl-F12\033[37m. \xBA\n" "\xBA To activate the keymapper \033[31mctrl-F1\033[37m. \xBA\n" "\xBA For more information read the \033[36mREADME\033[37m file in the DOSBox directory. \xBA\n" "\xBA \xBA\n" @@ -544,6 +548,9 @@ void SHELL_Init() { "\xBA Use \033[31m(alt-)F11\033[37m to change the colours when in this mode. \xBA\n" "\xBA \xBA\n" ); + MSG_Add("SHELL_STARTUP_HERC","\xBA Use \033[31mF11\033[37m to cycle through white, amber, and green monochrome color. \xBA\n" + "\xBA \xBA\n" + ); MSG_Add("SHELL_STARTUP_DEBUG", "\xBA Press \033[31malt-Pause\033[37m to enter the debugger or start the exe with \033[33mDEBUG\033[37m. \xBA\n" "\xBA \xBA\n" diff --git a/src/winres.rc b/src/winres.rc index 4a071af..f7e63b4 100644 --- a/src/winres.rc +++ b/src/winres.rc @@ -7,8 +7,8 @@ dosbox_ico ICON "dosbox.ico" // version resource VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,73,0,0 - PRODUCTVERSION 0,73,0,0 + FILEVERSION 0,74,0,0 + PRODUCTVERSION 0,74,0,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -19,15 +19,15 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "Comments", "© 2002-2009 DOSBox Team, published under GNU GPL" + VALUE "Comments", "© 2002-2010 DOSBox Team, published under GNU GPL" VALUE "CompanyName", "DOSBox Team" VALUE "FileDescription", "DOSBox DOS Emulator" - VALUE "FileVersion", "0, 73, 0, 0" + VALUE "FileVersion", "0, 74, 0, 0" VALUE "InternalName", "DOSBox" - VALUE "LegalCopyright", "Copyright © 2002-2009 DOSBox Team" + VALUE "LegalCopyright", "Copyright © 2002-2010 DOSBox Team" VALUE "OriginalFilename", "dosbox.exe" VALUE "ProductName", "DOSBox DOS Emulator" - VALUE "ProductVersion", "0, 73, 0, 0" + VALUE "ProductVersion", "0, 74, 0, 0" END END BLOCK "VarFileInfo"